title 'Disk Boot for CompuPro DISK1' ;******************************************************* ; Last Modification: 10/14/83 ; ; D i s k B O O T ; ; The following code is written onto track 0 sector ; 0 -3 of the disk. This routine is read into memory ; at location 0000:0100h by the CompuPro PROM. This ; routine then loads the system loader into memory. ; ; The format of the CompuPro Floppy Disk Boot sectors ; are as follows: ; ; Trk Sectors Description ; --- ------- ----------- ; 0 1 thru 4 Disk Boot program (this routine) ; ; 5 Loader Group Header ; 6 thru 26 Loader Part 1 ; ; 1 1 thru ? Loader Part 2 (remainder not on track 0) ; Number of sectors is determined by ; disk density and format. ; ; The following commands are used to generate DSKBOOT.CMD ; as an 8080 model routine ; RASM86 DSKBOOT ; LINK86 DSKBOOT.SYS = DSKBOOT [DATA[ORIGIN[0]]] ; ; The following commands are used to generate the ; boot tracks image in the file BOOTTRKS ; SID86 ; #RDSKBOOT.SYS ;strips header and ; #WBOOT,180,37F ;default base page ; PIP BOOTTRKS = BOOT[O],CPMLDR.SYS[O] ; ;******************************************************* N_TRK equ 26 ;sectors in Track 0 N_BOOT equ 4 ;sectors for Boot ; Assembly Constants FDPORT equ 0C0H ;base port address for DISK1 Controller FDC_S equ FDPORT ;8272 status register FDC_D equ FDPORT+1 ;8272 data register D1_DMA equ FDPORT+2 ;DISK1 DMA address (when write) D1_INTS equ FDPORT+2 ;DISK1 status Register (when read) DELCNT equ 5*1000 ;delay count for 5 MHz processor RQM_DELAY equ 5 ;12us delay count for master status ; Intel 8272 controller function definitions ; Specify (00) command F_SPEC equ 03 ;specify F_DSTS equ 04 ;drive status F_RDAT equ 06 ;read data F_RECA equ 07 ;recalibrate F_RSTS equ 08 ;read status F_RID equ 0Ah ;read ID F_SEEK equ 0Fh ;seek SRT equ 16-8 ;shuggart 800s HUT equ 240/16 ;head unload = 240 ms HLT equ (35+1)/2 ;head load = 35 ms ND equ 00 ;set DMA mode cgroup group code,data ;force code and data into 8080 model ;------------------------------------------------------- ; Bootstrap load. ; Do not change any addresses from here to START: ; Entry CL= Board switches from CompuPro PROM (0 .. 3) CSEG org 0100H ;origin for 8080 model nop! nop! nop ;these instructions have already nop! nop! nop ; been prefetched from the nop ; CompuPro boot PROM ; Start of Boot code. ; Save board option value. ; Load bios. start: ;===== cli mov ax,cs mov es,ax mov ss,ax ;switch to local stack in base page mov sp,offset stack ;area from 0080h down xor bx,bx! mov ds,bx mov opts,cl ;save DISK1 board options switch mov ds,ax ;DS = CS, 8080 model retry: mov si,offset spec ;specify controller parameters mov cl,LSPEC ;length of specify command call send_command ;send command to 8272 ;SI = offset of recal command mov cl,LRECAL ;length of recal command call send_command ;Recalibrate drive end_rcal: in al,D1_INTS ;interrupts are disabled, so we or al,al! jns end_rcal ;poll for command completion mov al,F_RSTS ;send sense interrupt status to 8272 out FDC_D,al ;required after recal command mov cx,250 ;Leave lite on for 1/4 second call delay call wait_rqm ;wait for drive ready in al,FDC_D ;get status 0 from 8272 sub al,020h ;remove seek end bit mov cl,al call wait_rqm ;wait for drive ready in al,FDC_D ;get present cylinder number or al,cl! jnz error ;error if not on track 0 after recal mov ax,ds ;setup AX to segment address of CMD add ax,offset header_buf/16 ; header buffer in base page for DMA mov si,offset read_ghdr ;command to read loader group header call disk_read ;read loader group header jnz error ;if error mov word ptr header_buf+1,0 ;setup offset for jump far to loader mov ax,word ptr header_buf+3 ;AX = segment address of DMA mov si,offset read ;command to read remainder of track 0 call disk_read ;read remainder of track 0 jz read_c1 ;if no errors error: ; Disk error handler. ;----- mov cx,2000 ;wait 2 seconds call delay ; and start all over again jmps retry read_c1: mov si,offset seek ;seek to cylinder 1 mov cl,LSEEK ;length of seek command call send_command ;send command to 8272 end_seek: in al,D1_INTS ;interrupts are disabled, so we or al,al! jns end_seek ;poll for command completion mov al,F_RSTS ;send sense interrupt status to 8272 out FDC_D,al ;required after seek command call wait_rqm ;wait for drive ready in al,FDC_D ;get status 0 from 8272 sub al,020h ;remove seek end bit mov cl,al call wait_rqm ;wait for drive ready in al,FDC_D ;get present cylinder number sub al,1 ;should be cylinder 1 or al,cl! jnz error ;if error then delay and try again ;determine density and sector ;size of cylinder 1 mov al,F_RID + 040h ;setup to try double density first try_fm: mov si,offset readid ;read id to determine density mov [si],al ;set read command for desired density mov cl,LREADID ;length of read id command call execute ;execute command and read result bytes mov al,status ;get status 0 of result bytes or al,al! jz dens_ok mov al,readid xor al,040h ;toggle MFM flag test al,040h! jnz error ;tried FM and MFM then error jmps try_fm dens_ok: mov bl,status+6 ;get N field from result bytes and bx,3! shl bx,1 ; to determine sector size mov si,read1[bx] ;SI -> command to read side 0 of cyl 1 mov ax,word ptr header_buf+3 add ax,(128*(26-5))/16 ;AX = DMA segment address for cyl 1 call disk_read ;read cylinder 1 jnz error ;if error delay and try again jmpf dword ptr header_buf+1 ;the group header has been setup ;to point to loader entry wait_rqm: ;wait for drive ready ;-------- mov al,RQM_DELAY ;must delay 12us before polling w_rqm1: ;FDC status to insure valid results dec al ! jnz w_rqm1 w_rqm2: in al,FDC_S ;get master status from 8272 or al,al! jns w_rqm2 ;if no master ready bit ret send_command: ; Send Function to Drive. ;------------ ; Entry: SI -> command bytes ; CL = length of command. ; Exit: SI -> end of command + 1. call wait_rqm ;wait for drive ready lodsb ;load command byte out FDC_D,al ;send to 8272 controller dec cl! jnz send_command ;if more bytes ret disk_read: ; Disk Read. ;--------- ; Entry: AX = segment address of DMA ; SI -> Command (9 bytes) ; Exit: SI -> End of Command + 1. ; Z flag set if successful read push ax ;compute 24 bit DMA address mov cl,4 ;for DISK1 DMA port shr ax,cl ;AX = most significant 16 bits xchg al,ah out D1_DMA,al ;send highest address byte xchg al,ah out D1_DMA,al ;send middle address byte pop ax shl ax,cl out D1_DMA,al ;send low address byte mov cl,LREAD ;length of read command execute: call send_command ;send command to controller wait_int_1: in al,D1_INTS ;interrupts are disabled, so we or al,al! jns wait_int_1 ;poll for command completion mov di,offset status ;SI -> to buffer to save result bytes mov cl,7 ;number of bytes to save get_status: call wait_rqm ;wait for drive ready in al,FDC_D ;read result byte stosb ;save in buffer dec cl! jnz get_status ;wait until all done mov ax,word ptr status ;get status 0 and 1 sub ax,8040h ;40h - zeros abnormal termination bit ;80h - zeros end of cylinder status bit ret delay: ;Delay process. ;----- ; Entry: CX = delay count (nominal milliseconds). ; Exit: AL modified mov al,DELCNT/26 dely1: inc cx! dec cx dec al! jnz dely1 ;if not one millisecond dec cx mov al,ch or al,cl! jnz delay ;if not requested time ret ;------------------------------------------------------- DSEG opts equ byte ptr .0040h stack equ word ptr .0080h header_buf equ byte ptr .0080h ; Disk setup command strings. spec db F_SPEC db SRT shl 4 + HUT db HLT shl 1 + ND LSPEC equ offset $ - offset spec recal db F_RECA db 0 LRECAL equ offset $ - offset recal ; Read Loader Group Header. read_ghdr db F_RDAT db 0 ;hds,ds1,ds0 db 0 ;Cylinder db 0 ;Head db N_BOOT+1 ;Record (sector) of Group db 0 ;Number of data bytes in sector db N_BOOT+1 ;EOT db 7 ;GPL db 128 ;DTL LRGHDR equ offset $ - offset read_ghdr ; Read remainder of track 0, sectors 6-26 read db F_RDAT db 0 ;hds,ds1,ds0 db 0 ;Cylinder db 0 ;Head db N_BOOT+2 ;Record (sector) of BIOS db 0 ;Number of data bytes in sector db N_TRK ;Read to end of track db 7 ;GPL db 128 ;DTL LREAD equ offset $ - offset read ; Disk Seek command for controller seek db F_SEEK db 0 db 1 LSEEK equ offset $ - offset seek readid db F_RID + 040h db 0 LREADID equ offset $ - offset readid status rb 7 ;buffer for status result bytes read1 dw read_128 dw read_256 dw read_512 dw read_1024 ; Read function for single density (128 bytes/sec) read_128 db F_RDAT db 0 ;hds,ds1,ds0 db 1 ;Cylinder db 0 ;Head db 1 ;Record (sector) of BIOS db 0 ;Number of data bytes in sector db 26 ;Read to end of track db 007h ;GPL db 128 ;DTL ; Read function for double density (256 bytes/sec) read_256 db F_RDAT + 040h db 0 ;hds,ds1,ds0 db 1 ;Cylinder db 0 ;Head db 1 ;Record (sector) of BIOS db 1 ;Number of data bytes in sector db 26 ;Read to end of track db 00Eh ;GPL db 255 ;DTL ; Read function for double density (512 bytes/sec) read_512 db F_RDAT + 040h db 0 ;hds,ds1,ds0 db 1 ;Cylinder db 0 ;Head db 1 ;Record (sector) of BIOS db 2 ;Number of data bytes in sector db 15 ;Read to end of track db 01Bh ;GPL db 255 ;DTL ; Read function for double density (1024 bytes/sec) read_1024 db F_RDAT + 040h db 0 ;hds,ds1,ds0 db 1 ;Cylinder db 0 ;Head db 1 ;Record (sector) of BIOS db 3 ;Number of data bytes in sector db 8 ;Read to end of track db 035h ;GPL db 255 ;DTL END