#TITLE "NEC-APC FLOPPY DISK DRIVER" #SUBTTL "Copyright (c) Multi-Micro Corp." #PAGE 132,66 ; ; DSKAPC.A ; Floppy disk driver for the NEC-APC and TurboDOS. ; ; Version: 6/23/84 ; ; Edit History: ; 6/23/84 jl - Module created. ; 6/24/84 jl - Module assembling but not debugged. ; MODULE "DSKAPC" ; module ID ; #INCLUDE "DREQUATE" ; common driver equivalences #INCLUDE "APCEQU" ; NEC-APC equivalences ; RETRYS == 5 ; number of retrys FDDIREQ == 11 ; FDD Interrupt request number INTRPS == 0 ; -1=interrupts, 0=polled ; ; NEC 765 timer equates ; ND == 0 ; set 765 DMA mode HUT == 240 ; head unload timeout HLT == 38 ; head load delay HUTVAL == HUT/16 ; prep for specify command HLTND == ((HLT/2)<<1)|ND ; prep also ; ; NEC 765 intructions ; SCYCMD == 0X03 ; specify drive parameters SDSCMD == 0X04 ; sense drive status WRCMD == 0X05 ; write sector RDCMD == 0X06 ; read sector RECCMD == 0X07 ; recalibrate SISCMD == 0X08 ; sense interrupt status RIDCMD == 0X0A ; read sector ID FMTCMD == 0X0D ; format a track SKCMD == 0X0F ; seek command ; ; DMA instructions ; DMAWR == 0X15 ; memory write (FDD read) DMARD == 0X19 ; memory read (FDD write) DMAVFY == 0X11 ; memory verify (FDD read) DMAENA == 0X01 ; channel 1 enable DMADIS == 0X05 ; channel 1 disable ; ; Status register 3 bit definitions ; ST3TS == 1<<3 ; two-sided disk ST3RDY == 1<<5 ; drive ready ; ; Pre-defined type code bits ; TSD == 1<<2 ; two-sided disk DDD == 1<<3 ; double density disk MINI == 1<<4 ; mini-floppy disk TPI96 == 1<<5 ; quad density mini floppy ; LOC Data# ; locate in data segment ; DMXSPH: ; mutual exclusion semaphore WORD 1 ; semaphore count WORD . ; semaphore P/D head WORD .-2 ; DWTSPH: ; disk wait semaphore WORD 0 ; semaphore count WORD . ; semaphore P/D head WORD .-2 ; ; 765 read/write table ; RWTBL: DRIVE: BYTE 0 ; drive number TRACK: BYTE 0 ; track number HEAD: BYTE 0 ; head number SECTOR: BYTE 0 ; sector number N: BYTE 0 ; bytes/sector code EOT: BYTE 0 ; end of track GPL: BYTE 0 ; gap length DTL: BYTE 0 ; data length ; ; 765 format table ; FMTBL: FDRV: BYTE 0 ; format drive number FN: BYTE 0 ; format bytes/sector FSC: BYTE 0 ; format sectors/track FGPL: BYTE 0 ; format gap length (3) BYTE 0XE5 ; format filler byte ; RWSTBL: RES 7 ; read/write status table ; ; read/write GAP length table ; RWGAPS: BYTE 0X07 ; 128 bytes BYTE 0X0E ; 256 bytes BYTE 0X1B ; 512 bytes BYTE 0X35 ; 1024 bytes ; TRKTBL: BYTE 0,0,0,0 ; track table (support four drives) ; IOERR: BYTE 0 ; I/O error status byte CURSC: BYTE 0 ; current sector count CURSEC: BYTE 0 ; current sector number CURADR: WORD 0 ; current DMA address ; SECTC: WORD 0 ; sector terminal count RTYCNT: BYTE 0 ; retry counter (set to number of retrys) RECFL: BYTE 0 ; recal flag (set to number of recals) DMAOP: BYTE 0 ; DMA read, write or verify command FDCOP: BYTE 0 ; FDC read or write command ; FLSRT_::BYTE 6 ; drive step rate (patchable) ; ; Function branching table. ; FCNTBL: WORD READ ; function=0, disk read WORD WRITE ; function=1, disk write WORD RETDST ; function=2, return specifications WORD RETRDY ; function=3, return ready WORD FMTTRK ; function=4, format track NMBFCN == (.-FCNTBL)/2 ; number of supported functions ; ; LOC Code# ; locate in code segment ; ; Driver initialization. ; This entry point is called once at system cold boot time and may ; be used to perform any neccessary device initialization. ; DSKIN_:: ; #IF INTRPS ; if interrupts MOV DX,&FDCISR ; get ISR routine address MOV AL,=FDDIREQ ; get FDD interrupt request number CALL INTENA# ; enable interrupts from this device #ENDIF ; INTRPS ; IN AL,FDD_STAT ; read 765 status port INC AL ; is it present? JZ __X ; if not, skip init ; MOV BX,&RWTBL ; use RWTBL for transfer MOV AL,FLSRT_ ; get floppy disk step rate DEC AL NOT AL ; adjust for device MOV CL,=4 ; get shift count SHL AL,CL ; move step value to bits 4-7 OR AL,=HUTVAL ; add in head unload value MOV [BX],AL ; place in table INC BX MOV BYTE [BX],=HLTND ; set HLT and ND MOV CX,=(SCYCMD<<8)|3 ; get command and length CALL CMDRDY ; issue it ; __X: RET ; end of initialization ; ; ; Driver entry point. ; DSKDR_:: MOV BX,&DMXSPH ; get mutual exclusion semaphore CALL WAIT# ; dispatch if necessary CALL __E ; call the disk driver PUSH AX ; save results MOV BX,&DMXSPH ; get mutual exclusion semaphore CALL SIGNAL# ; signal process as ready POP AX ; restore results RET ; done ; __E: MOV BL,PDRFCN[SI] ; get PD request function number CMP BL,=NMBFCN ; check max function number JB __C ; if valid, continue XOR AL,AL ; set error status RET ; and exit ; __C: XOR BH,BH ; make double word ADD BX,BX ; times 2 for table lookup JMPI FCNTBL[BX] ; off to the driver function ; ; ; Function=2, Return disk specifications. ; RETDST: CALL RETRDY ; select and return ready condition TEST AL,AL ; drive ready? JNZ __C1 ; if so, continue RET ; else, exit here ; __C1: ; ; Issue a read ID field in single-density and branch to ; good ID read with AL equal to sector code if successful. ; MOV RECFL,=1 ; set recal flag __DST1: MOV CH,=RIDCMD ; get Read ID command CALL READID ; issue it MOV AL,RWSTBL+6 ; get returned sector size (N) JZ __GID ; if good read ID ; ; Now try a read ID field in double-density and branch to ; good ID read with AL equal to sector code if successful. ; MOV CH,=RIDCMD|(1<<6) ; try double-density next CALL READID ; issue it MOV AL,RWSTBL+6 ; get returned N for FMT sector size PUSHF ; save flags OR AL,=DDD ; set double-density type POPF ; restore flags JZ __GID ; if good read ID ; ; Check the recalibrate flag, and recalibrate the drive if first pass ; through this routine. set recal flag to show recal done. ; DEC RECFL ; check recal flag JS FMTERR ; if retries up, continue error CALL RECAL ; do one recalibrate JMPS __DST1 ; and try format look-up again ; ; AL reg contains the format type as far as density and sector size go. ; Now use the sense drive status command to test for a two sided disk. ; __GID: MOV DL,AL ; hold in register TEST AL,AL ; single density? JNZ __GID1 ; if not, continue MOV AL,RWSTBL+3 ; get cylinder number from results CMP AL,=1 ; track 0 or 1? JA __GID1 ; if not, continue MOV AL,=2 ; load track 2 CALL SEEK1 ; and seek to it JMPS __DST1 ; then check density again ; __GID1: PUSH DX ; save sector type CALL SDS ; sense drive status POP DX ; restore sector type TEST AL,=ST3TS ; test two sided bit JZ __GID2 ; no, FMT correct OR DL,=TSD ; yes, set two-sided type bit __GID2: ; ; Find proper DPB in list ; MOV BX,&DSTBLS# ; get disk spec tables ; __1: CMP DTCO#[BX],DL ; type code correct? JZ __2 ; if so, continue MOV BX,[BX] ; load spec table link TEST BX,BX ; end of list? JNZ __1 ; if not, continue JMPS FMTERR ; format type not found ; __2: ADD BX,=2 ; skip past table linkage MOV PDRDST[SI],BX ; set disk spec table address OR AL,=0XFF ; set return code=http://cpmarchives.classiccmp.org/cpm/Software/maslin/maslin_c_d_10apr97/ddrive/sydex/xfer/apc/FF RET ; done ; ; Branch here if device read errors or format cannot be found ; FMTERR: XOR AL,AL ; force error status RET ; and exit ; ; ; Function=4, format a track ; FMTTRK: CALL RETRDY ; select drive and return ready TEST AL,AL ; drive ready? JNZ __C1 ; if so, continue NOT AL ; else, set AL=FF RET ; and exit here ; __C1: TEST BYTE PDRTRK[SI],=0XFF ; PD requested track=0? JNZ __C2 ; if not, continue CALL RECAL ; else, recalibrate drive __C2: CALL SEEK ; seek to requested track ; MOV BX,&FDRV ; point to drive number in format table TEST BYTE PDRSEC+1[SI],=0X80 ; head number 1 flag set? JZ __C3 ; if not, continue OR BYTE [BX],=1<<2 ; select head 1 in drive field __C3: INC BX ; point to bytes/sector field MOV AL,BYTE PDRSEC[SI] ; get req sector value AND AL,=3 ; extract format sector size MOV [BX],AL ; store in format table INC BX ; point to sectors/track field MOV AL,BYTE PDRSC[SI] ; get req sector count MOV [BX],AL ; store in format table INC BX ; point to gap field MOV AL,BYTE PDRSEC+1[SI] ; get req sector value AND AL,=0X7F ; extract format gap length MOV [BX],AL ; store in format table ; MOV RTYCNT,=RETRYS ; set retry counter __RETRY: MOV AX,PDRBAS[SI] ; get PD request base PUSH AX ; save it MOV CL,=12 SHR AX,CL ; calc extended page MOV DL,AL ; save it POP AX MOV CL,=4 SHL AX,CL ; calc base address ADD AX,PDRDMA[SI] ; add in offset ADC DL,=0 ; add CY into page addr OUT CH1_ADR,AL ; send LSB first MOV AL,AH OUT CH1_ADR,AL ; and MSB second MOV AX,PDRTC[SI] ; get PD request transfer count OUT CH1_TC,AL ; send LSB first MOV AL,AH OUT CH1_TC,AL ; and MSB second MOV AL,DL ; get page addr OUT CH1_EXA,AL ; send page addr MOV AL,=DMARD ; get DMA read memory command OUT DMA_MODE,AL ; send to mode register MOV AL,=DMAENA ; get DMA enable mask OUT DMA_WSM,AL ; send to mask register ; MOV CX,=(FMTCMD<<8)|6 ; get command and length TEST BYTE PDRSEC[SI],=0X80 ; double density flag set? JZ __1 ; if not, continue OR CH,=1<<6 ; set 765 double density bit __1: CALL CMDRDY ; output command to 765 CALL FLWAIT ; wait for completion MOV AL,RWSTBL ; get returned ST-0 AND AL,=0XC0 ; mask error bits JZ __X ; done if no errors DEC RTYCNT ; another retry? JP __RETRY ; if so, loop OR AL,=0XFF ; else get error return __X: RET ; done ; ; ; Function=0, read disk ; READ: MOV DMAOP,=DMAWR ; set DMA mode to write memory MOV DL,=RDCMD ; get FDC read command JMPS RWCOM ; and join common code ; ; ; Function=1, write disk ; WRITE: MOV DMAOP,=DMARD ; set DMA mode to read memory MOV DL,=WRCMD ; get FDC write command CALL RWCOM ; use common routines TEST AL,AL ; test results JZ __C1 ; if good, continue RET ; else, exit here ; __C1: MOV DMAOP,=DMAVFY ; set DMA verify command MOV DL,=RDCMD ; FDC read command ; ; Common routines to both reading and writing. ; RWCOM: ; ; Set up the read or write operation for single- or double- ; density as specified by DDD bit of the format type code in ; the drive specification table. ; CALL RETTCA ; return type code address TEST BYTE [BX],=DDD ; test double-density type bit JZ __SD ; if single-density, continue OR DL,=1<<6 ; set MFM bit-6 in FDC command __SD: TEST BYTE [BX],=TSD ; test double-sided type bit JZ __SS ; if single-sided, continue OR DL,=1<<7 ; set MT bit-7 in FDC command __SS: MOV FDCOP,DL ; store FDC command ; MOV AL,BYTE PDRSEC[SI] MOV CURSEC,AL ; set current sector MOV AX,PDRDMA[SI] MOV CURADR,AX ; set current address MOV AL,BYTE PDRSC[SI] MOV CURSC,AL ; set current sector count ; ; Lookup the values for the GPL and DTL based on the current sector size. ; MOV BL,SECSIZ[SI] ; get the sector size value AND BL,=3 ; mask the sector size bits 0&1 MOV N,BL ; set the N field XOR BH,BH ; make double length MOV AL,RWGAPS[BX] ; get GPL entry MOV GPL,AL ; and patch it MOV DTL,=128 ; preset DTL for single-density TEST BL,BL ; sector size=0? JZ __SD1 ; if so, continue MOV DTL,=0XFF ; set for other sector sizes __SD1: MOV IOERR,=0 ; clear I/O error status byte MOV RECFL,=1 ; set the recal flag ; ; Select in drive through ready test routine (RETRDY) ; RWLOOP: CALL RETRDY ; use subroutine TEST AL,AL ; drive ready? JNZ __C1 ; if so, continue NOT AL ; set AL=FF RET ; __C1: CALL SEEK ; seek to proper track ; ; Select either head-0 or head-1 from the format type value. ; MOV DL,CURSEC ; get current sector CALL RETXLT ; return translation table address JZ __NT ; if no translation required XOR DH,DH ; make sector double length ADD BX,DX ; index into table MOV DL,[BX] ; get translated sector __NT: INC DL ; set sector base to 1 MOV DH,BYTE SECTRK[SI] ; get sectors per track value CALL RETTCA ; return type code address TEST BYTE [BX],=TSD ; test double sided disk JZ __SS ; if not, continue SHR DH,=1 ; find number of sectors per side __SS: MOV BX,&DRIVE AND BYTE [BX],=3 ; reset head select bit MOV HEAD,=0 ; and head match field for 0 CMP DH,DL ; on side 0? JNB __S0 ; if side 0 selected SUB DL,DH ; remove side 1 bias OR BYTE [BX],=1<<2 ; set drive number for head 1 MOV HEAD,=1 ; set head match field for 1 __S0: MOV SECTOR,DL ; set sector MOV EOT,DH ; use as EOT value ; ; Start of reading and writing. NOTE: retry entry point also. ; MOV RTYCNT,=RETRYS ; set retry counter __RETRY: CALL DMANIT ; setup the DMA device MOV CH,FDCOP ; get FDC command MOV CL,=9 ; length of command CALL CMDRDY ; issue command CALL FLWAIT ; wait for completion interrupt MOV AL,RWSTBL ; get ST-0 AND AL,=0XC0 ; mask error bits JZ RWNXT ; if successful operation ; ; Test for a drive not ready condition and branch ; to the error exit routine with the proper result if true. ; TEST BYTE RWSTBL,=1<<3 ; drive not ready? JNZ RWNXT ; if so, continue ; ; Now check the wrong cylinder bit in ST-2. If not true, then branch ; to more error routines. If true, then recalibrate the drive and perform ; a re-seek to the selected track. ; TEST BYTE RWSTBL+2,=1<<4 ; wrong cylinder error set? JZ __E1 ; if not, continue DEC RECFL ; recal done? JS __E1 ; if so, skip it CALL RECAL ; recalibrate the drive JMP RWLOOP ; and re-seek selected track ; ; Check the retry counter for zero and perform preset number ; of retrys to read or write a sector. ; __E1: MOV CL,=ABEL ; get bell character CALL CONOUT# ; output to console DEC RTYCNT ; one less retry JP __RETRY ; if not zero ; RWNXT: MOV AL,RWSTBL OR IOERR,AL ; update I/O error flag CALL RETXLT ; return translate table and status JZ __X1 ; if not present, continue exit ; CALL RETSSZ ; return current sector size ADD CURADR,AX ; set new DMA address INC CURSEC ; bump current sector number DEC CURSC ; check sector count JZ __X1 ; if done, continue exit JMP RWLOOP ; else, continue loop ; __X1: MOV AL,IOERR ; get error status AND AL,=0XC0 ; mask error bits JZ __X2 ; done if no errors OR AL,=0XFF ; set AL=FF __X2: RET ; done ; ; ; Setup DMA controller ; DMANIT: MOV AX,PDRBAS[SI] ; get PD requested base PUSH AX ; save it MOV CL,=12 SHR AX,CL ; calc the extended page MOV DL,AL ; save it POP AX ; restore base MOV CL,=4 SHL AX,CL ; calc page offset ADD AX,CURADR ; add in DMA offset ADC DL,=0 ; add CY to page addr OUT CH1_ADR,AL ; send LSB addr first MOV AL,AH OUT CH1_ADR,AL ; send MSB second CALL RETSSZ ; return current sector size CALL RETXLT ; return translate table and status JNZ __C1 ; if present, cont' with single length MOV AX,PDRTC[SI] ; load PD request transfer count __C1: DEC AX OUT CH1_TC,AL ; send LSB first MOV AL,AH OUT CH1_TC,AL ; send MSB second MOV AL,DL ; get DMA page back OUT CH1_EXA,AL ; send to extended page select MOV AL,DMAOP ; get DMA operation OUT DMA_MODE,AL ; send current DMA mode MOV AL,=DMAENA ; get channel 1 enable command OUT DMA_WSM,AL ; enable DMA controller RET ; done ; ; ; Function=3, return drive ready status ; RETRDY: MOV AL,PDRDRV[SI] ; get disk number CMP AL,=4 ; test for valid drive number JAE __NR ; if invalid, return not ready IN AL,FDD_STAT ; read 765 status port INC AL ; is it present? JZ __NR ; if not, return not ready status CALL DSKSEL ; select in drive CALL SDS ; test drive status TEST AL,=ST3RDY ; test ready status JZ __NR ; if not, return not ready OR AL,=0XFF ; set drive ready status RET ; and exit ; __NR: XOR AL,AL ; clear AL for not ready RET ; and exit ; ; ; Drive select subroutine. ; The new drive is checked against the current drive selected ; on the board and if not the same, the track table is used to store the ; old track number and get the new drives track number, then the new drive ; is selected on the board. ; DSKSEL: MOV DL,PDRDRV[SI] ; get drive number AND DL,=3 ; mask valid bits MOV AL,DRIVE ; get current drive AND AL,=3 ; mask to drive number CMP AL,DL ; same as new? JZ __X ; if so, skip select MOV BL,AL ; old disk to reg XOR BH,BH ; prep for double add MOV AL,TRACK ; get track from RW table MOV TRKTBL[BX],AL ; and place in track table MOV BL,DL ; get new disk to reg MOV AL,TRKTBL[BX] ; get entry from track table MOV TRACK,AL ; and place in RW table MOV DRIVE,BL ; set drive number in RW table MOV FDRV,BL ; and drive number in FORMAT table __X: AND DRIVE,=~(1<<2) ; select head 0 in drive field AND FDRV,=~(1<<2) ; select head 0 in drive field RET ; done ; ; ; Recalibrate the current board selected drive. The 765 recalibrate ; command is issued and the track field in the RW table set to 0. ; RECAL: MOV CX,=(RECCMD<<8)|2 ; get recal command and length CALL CMDRDY ; issue command CALL FLWAIT ; wait for completion XOR AL,AL MOV TRACK,AL ; reset track field in RW table RET ; done ; ; ; Seek to PD requested track number. ; SEEK: MOV AL,BYTE PDRTRK[SI] ; get selected track CMP AL,TRACK ; same as current? JZ SKX ; if so, continue exit SEEK1: MOV TRACK,AL ; put in RW table MOV CX,=(SKCMD<<8)|3 ; get seek command and length CALL CMDRDY ; send command CALL FLWAIT ; wait for completion SKX: RET ; ; ; Issue sense drive status command and retreive results. ; SDS: MOV CX,=(SDSCMD<<8)|2 ; get sense drive status command CALL CMDRDY ; issue it CALL CMDRES ; read results MOV AL,RWSTBL ; get ST-3 RET ; with it ; ; ; Read sector ID field. The B register contains either a single- ; or a double-density read ID command. The command is issued and ; ST-0 error bits mask. ZERO flag is set if no error occured. ; READID: MOV CL,=2 ; length in C CALL CMDRDY ; issue command CALL FLWAIT ; wait for completion MOV AL,RWSTBL ; get status AND AL,=0XC0 ; mask error bits RET ; with Z set for success ; ; ; Send command to NEC 765 subroutine. ; initial command in CH reg, additional bytes are sent from the ; beginning of the READ/WRITE table as requested by the 765. ; If command in CH reg is a format command, the FORMAT table is used. ; reg CL contains the number of bytes that should be transfered. ; CMDRDY: IN AL,FDD_STAT ; get main status register TEST AL,=1<<4 ; mask FDC busy bit-4 JNZ CMDRDY ; loop if busy PUSHF ; save flags CLI ; and disable interrupts MOV BX,&RWTBL ; point to RW table MOV AL,CH ; get 765 command AND AL,=0X0F ; mask command bits CMP AL,=FMTCMD ; format command? JNZ __C1 ; if not, continue MOV BX,&FMTBL ; point to FORMAT table ; __C1: IN AL,FDD_STAT ; get main status register TEST AL,=1<<7 ; test RQM JZ __C1 ; loop if not ready TEST AL,=1<<6 ; test DIO for direction JNZ __X ; if 765 full MOV AL,CH ; get byte for output OUT FDD_DATA,AL ; send it MOV CH,[BX] ; get next byte for output INC BX ; bump RW table pointer DEC CL ; count=count-1 JNZ __C1 ; loop if more to send __X: POPF ; restore intrp status RET ; done ; ; ; Receive NEC 765 result phase subroutine. ; The results of an operation are read out of the 765 as ; requested to be read by the DIO bit-6. The results are loaded ; into the RW status table. ; CMDRES: PUSHF ; save machine status CLI ; disable interrupts MOV BX,&RWSTBL ; set result table pointer ; __C1: IN AL,FDD_STAT ; get main status register TEST AL,=1<<7 ; test RQM JZ __C1 ; loop if not ready TEST AL,=1<<6 ; test DIO JZ __X ; if done receiving IN AL,FDD_DATA ; get result byte MOV [BX],AL ; store data in table INC BX ; bump table pointer JMPS __C1 ; and loop for more __X: POPF ; restore intrp status RET ; ; ; Disk wait subroutine. This is called when waiting on the 765 ; to perform an operation in which it will interrupt when completed. ; FLWAIT: #IF INTRPS ; if interrupts ; MOV BX,&DWTSPH ; get disk wait semaphore JMP WAIT# ; wait for completion ; #ELSE ; MOV DX,&FDCPOL ; get poll routine addr CALL LNKPOL# ; add to poll list MOV BX,&DWTSPH ; get disk wait semaphore JMP WAIT# ; wait for completion ; #ENDIF ; INTRPS ; ; ; Get translate table address. Z flag set if no table. ; RETXLT: MOV BX,PDRDST[SI] ; get disk specifications offset MOV BX,XLTBL#[BX] ; get translation table offset TEST BX,BX ; translation required? RET ; exit with status ; ; ; Return current drive type code address as [BX]. ; RETTCA: MOV BX,PDRDST[SI] ; get disk specifications offset ADD BX,=TYPCOD# ; index to type code address RET ; all done ; ; ; Return the current sector size in bytes. ; RETSSZ: PUSH CX ; save reg MOV CL,SECSIZ[SI] ; get PD request size code MOV AX,=128 ; get base sector size SHL AX,CL ; calc physical byte count POP CX ; restore reg RET ; and exit ; ; #IF INTRPS ; if interrupts ; ; TurboDOS floppy disk interrupt service routine ; FDCISR: PUSH AX PUSH BX PUSH CX PUSH DX ; save regs PUSH DS ; save user data seg CALL GETSDS# ; get system data seg CALL FLINT ; process 765 interrupt request JC __NSIG ; if ready change int, no signal MOV BX,&DWTSPH ; get disk wait semaphore CALL SIGNAL# __NSIG: MOV AL,=FDDIREQ ; get interrupt request level CALL SIGEOI# ; do specific EOI command POP DS POP DX POP CX POP BX POP AX ; restore regs JMP ISRXIT# ; continue with interrupt ; #ELSE ; ; TurboDOS polling routine for FDD interrupts. ; FDCPOL: WORD 0 WORD 0 ; poll linkages ; PUSHF ; save machine status CLI ; disable interrupts MOV AL,=0X0A OUT SIC_P0,AL ; OCW3=read IRR IN AL,SIC_P0 ; read IRR POPF ; restore intrp status TEST AL,=1<<4 ; test FDD IREQ JZ __X ; if not ready, continue CALL FLINT ; process end of operation JC __X ; if false alarm, continue MOV BX,&FDCPOL ; get poll routine addr CALL UNLINK# ; and remove it MOV BX,&DWTSPH ; get disk wait semaphore CALL SIGNAL# ; signal process ready __X: RET ; #ENDIF ; INTRPS ; ; Now the 765 result phase must be performed for any interrupting ; type of command. If the 765 busy bit is set, the results from a ; read or a write type command must be read. If the 765 busy bit is ; not set, then a sense interrupt status command is sent and the ; results of a seek, recal, or drive ready change interrupt are read out. ; FLINT: IN AL,FDD_STAT ; get main status register TEST AL,=1<<4 ; busy? (read or write in process) JNZ __RWD ; yes, read results out MOV CX,=(SISCMD<<8)|2 ; get command and length CALL CMDRDY ; issue sense interrupt status command __RWD: CALL CMDRES ; read the results MOV AL,RWSTBL ; get ST-0 AND AL,=0XC0 ; mask error bits CMP AL,=0XC0 ; drive ready change? STC ; preset CY flag JZ __X ; if so, continue exit MOV AL,=DMADIS ; get DMA disable command OUT DMA_WSM,AL ; disable DMA device XOR AL,AL ; clear CY flag __X: RET ; exit ; END