if hard .D2 IF DISK2 ; ; HDSEL -- Select appropriate hard disk drive. ; hdsel call hdalt ;Check for alternate sectors stob #2,rept hdsl1 ld cl,ciopb+1 ;Get unit # or cl,#'0' sto cl,hdrdy1 and cl,#3 ;Strip off ascii bias ld ch,#10h rol ch,cl ld al,ciopb+1 or al,#h.dvs outb hdctl ;Set select register mov al,ch outb hddata inb hdctl and al,#1000_1000b cmp al,#80h je hdsl2 ;If drive ready decb rept jnz hdsl1 ld bx,#hdrdy call print ld cx,#500 call delay call j.cst and al,al jz hdsl1 ;If not abort inc al ;A = 0FFh +1 = 0 inc al ;A = 1 ret hdsl2 ld al,ciopb+1 or al,#0000_0100b outb hdctl call badmap ld al,#0ffh jc hdsl3 ;Error in reading bad map. A = 0ffh inc al ;A + 1 = 0 hdsl3 ret hdrdy db cr,lf,'Hard disk unit ' hdrdy1 db 'x not ready!',0 space 4,10 hditab db 0, 0, 0, 0 ;Set to one once bad map is read ; ; BADMAP -- Read in bad map first time a drive is selected ; badmap cld ld bx,ciopb+1 ;Pick up drive number in (l) ld bh,#0 test [bx+hditab],#1 jnz addlr2 stob #1,[bx+hditab] ;Set as read in push bufadr push ciopb+4 push ciopb+2 push ciopb+0 ld bx,#ciopb+0 stob #h.red,[bx] stob #0,[bx+2] ;Cylinder 0 stob #2,[bx+3] ;Head 2 stob #1,[bx+4] ;Sector 0 (1) sto #hstbuf,bufadr ;Set DMA address to internal buffer call hdseek if @ldr <> 0 ld ch,numsec push cx stob #1,numsec endif call hdxfer if @ldr <> 0 pop cx sto ch,numsec endif stc ;Set error flag jnz baderr ;Return if error pop ciopb+0 pop ciopb+2 pop ciopb+4 pop bufadr ld bx,#hstbuf addlr test [bx],#0ffh jnz addlr1 jmp hdsel addlr1 call addto add bx,#6 jmp addlr baderr pop bx pop bx pop bx pop bx stc addlr2 ret addto mov si,bx ld di,#hdbad ;Start of bad map pointer addl cmp di,hdptr jnz more ld al,ciopb+1 ;Pick up drive stosb push di ld cx,#6 rep movsb sto di,hdptr pop di incb [di+2] incb [di+5] ret more push si ;Save current bad sector push di ;Save bad map pointer ld al,ciopb+1 scasb jnz miss ld cx,#3 repz cmpsb jnz miss pop di pop si ret miss pop di pop si add di,#7 jmp addl ; ; HDSEEK -- Seek to specified cylinder. ; ; ENTRY CIOPB+2 = cylinder. ; hdseek ld bl,actdsk ld bh,#0 cmpb [bx+hdcyl],#0ffh ld al,[bx+hdcyl] jnz hdsk3 hdsk0 inb hdctl and al,#0000_0001b jz hdsk3 ld al,actdsk or al,#4+h.sou outb hdctl if gbc26 ld cx,#1 else ld cx,#0 endif hdsk1 inb hddata loop hdsk1 hdsk2 inb hdctl and al,#0000_0100b jnz hdsk2 if gbc26 jmp hdsk0 endif hdsk3 ld cl,ciopb+2 sto cl,[bx+hdcyl] sub cl,al sto cl,hdskfg jnz hdsk3a ret hdsk3a jc hdsk4 ld al,#h.sin jmp hdstep hdsk4 neg cl ld al,#h.sou hdstep or al,ciopb+1 outb hdctl ld ch,#0 hdsp1 inb hddata loop hdsp1 ret ; ; HDXFER -- Transfer data to/from hard disk. ; ; ENTRY CIOPB+0 = command. ; hdxfer if @ldr <> 0 stob #0,secoff sto #0,secadd endif test hdskfg,#0ffh jz hdx2 hdx1 inb hdctl and al,#0000_0100b jnz hdx1 if gbc26 ld cx,#32 call delay endif hdx2 ld cl,ciopb+1 ;Pick up drive ld ch,#10h rol ch,cl hdxdn ld al,ciopb+1 or al,#h.dvs outb hdctl ;Output to drive select ld al,ciopb+3 or al,ch outb hddata ;Select drive, head ld bx,#ciopb+2 ld al,#h.cyl outb hdctl ld al,[bx] ;Cylinder outb hddata ld al,#h.hed outb hdctl ld al,[bx+1] ;Head outb hddata ld al,#h.sec outb hdctl ld al,[bx+2] if @ldr <> 0 add al,secoff endif dec al outb hddata inb selchan ld ax,bufseg ld cl,#4 rol ax,cl mov bx,ax and al,#0fh and bx,#0fff0h add bx,bufadr adc al,#0 outb selchan mov al,bh outb selchan mov al,bl outb selchan ld ch,ciopb+0 cmp ch,#h.red ld al,#80h+selbyt jz hdx4 ld al,#selbyt hdx4 outb selchan ld al,ciopb+1 or al,ch outb hdctl hdx5 inb hdctl ;Get status and al,#1000_0000b jnz hdx5 ;If transfer not complete inb hdctl and al,#0111_1110b ;Mask timeout, crc, over run etc xor al,#02h ;Flip status of write fault bit for final pushf ;Save error status ld al,#80h ;Reset interrupt status bit to inactive outb hdctl ld al,#0001_0000b ;Reselect unit 0 to execute command outb hddata popf ;Recover error status jnz hderr xor al,al if @ldr <> 0 decb numsec jnz hdx6 endif ret hdx6 if @ldr <> 0 incb secoff add secadd,#1024 jmp hdx2 endif hderr xor al,al or al,#01h ret hdalt ld bx,#hdbad-7 ;Point to start of bad map altlop add bx,#7 cmp bx,hdptr jnz almore ret almore mov si,bx ld di,#ciopb+1 ld cx,#4 repz cmpsb jnz altlop ld di,#ciopb+2 ld cx,#3 rep movsb ret rept db 0 hdskfg db 0 secoff db 0 secadd dw 0 endif .D2 ENDIF