title 'SBC86/12 w/ SBC204 Bootstrap EPROM' ; ; ROM bootstrap for CP/M-86 on an iSBC86/12 ; with the ; Intel SBC 204 Floppy Disk Controller ; ; Copyright (C) 1980,1981 ; Digital Research, Inc. ; Box 579, Pacific Grove ; California, 93950 ; ;******************************************** ;* This is the BOOT ROM which is initiated * ;* by a system reset. First, the ROM moves * ;* a copy of its data area to RAM at loca- * ;* tion 00000H, then initializes the segment* ;* registers and the stack pointer. The * ;* various peripheral interface chips on the* ;* SBC 86/12 are initialized. The 8251 * ;* serial interface is configured for a 9600* ;* baud asynchronous terminal, and the in- * ;* terrupt controller is setup for inter- * ;* rupts 10H-17H (vectors at 00040H-0005FH) * ;* and edge-triggered auto-EOI (end of in- * ;* terrupt) mode with all interrupt levels * ;* masked-off. Next, the SBC 204 Diskette * ;* controller is initialized, and track 1 * ;* sector 1 is read to determine the target * ;* paragraph address for LOADER. Finally, * ;* the LOADER on track 0 sectors 2-26 and * ;* track 1 sectors 1-26 is read into the * ;* target address. Control then transfers * ;* to LOADER. This program resides in two * ;* 2716 EPROM's (2K each) at location * ;* 0FF000H on the SBC 86/12 CPU board. ROM * ;* 0 contains the even memory locations, and* ;* ROM 1 contains the odd addresses. BOOT * ;* ROM uses RAM between 00000H and 000FFH * ;* (absolute) for a scratch area, along with* ;* the sector 1 buffer. * ;******************************************** true equ 0ffh false equ not true ; debug equ true ;debug = true indicates bootstrap is in same roms ;with SBC 957 "Execution Vehicle" monitor ;at FE00:0 instead of FF00:0 ; cr equ 13 lf equ 10 ; ; disk ports and commands ; base204 equ 0a0h fdccom equ base204+0 fdcstat equ base204+0 fdcparm equ base204+1 fdcrslt equ base204+1 fdcrst equ base204+2 dmacadr equ base204+4 dmaccont equ base204+5 dmacscan equ base204+6 dmacsadr equ base204+7 dmacmode equ base204+8 dmacstat equ base204+8 fdcsel equ base204+9 fdcsegment equ base204+10 reset204 equ base204+15 ; ;actual console baud rate baud_rate equ 9600 ;value for 8253 baud counter baud equ 768/(baud_rate/100) ; csts equ 0DAh ;i8251 status port cdata equ 0D8h ; " data port ; tch0 equ 0D0h ;8253 PIC channel 0 port tch1 equ tch0+2 ;ch 1 port tch2 equ tch0+4 ;ch 2 port tcmd equ tch0+6 ;8253 command port ; icp1 equ 0C0h ;8259a port 0 icp2 equ 0C2h ;8259a port 1 ; ; IF NOT DEBUG ROMSEG EQU 0FF00H ;normal ENDIF ; IF DEBUG ;share prom with SBC 957 ROMSEG EQU 0FE00H ENDIF ; ; ; This long jump prom'd in by hand ; cseg 0ffffh ;reset goes to here (ffff0h) ; JMPF BOTTOM ;boot is at bottom of PROM ; EA 00 00 00 FF ;cs = bottom of prom (ff000h) ; ip = 0 ; EVEN PROM ODD PROM ; 7F8 - EA 7F8 - 00 ; 7F9 - 00 7F9 - 00 ; 7FA - FF ;this is not done if special = true ; cseg romseg ; ;First, move our data area into RAM at 0000:0200 ; mov ax,cs mov ds,ax ;point DS to CS for source mov SI,drombegin ;start of data mov DI,offset ram_start ;offset of destination mov ax,0 mov es,ax ;destination segment is 0000 mov CX,data_length ;how much to move in bytes rep movs al,al ;move out of eprom a byte at a time ; mov ax,0 mov ds,ax ;data segment now in RAM mov ss,ax mov sp,stack_offset ;Initialize stack segment/pointer cld ;clear the direction flag ; IF NOT DEBUG ; ;Now, initialize the console USART and baud rate ; mov al,0Eh out csts,al ;give 8251 dummy mode mov al,40h out csts,al ;reset 8251 to accept mode mov al,4Eh out csts,al ;normal 8 bit asynch mode, * 16 mov al,37h out csts,al ;enable Tx & Rx mov al,0B6h out tcmd,al ;8253 ch.2 square wave mode mov ax,baud out tch2,al ;low of the baud rate mov al,ah out tch2,al ;high of the baud rate ; ENDIF ; ;Setup the 8259 Programmable Interrupt Controller ; mov al,13h out icp1,al ;8259a ICW 1 8086 mode mov al,10h out icp2,al ;8259a ICW 2 vector @ 40-5F mov al,1Fh out icp2,al ;8259a ICW 4 auto EOI master mov al,0FFh out icp2,al ;8259a OCW 1 mask all levels off ; ;Reset and initialize the iSBC 204 Diskette Interface ; restart: ;also come back here on fatal errors out reset204,AL ;reset iSBC 204 logic and mov AL,1 out fdcrst,AL ;give 8271 FDC mov al,0 out fdcrst,AL ; a reset command mov BX,offset specs1 CALL sendcom ;program mov BX,offset specs2 CALL sendcom ; Shugart SA-800 drive mov BX,offset specs3 call sendcom ; characteristics homer: mov BX,offset home CALL execute ;home drive 0 ; mov bx,sector1 ;offset for first sector DMA mov ax,0 mov es,ax ;segment " " " " call setup_dma ; mov bx,offset read0 call execute ;get T0 S1 ; mov es,ABS mov bx,0 ;get loader load address call setup_dma ;setup DMA to read loader ; mov bx,offset read1 call execute ;read track 0 mov bx,offset read2 call execute ;read track 1 ; mov leap_segment,ES ; setup far jump vector mov leap_offset,0 ; ; enter LOADER jmpf dword ptr leap_offset ; pmsg: mov cl,[BX] test cl,cl jz return call conout inc BX jmp pmsg ; conout: in al,csts test al,1 jz conout mov al,cl out cdata,al ret ; conin: in al,csts test al,2 jz conin in al,cdata and al,7Fh ret ; ; ; execute: ;execute command string @ [BX] ; points to length, ;followed by Command byte ;followed by length-1 parameter bytes ; mov lastcom,BX ;remember what it was retry: ;retry if not ready drive call sendcom ;execute the command ;now, let's see what type ;of status poll was necessary ;for that command type . . . mov BX,lastcom ;point to command string mov AL,1[BX] ;get command op code and AL,3fh ;drop drive code bits mov CX,0800h ;mask if it will be "int req" cmp AL,2ch ;see if interrupt type jb execpoll mov CX,8080h ;else we use "not command busy" and AL,0fh ;unless . . . cmp AL,0ch ;there isn't mov AL,0 ja return ;any result at all ; execpoll: ;poll for bit in b, toggled with c in AL,FDCSTAT and AL,CH xor AL,CL ! JZ execpoll ; in AL,fdcrslt ;get result register and AL,1eh ;look only at result type & code jz return ;zero means it was a good operation ; cmp al,10h jne fatal ;if other than "Not Ready", stop ; mov bx,offset rdstat call sendcom ;perform read status command rd_poll: in al,fdc_stat test al,80h ;wait for command not busy jnz rd_poll mov bx,last_com ;recover last attempted command jmp retry ;and try it over again ; fatal: ; fatal error mov ah,0 mov bx,ax ;make 16 bits mov bx,errtbl[BX] ; print appropriate error message call pmsg call conin ;wait for key strike pop ax ;discard unused item jmp restart ;then start all over ; return: RET ;return from EXECUTE ; setupdma: mov AL,04h out dmacmode,AL ;enable dmac mov al,0 out dmaccont,AL ;set first (dummy) byte to mov AL,40h out dmaccont,AL ;force read data mode mov AX,ES out fdcsegment,AL mov AL,AH out fdcsegment,AL mov AX,BX out dmacadr,AL mov AL,AH out dmacadr,AL RET ; ; ; sendcom: ;routine to send a command string to SBC204 in AL,fdcstat and AL,80h jnz sendcom ;insure command not busy mov CL,[BX] ;get count inc BX mov al,[BX] ;point to and fetch command byte out fdccom,AL ;send command parmloop: dec CL jz return ;see if any (more) parameters inc BX ;point to next parameter parmpoll: in AL,fdcstat and AL,20h jnz parmpoll ;loop until parm not full mov AL,[BX] out fdcparm,AL ;output next parameter jmp parmloop ;go see about another ; ; ; Image of data to be moved to RAM ; drombegin equ offset $ ; clastcom dw 0000h ;last command ; creadstring db 3 ;length db 52h ;read function code for drive 0 db 0 ;track # db 1 ;sector # ; creadtrk0 db 4 db 53h ;read multiple db 0 ;track 0 db 2 ;sectors 2 db 25 ;through 26 ; creadtrk1 db 4 db 53h db 1 ;track 1 db 1 ;sectors 1 db 26 ;through 26 ; chome0 db 2,69h,0 crdstat0 db 1,6ch cspecs1 db 5,35h,0dh db 08h,08h,0e9h cspecs2 db 5,35h,10h db 255,255,255 cspecs3 db 5,35h,18h db 255,255,255 ; cerrtbl dw offset er0 dw offset er1 dw offset er2 dw offset er3 dw offset er4 dw offset er5 dw offset er6 dw offset er7 dw offset er8 dw offset er9 dw offset erA dw offset erB dw offset erC dw offset erD dw offset erE dw offset erF ; Cer0 db cr,lf,'Null Error ??',0 Cer1 equ cer0 Cer2 equ cer0 Cer3 equ cer0 Cer4 db cr,lf,'Clock Error',0 Cer5 db cr,lf,'Late DMA',0 Cer6 db cr,lf,'ID CRC Error',0 Cer7 db cr,lf,'Data CRC Error',0 Cer8 db cr,lf,'Drive Not Ready',0 Cer9 db cr,lf,'Write Protect',0 CerA db cr,lf,'Trk 00 Not Found',0 CerB db cr,lf,'Write Fault',0 CerC db cr,lf,'Sector Not Found',0 CerD equ cer0 CerE equ cer0 CerF equ cer0 ; dromend equ offset $ ; data_length equ dromend-drombegin ; ; reserve space in RAM for data area ; (no hex records generated here) ; dseg 0 org 0200h ; ram_start equ $ lastcom rw 1 ;last command read0 rb 4 ;read track 0 sector 1 read1 rb 5 ;read T0 S2-26 read2 rb 5 ;read T1 S1-26 home rb 3 ;home drive 0 rdstat rb 2 ;read status specs1 rb 6 specs2 rb 6 specs3 rb 6 errtbl rw 16 er0 rb length cer0 ;16 er1 equ er0 er2 equ er0 er3 equ er0 er4 rb length cer4 ;14 er5 rb length cer5 ;11 er6 rb length cer6 ;15 er7 rb length cer7 ;17 er8 rb length cer8 ;18 er9 rb length cer9 ;16 erA rb length cerA ;19 erB rb length cerB ;14 erC rb length cerC ;19 erD equ er0 erE equ er0 erF equ er0 ; leap_offset rw 1 leap_segment rw 1 ; ; rw 32 ;local stack stack_offset equ offset $;stack from here down ; ; T0 S1 read in here sector1 equ offset $ ; Ty rb 1 Len rw 1 Abs rw 1 ;ABS is all we care about Min rw 1 Max rw 1 end