; LAST UPDATED: 15 JUN 83 ; REASON FOR UPDATE: Reorganized structure of BOOT and BIOS routines so that ; a portion of the cold boot initialization takes place in the ; boot loader. This facilitates modification of Input/Output ; initialization by placing the most common tables in a smaller ; program and at fixed locations. aep ; ; PROGRAM NAME: xxxFBOOT.ASM, where "xxx" identifies the relationship ; of the revision level to it's corresponding BIOS source. ; ; PURPOSE: Floppy Disk (either 8 inch or 5 1/4 inch drives) boot loader ; for CP/M or MP/M. ; ; ========================== Copyright 1982, CompuPro Corporation, ; || || A division of Godbout Electronics. ; || FLOPPY BOOT LOADER || Oakland Airport, Oakland, CA ; || || ; ========================== ; ; This product is a copyright program product of CompuPro and is ; supplied for use with the CompuPro Disk controllers. ; ; LIBRARY CONSTANTS: MACLIB COMPUPRO ;Disk and Serial/Parallel interface constants MACLIB ACTIVE ;Flags directing construction for the various ; ; EQUATED CONSTANTS: ; if BOOT5X ;If 5 1/4 inch drive used during cold boot FDPORT EQU FD5PORT ;Normal controller port is 5 1/4 inch FDXPORT EQU FD8PORT ;Auxiliary controller port is 8 inch else FDPORT EQU FD8PORT ;Defaults to using 8 inch controller to boot FDXPORT EQU FD5PORT ;Auxiliary controller port is 5 1/4 inch endif ; ; PROGRAM: ASEG ORG 100h ;Base address of bootstrap load ; ;******************************************************** ;* CHARACTER INPUT / OUTPUT INITIALIZATION * ;******************************************************** ; ;Entry: C = Board switches from ROM (0 .. 3) ; START: LXI SP,100h ;Initialize top of stack MOV A,C ;Save board options (boot switch selected) STA BOOTSW ;In CBIOS reserved area at low memory ADD A ;Get Boot Switch value times 2 LXI H,BIOTBL ;Add to I/O vector initialization table ADD L! MOV L,A ;To get offset entry from it MOV A,M! STA IOBYTE ;Set I/O BYTE as in table INX H ;Set I/O Control as well MOV A,M! STA IOCNTL ; ; This routine performs the initialization required by the system ; Input/Output support chips (UARTs). ; IOINIT: LXI H,INISEQ ;Point to initialization sequence string IOINIT1:MOV A,M! INX H ;Get the port to xmit to, point to next value STA INIPORT+1 ;Store in code sequence for transmission INR A ;See if highest address port JZ IOINIT2 ;Clear console input ports if so MOV A,M! INX H ;Get value to xmit in "A", point to next value INIPORT:OUT 0 ;Send data to correct port JMP IOINIT1 ;Loop until all ports initialized ; IOINIT2:IN SS1UD ;Flush System Support I UART of any input data IN IF3UD ;as well as USER 7 on the Interfacer 3 or 4 ; ;************************************************ ;* BOOTSTRAP LOAD FROM FLOPPY DISK * ;************************************************ ; ; Load Specify Command for boot controller (usually 8 inch) floppy drives. SPECIFY:LXI H,SPEC ;Start of specification table MVI B,3 ;3 Byte length in "B" CALL PUTDATA ;Put specification in boot controller ; ; Load Specify Command for auxiliary drive controller. ; (does nothing if other DISK 1 is absent) MVI B,3 ;3 Byte length in "B" SPEC2: IN FDXPORT+FDCS ;See if ready to accept next byte ORA A JP SPEC2 ;Wait if not ready MOV A,M ;Load command byte OUT FDXPORT+FDCD ;to controller command port INX H ;Point to next byte DCR B ;Bump count until all loaded JNZ SPEC2 ;Loop if more to do ; ; The drive is already known to be positioned on track 0 (done to load this ; routine), and therefore a seek is not necessary. The routine will loop on ; error back to this point. ; RETRY: LXI H,DATA ;DMA data pointer CALL READ$DISK ;Read in remainder of track at CBIOS position JNZ RETRY ;Loop on error to re-issue command CALL READ$DISK ;Re-read sector 2 into the 8088's highest RAM JNZ RETRY ;Loop on error to re-issue both read commands LHLD ENTRY ;Get CBIOS entry address (cold boot vector) MOV D,H ;Exchange bytes to correct for reverse order MOV H,L MOV L,D PCHL ;Enter CBIOS by direct vector in "H,L" ; PAGE ;**************************************************************** ;* LOAD DMA REGISTERS AND EXECUTE FLOPPY READ COMMAND * ;**************************************************************** ; READ$DISK: ; Output beginning DMA address. MVI B,3 ;3 Bytes of DMA data ADDR: MOV A,M ;Get byte of extended address OUT FDPORT+FDMA ;Send to DMA port of DISK 1 INX H ;Next byte to xfer DCR B ;Bump count JNZ ADDR ;Loop until all 3 bytes loaded ; ; Read the remainder of track 0 in as the CBIOS to execute the cold boot. MVI B,9 ;Load "B" with command length (9 Bytes) CALL PUTDATA ;Wait until controller ready to accept data READ1: IN FDPORT+INTS ;See if interrupt active (command complete) ORA A JP READ1 ;Loop until so CALL GETDATA ;Get a result status byte from controller XRI 40h ;Test for "abnormal ending" status bit only MOV E,A ;Put result in "E" CALL GETDATA ;Get second result status byte from controller XRI FD$EOC ;Flip status of "End Of Cylinder" bit MOV D,A ;Put result in "D" MVI B,7-2 ;Count of remaining status bytes (ignored) READ2: CALL GETDATA ;Get next result status byte from controller DCR B ;Bump remaining count JNZ READ2 ;Wait until all done MOV A,E! ORA D ;Combine the two significant status bytes RET ;Return with zero if successful read operation ; ; ; Routine to load controller with command and data bytes. PUTDATA:IN FDPORT+FDCS ;Get controller status ORA A JP PUTDATA ;Wait until controller ready for another byte MOV A,M ;load command byte OUT FDPORT+FDCD ; to controller INX H ;Point to next byte to load DCR B ;Bump command load count JNZ PUTDATA ;Loop if more bytes to load RET ;Return if all data loaded in controller ; ; Routine to get a command result status byte from controller. GETDATA:IN FDPORT+FDCS ;See if ready to read status ORA A JP GETDATA ;Wait if not IN FDPORT+FDCD ;Get resulting status of read operation RET ; PAGE ;************************************************ ;* FIXED STORAGE FOR DISK SPECIFICATIONS * ;************************************************ SPEC: ; FLOPPY Specification sequences (loaded only once). if BOOT5X DB FD$SPEC ;5 1/4 inch drive specifications DB (SRT5 SHL 4) + HUT5 DB HDLT5 SHL 1 DB FD$SPEC ;8 inch drive specifications DB (SRT8 SHL 4) + HUT8 DB HDLT8 SHL 1 else DB FD$SPEC ;8 inch drive specifications DB (SRT8 SHL 4) + HUT8 DB HDLT8 SHL 1 DB FD$SPEC ;5 1/4 inch drive specifications DB (SRT5 SHL 4) + HUT5 DB HDLT5 SHL 1 endif ; ;************************************************ ;* FIXED STORAGE FOR DISK READ OPERATIONS * ;************************************************ ; ; Function data for controller to boot. DATA: DB 0 ;Extended Address ENTRY: DB high BIOS ;Base address of CBIOS DB low BIOS READ: DB FD$RDAT ;Read sector(s) command for 8272 controller DB 0 ;Head select, Drive select = 0 DB 0 ;Cylinder #0 DB 0 ;Head #0 DB 3 ;Starting Record (sector) DB 0 ;"N" parameter (128 byte sectors) DB 26 ;Read to end of track DB 7 ;GPL (Gap length) DB 128 ;DTL (Data length) ; ; Re-read this sector into the memory at 0FFF80h to place the 8088 code for ; a long jump back to 400h, the default run address of the GO86 prom. ; READ88: DB 00Fh,0FFh,080h ;3 bytes of the DMA to setup for 8088 DB FD$RDAT ;Read sector(s) command for 8272 controller DB 0 ;Head select, Drive select = 0 DB 0 ;Cylinder #0 DB 0 ;Head #0 DB 2 ;Starting Record (sector) DB 0 ;"N" parameter (128 byte sectors) DB 2 ;Read just a single sector DB 7 ;GPL (Gap length) DB 128 ;DTL (Data length) ; PAGE ;**************************************************************** ;* INPUT/OUTPUT DEVICE INITIALIZATION SEQUENCE TABLE * ;**************************************************************** INISEQ: ;Port, Value to transmit sequence until Port = 0FFh. ; ; Interfacer 3,4 UART initialization. DB IF3UX, 4 ;Select Uart 4 DB IF3UM,01011010b ;Async, 16x, 7 bits, odd parity, 1 stop DB IF3UM,01111110b ; 9600 baud DB IF3UC,00100111b ;Trans. on, DTR low, rec. on, no break/ reset, RTS low ; DB IF3UX, 5 ;Select Uart 5 DB IF3UM,01011010b ;Async, 16x, 7 bits, odd parity, 1 stop DB IF3UM,01111110b ; 9600 baud DB IF3UC,00100111b ;Trans. on, DTR low, rec. on, no break/ reset, RTS low ; DB IF3UX, 6 ;Select Uart 6 DB IF3UM,01011110b ;Async, 16x, 8 bits, odd parity, 1 stop DB IF3UM,01111110b ; 9600 baud DB IF3UC,00100111b ;Trans. on, DTR low, rec. on, no break/ reset, RTS low ; DB IF3UX, 7 ;Select Uart 7 DB IF3UM,01011010b ;Async, 16x, 7 bits, odd parity, 1 stop DB IF3UM,01111110b ; 9600 baud DB IF3UC,00100111b ;Trans. on, DTR low, rec. on, no break/ reset, RTS low ; ; System Support I UART initialization. DB SS1UM,01011010b ;Async, 16x, 7 bits, odd parity, 1 stop DB SS1UM,01111111b ;19200 baud DB SS1UC,00100111b ;Xmit on, DTR low, rec. on, no break, run, RTS low ; DB 0FFh ;End of I/O port initialization string ; ;************************************************ ;* STORAGE "LONG JUMP" FOR 8088 * ;************************************************ ORG 1F0h ;Place in the last 16 bytes of last sector DB 0EAh ;Long jump instruction DW 0400h,0000h ;Segment at 0 hex, offset 400h (000400h) DB 90h,90h,90h ;Fill out remainder with 8088 NOP instructions ; PAGE ;******************************************************** ;* INPUT/OUTPUT DEVICE INITIAL SELECT TABLE * ;******************************************************** ; BIOTBL: ;I/O byte (IOBYTE) value, Aux I/O control byte (IOCNTL) value ; Switch = 0 DB 10$00$00$01b ;LST:=LPT:, PUN:=TTY:, RDR:=TTY:, CON:=CRT: DB 01$00$00$10b ;LPT:=Interfacer I UART 1, CRT:=Interfacer I UART 0 ; Switch = 1 DB 10$00$00$01b ;LST:=LPT:, PUN:=TTY:, RDR:=TTY:, CON:=CRT: DB 00$00$01$00b ;LPT:=Interfacer 3 USER 4 xon/xoff, CRT:=USER 0 ; Switch = 2 DB 10$00$00$01b ;LST:=LPT:, PUN:=TTY:, RDR:=TTY:, CON:=CRT: DB 00$00$01$01b ;LPT:=Interfacer 3,4 USER 4, CRT:=System Support I ; Switch = 3 DB 00$00$00$11b ;LST:=TTY:, PUN:=TTY:, RDR:=TTY:, CON:=UC1: DB 00$00$01$01b ;LPT:=Interfacer 3,4 USER 4, CRT:=System Support I ; ; IOBYTE value is the first entry for each switch selection, and -- ; IOCNTL = ww$xx$yy$zzb selects the following: ;(second byte ww xx yy 00 CRT:=Interfacer 3 USER 0. ;of each entry ww xx yy 01 CRT:=System Support I. ;in BIOTBL). ww xx yy 10 CRT:=Interfacer 1,2 UART 0. ; xx yy 11 CRT:=Interfacer 1,2 UART 1 (Custom Routine). ; 00 xx yy -- LPT:=Interfacer 3,4 USER 4. ; 01 xx yy -- LPT:=Interfacer 1,2 UART 1. ; 10 xx yy -- LPT:=Interfacer 1,2 UART 2 (Custom Routine). ; 11 xx yy -- LPT:= " " " " " ; -- xx -- -- Interfacer 3,4 USER 5 list routine select, ; -- -- yy -- Interfacer 3,4 USER 4 list routine select, ;Where xx and/or yy = 00 Straight output, no software protocol. ; 01 XON/XOFF software protocol active. ; 10 ETX/ACK software protocol active. ; And (always): ; UC1:= Interfacer 3,4 USER 7 ; TTY:= Interfacer 3,4 USER 6 ; UL1:= Interfacer 3,4 USER 5 at all times. ; ;<========= If CON:=BAT: then -- ;/==| BAT:= RDR:= Interfacer 3,4 USER 3 when RDR:=UR2: on input. ;\==|__ BAT:= PUN:= " " 3 when PUN:=UP2: on output. ;/==| BAT:= RDR:= Interfacer 3,4 USER 2 when RDR:=UR1: on input. ;\==|__ BAT:= PUN:= " " 2 when PUN:=UP2: on output. ;/==| BAT:= RDR:= Interfacer 3,4 USER 1 when RDR:=PTR: on input. ;\==|__ BAT:= PUN:= " " 1 when PUN:=PTP: on output. ;x /--| BAT:= ----- Interfacer 3,4 USER 0 when RDR:=TTY: on input. ;x \--| BAT:= ----- " " 0 when PUN:=TTY: on output. ; and for reader/punch vectors only -- ;x -- ------ RDR:= Interfacer 3,4 USER 6 when RDR:=TTY: on input. ;x -- ------ PUN:= " " 6 when PUN:=TTY: on output. ; END