; LAST UPDATED: 14 FEB 84 ; REASON FOR UPDATE: Redone to boot up CP/M 86 or MP/M 8-16 w/ a CPU 8085/88 ; llo ; 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 Godbout Company ; || FLOPPY BOOT LOADER || Hayward, CA 94545 ; || || ; ========================== ; ; This product is a copyright program product of CompuPro and is ; supplied for use with the CompuPro Disk controllers. FALSE EQU 0 TRUE EQU not FALSE ; ; ACTIVE CONSTANTS: BOOT8X EQU TRUE ;True to boot off of an 8" disk BOOT5X EQU not BOOT8X ;True to boot from a 5.25" disk ; STEPR8 EQU 3 ;Drive step rate in milliseconds ULOAD8 EQU 240 ;Drive Head unload time HDLT8 EQU 35 ;Drive Head load time ; STEPR5 EQU 3 ;Drive step rate in milliseconds ULOAD5 EQU 240 ;Drive Head unload time HDLT5 EQU 15 ;Drive Head load time ; SRT8 EQU 16-STEPR8 ;15 count max allowed HUT8 EQU ULOAD8/16 ; SRT5 EQU (33-STEPR5)/2 ;15 count max allowed HUT5 EQU ULOAD5/16 ; ; EQUATEÄ CONSTANTS ; SWAPP EQU 0FDH ;CPU 8085/88 swap port (memory manager) ; FD8PORT EQU 0C0H ;8 inch floppy disk controller base port FD5PORT EQU 0CCH ;5.25 inch floppy disk controller base port FDCS EQU 0 ;Status register offset FDCD EQU 1 ;Data register offset FDMA EQU 2 ;DMA address offset (when written) INTS EQU 2 ;Status register offset (when read) FDON EQU 3 ;Motor on/off control port ; FD$EOC EQU 1000$0000B ; XFER EQU 400H ;Transfer point for the 8088 I$JMPL EQU 0EAH ;Long jump for 8086 WAIT85 EQU 0F940H ;Location where the 8085 should wait in CP/M 8-18 $ MP/M 8-16 IN85 EQU 0DBH ;8085 input instruction ; LDRBIOS EQU 1200H ;Offset into loader for BIOS BOOTSW EQU 40H ; ; 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 endif if BOOT8X FDPORT EQU FD8PORT ;Defaults to using 8 inch controller to boot FDXPORT EQU FD5PORT ;Auxiliary controller port is 5 1/4 inch endif ; ; PROGRAM: 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 ; ;************************************************ ;* 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 ; ; ; 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 LOADER group header (sector 26) JNZ RETRY ;Loop on error to re-issue command PUSH H ;Save FDC command DMA pointer MVI A,I$JMPL ;Put 8086 long jump into transfer point STA XFER ;Save JUMP instruction in memory LXI H,LDRBIOS ;Get offset into loader of bios SHLD XFER+1 ;Save offset in transfer point LHLD BUF+3 ;Get loader segment SHLD XFER+3 ;Save new segment in transfer point LXI B,LDRBIOS/16 ;Get BIOS offset in paragraphs DAD B ;Add BIOS start paragraph to LOADER segment MOV A,L ! ANI 0FH ;Isolate lowest nibble of load address RAR ! RAR ! RAR ! RAR ;Multiply lowest nibble * 16 to get paragraph STA LDRDMA+2 ;Save lowest nibble in read command MOV A,H ! ANI 0F0H ; RAR ! RAR ! RAR ! RAR ;Multiply highest nibble * 16 to get paragraph STA LDRDMA+0 ;Save highest nibble in read command DAD H ! DAD H DAD H ! DAD H ;* 4 MOV A,H ;Get middle byte STA LDRDMA+1 ;Save middle byte in read command POP H ;Recover Command DMA pointer CALL READ$DISK ;Read the loader bios directly into its load address JNZ RETRY CALL READ$DISK ;Re-read sector 2 into the 8088's highest RAM JNZ RETRY ;Loop on error to re-issue both read commands LXI H,(SWAPP * 256) + IN85 ;Put "IN" instruction and memory manager port SHLD WAIT85 ;At 8085's wait point JMP WAIT85 ;And go wait there ; ;**************************************************************** ;* 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 ; ;************************************************ ;* FIXED STORAGE FOR DISK SPECIFICATIONS * ;************************************************ ; SPEC: ; FLOPPY Specification sequences (loaded only once). if BOOT5X DB 03 ;5 1/4 inch drive specifications DB (SRT5 SHL 4) + HUT5 DB HDLT5 SHL 1 endif if BOOT8X DB 03 ;8 inch drive specifications DB (SRT8 SHL 4) + HUT8 DB HDLT8 SHL 1 endif ; ;************************************************ ;* FIXED STORAGE FOR DISK READ OPERATIONS * ;************************************************ ; ; Function data for controller to boot. DATA: DB 0 ;Extended Address ENTRY: DB BUF shr 8 ;Base address of CBIOS DB BUF and 0FFH READ: DB 06 ;Read sector(s) command for 8272 controller DB 0 ;Head select, Drive select = 0 DB 0 ;Cylinder #0 DB 0 ;Head #0 DB 25 ;Starting Record (sector DB 0 ;"N" parameter (128 byte sectors) DB 25 ;Read just one sector DB 7 ;GPL (Gap length) DB 128 ;DTL (Data length) ; LDRDMA DB 0,52H,0 ;3 bytes of the DMA to setup for 8088 DB 6 ;Read sector(s) command for 8272 controller DB 0 ;Head select, Drive select = 0 DB 0 ;Cylinder #0 DB 0 ;Head #0 DB 5 ;Starting Record (sector) DB 0 ;"N" parameter (128 byte sectors) DB 24 ;Read entire LDRBIOS 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 6 ;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 ;************************************************ ;* 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 ; BUF DS 128 ;Buffer to read the group header into FILL DS 380H-FILL-1 ;Fill out for LOADER image DB 0 END