cgroup group code,data public pdio_init public pdio_rd public pdio_wr public dst1 public dst2 public hst_dsk public hst_trk public hst_sec public hst_seg public hst_off ; PIC declarations extrn snsfdint:near extrn fdint_sw:byte ; main xios externs extrn poll:near extrn flagwait:near ; use global equates file nolist include ccpmxios.equ list ; ; 765A Programmable Fllopy Disk Controller ; and 8257 Programmable DMA Controller ; fdcsts equ 64h ; staus_reg port fdcparm equ 66h ; parameter_reg port fdcrslt equ fdcparm ; result_reg port ; dma0adr equ 20h ; CH_0 DMA address port dma0cnt equ 22h ; CH_0 terminal count port dma0seg equ 70h ; CH_0 address (AD_16 -- AD_19) port dmamode equ 30h ; mode set port ; wtdmamod equ 8000h ; DMA write direction rddmamod equ 4000h ; DMA read direction ; fdc_read equ 11000110b ; read function code fdc_write equ 11000101b ; write function code fdc_seek equ 00001111b ; seek function code fdc_recal equ 00000111b ; recalibrate function code fdc_sis equ 00001000b ; sense interrupt status fdc_sds equ 00000100b ; sense device status fdc_hd_bit equ 00000100b ; HD bit fdc_spec equ 00000011b ; specify function code fdc_spec_srt equ 0Dh ; step rate time ( 6 msec ) fdc_spec_hut equ 32/32 ; head unload time ( 32 msec ) fdc_spec_hlt equ 52/4 ; head load time ( 52 msec ) ; n equ 1 ; record (sector) length [ 256 bytes ] eot equ 16 ; end of track gpl equ 0Eh ; gap length dtl equ 0FFh ; data length [ ignore ] ; ; FDC command table offset fcto_lng equ 0 ; length fcto_cmd equ 1 ; function code fcto_unt equ 2 ; unit number fcto_c equ 3 ; cylinder number fcto_h equ 4 ; head address fcto_r equ 5 ; record(sector) address fcto_n equ 6 ; record size fcto_eot equ 7 ; end of track fcto_gpl equ 8 ; gap length fcto_dtl equ 9 ; data length ; ; result status ; st0_nr equ 00001000b ; not ready st0_ec equ 00010000b ; equipment check st0_se equ 00100000b ; seek end st1_ma equ 00000001b ; missing address mark st1_nw equ 00000010b ; not writable st1_nd equ 00000100b ; no data st1_de equ 00100000b ; data error st2_md equ 00000001b ; missing addr. mark in data field st2_bc equ 00000010b ; bad cylinder st2_nc equ 00010000b ; no cylinder st2_dd equ 00100000b ; data error in data field st2_cm equ 01000000b ; control mark st3_ry equ 00100000b ; dvice ready st3_wp equ 01000000b ; write protected st3_ft equ 10000000b ; fault ; ; FD error code ; fer_nul equ 0 ; null error fer_nsy equ 1 ; not system disk fer_nrd equ 2 ; drive not ready fer_0nf equ 3 ; track 00 not found fer_sek equ 4 ; seek error fer_ndam equ 5 ; lost data [ incorrected data address mark ] fer_nam equ 6 ; address error [ incorrected address mark ] fer_nwt equ 7 ; write fault fer_wpr equ 8 ; write protected fer_badc equ 9 ; bad track fer_nc equ 10 ; track not found fer_nd equ 11 ; sector not found fer_dcrc equ 12 ; data CRC error fer_icrc equ 13 ; ID CRC error fer_ddam equ 14 ; deleted record ; rtrycnt equ 10 eject cseg dst1: call snsfdint ; ask pic module about interrupt waiting ret ; return to caller dst2: ret eject ; ; the following code tests the ability of the system to read ; sectors from the TMP: disk. ; pdio_init: mov al,temp_disk ! mov hst_dsk,al mov ax,0 ! mov hst_trk,ax mov al,0 ! mov hst_sec,al call readhst and al,al ret pdio_rd: CALL READHST ; GET PHYSICAL SECTOR push ax ; save return code from hst_* CALL B2U ; BUFFER ==> USER pop ax ; restore return code from hst_* RET pdio_wr: CALL U2B ; USER ==> BUFFER CALL WRITEHST RET EJECT ; THESE ROUTINES TRANSFER THE SECTOR FROM THE READ/WRITE ; BUFFER TO/FROM THE USERS BUFFER B2U: PUSHF ; SAVE FLAGS PUSH ES ; SAVE EXTRA SEGMENT PUSH DS ; SAVE DATA SEGMENT CLD ; <-- MOV AX,HST_SEG ; GET USER SEGMENT MOV ES,AX ; SET ES FOR DEST MOV AX,CS ; GET BUFFER SEGMENT MOV DS,AX ; SET DS FOR SOURCE MOV DI,HST_OFF ; GET/SET USER OFFSET MOV SI,OFFSET HST_BUF ; GET/SET BUFFER OFFSET MOV CX,HSTSIZ ; BUFFER SIZE REP MOVSB ; DO IT POP DS ; RESTORE CALLER'S DS POP ES ; RESTORE CALLER'S ES POPF ; RESTORE CALLER'S FLAGS RET ; RETURN TO CALLER U2B: PUSHF ; SAVE FLAGS PUSH ES ; SAVE EXTRA SEGMENT PUSH DS ; SAVE DATA SEGMENT CLD ; <-- MOV AX,CS ; GET BUFFER SEGMENT(MINE) MOV ES,AX ; SET ES FOR DEST MOV DI,OFFSET HST_BUF ; GET/SET BUFFER OFFSET MOV SI,HST_OFF ; GET/SET USER OFFSET MOV AX,HST_SEG MOV DS,AX MOV CX,HSTSIZ ; BUFFER SIZE REP MOVSB ; DO IT POP DS ; RESTORE CALLER'S DS POP ES ; RESTORE CALLER'S ES POPF ; RESTORE CALLER'S FLAGS RET ; RETURN TO CALLER eject ;***************************************************** ;* * ;* WRITEHST performs the physical write to the host * ;* disk, while READHST reads the physical disk. * ;* * ;***************************************************** writehst: mov AX,wtdmamod + fdc_write jmps r_w_common ; readhst: mov AX,rddmamod + fdc_read r_w_common: mov rdwtcmd+fcto_cmd,AL ; set function code mov CX,hstsiz-1 or CH,AH ; set DMA direction ; set DMA parameter mov AX,offset hst_buf mov dmapara,AX ; set DMA offset address mov AX,CS mov dmapara+2,AX ; set DMA segment address mov dmapara+4,CX ; set DMA direction and length ; ; set unit number to FDC command tables mov AL,hst_dsk ; unit number mov rdwtcmd+fcto_unt,AL mov rcalcmd+fcto_unt,AL mov sdscmd+fcto_unt,AL ; set track address to FDC command tables mov AL,byte ptr hst_trk mov rdwtcmd+fcto_c,AL ; set sector address to FDC command table mov AL,hst_sec mov BX,offset transct xlat transct shr AL,1 mov rdwtcmd+fcto_r,AL ; set head address to FDC command table mov AL,0 jnb rwhst10 inc AL or rdwtcmd+fcto_unt,fdc_hd_bit rwhst10: mov rdwtcmd+fcto_h,AL outer_retry: ; check device status call snsdvs ; sense device status mov CL,fer_nrd * 2 jnz rwhsterr ; drive not ready ; check whether selected device has been recalibrated or not mov AL,hst_dsk mov AH,0 mov BX,offset rcalflg add BX,AX test byte ptr [BX],0FFh jnz rwhst30 ; it has been recalibrated push BX call seekhome ; recalibrate pop BX jnz rwhsterr ; track 00 not found mov byte ptr [BX],0FFh rwhst30: ; read or writ access mov BX,offset rdwtcmd mov DX,offset dmapara call access ; execution jnb rwhst_ner_ret ; error rwhsterr: cmp CL,2 * fer_nc jnz rwhster1 push CX call seekhome pop CX rwhster1: JMPS BADRET ; <<<<<<<<<<<<<<<<<<<<<<<<<<<< ; rwhst_ner_ret: sub AL,AL rwhst_ret: and al,al jnz badret mov al,0 ret badret: mov al,1 ret wboot_c: db 0cch ; breakpoint for sid86 eject access: mov erflag,0 mov retry,rtrycnt ; set retry counter mov last_com,BX ; save BX mov last_dma,DX ; save DMA parameter address mov AX,fcto_unt[BX] mov word ptr seekcmd+fcto_unt,AX access1: mov BX,offset seekcmd call execute ; seek jnz access2 ; error detected mov BX,last_dma ; DMA parameter table address call setup_dma mov BX,last_com ; restore BX call execute ; read or write mov AH,AL ; ST0 mov AL,0 out dmamode,al ; CH_0 DMA disabled mov CL,AL jz acs_ret ; no error detected access2: dec retry jnz access1 ; retry ; accerr: mov AL,rsltreg ; ST0 mov AH,AL and AH,0C0h cmp AH,40h jnz aer60 ; null error ; mov CL,fer_nrd test AL,st0_nr ; test NR bit jnz aer70 ; device not ready ; mov CL,fer_0nf test AL,st0_ec ; test EC bit jnz aer70 ; track 00 not found ; mov CL,fer_sek test AL,st0_se ; test SE bit jnz aer70 ; seek error ; mov AX,word ptr rsltreg+1 ; AL=ST1 , AH=ST2 test AL,st1_ma ; test MA bit jz aer40 mov CL,fer_ndam test AH,st2_md ; test MD bit jnz aer70 ; lost data (missing address mark in data field) mov CL,fer_nam jmps aer70 ; address error (missing address mark) ; aer40: mov CL,fer_nwt test AL,st1_nw ; test NW bit jnz aer70 ; write fault ; test AL,st1_nd ; test ND bit jz aer50 mov CL,fer_badc test AH,st2_bc ; test BC bit jnz aer70 ; bad track ; mov CL,fer_nc test AH,st2_nc ; test NC bit jnz aer70 ; track not found mov CL,fer_nd jmps aer70 ; sector not found ; aer50: test AL,st1_de ; test DE bit jz aer56 mov CL,fer_dcrc test AH,st2_dd ; test DD bit jnz aer70 ; data CRC error mov CL,fer_icrc jmps aer70 ; ID CRC error ; aer56: mov CL,fer_ddam test AH,st2_cm ; test CM bit jnz aer70 ; deleted record ; aer60: ; null error mov CL,fer_nul ; aer70: mov AL,CL mov erflag,AL add CL,CL stc acs_ret: ret ; ; ; execute: mov AL,fcto_unt[BX] and AL,11b ; unit number mov rqdisk,AL call sndcm_sfdi ; send command to FDC exec_10: call getrslt ; get result register from FDC mov AL,rsltreg ; 1'st result mov AH,AL and AH,11b cmp AH,rqdisk jnz exec_10 and AL,0C0h ; error check ret seekhome: mov BX,offset rcalcmd call execute jz seekhome_end mov BX,offset rcalcmd call execute jz seekhome_end call accerr or AL,0FFh seekhome_end: ret ; ; ; snsdvs: mov BX,offset sdscmd call sndcm_sfdi mov AH,1 call grsl20 mov AL,rsltreg and AL,st3_ft + st3_ry xor AL,st3_ry ret ; ; ; sndcm_sfdi: call snsfdint ; sense FD interrupt jz sendcom push BX call getrslt pop BX sendcom: mov AH,[BX] ; command length sendcom1: in AL,fdcsts ; FDC status add AL,AL jnb sendcom1 inc BX mov AL,[BX] out fdcparm,AL ; command out dec AH jnz sendcom1 ; continue ret eject ; the following code is called to wait for the disk operation to ; complete. in a single user operating system this would be ok ; but under concurrent, it would be more social to the other ; processes to give up here. first we will poll here, then later ; we will use real interrupts. getrslt: ; the following code is suspended because it is not social ; call snsfdint ; sense FD interrupt ; jz getrslt mov al,fdint_sw and al,al jz no_fd_int ; floppy disk interrupt option push cx push dx mov dx,fdc_flag call flagwait pop dx pop cx jmps fd_go_ahead no_fd_int: ; floppy disk polled option push dx mov dl,diskst1_poll_no call poll pop dx ; jmps fd_go_ahead fd_go_ahead: eject mov AH,7 in AL,fdcsts and AL,10000b ; check CB bit jnz grsl20 ; input result register ; out sense interrupt status mov BX,offset siscmd ; bx ==> command bytes call sendcom ; sense int. status mov AH,2 ; # bytes in result of sense int stat cmd grsl20: mov BX,offset rsltreg ; bx ==> destination for result bytes grsl30: in AL,fdcsts ; byte waiting? add AL,AL ; jnb grsl30 in AL,fdcrslt mov [BX],AL inc BX dec AH jnz grsl30 ret eject setup_dma: ; BX = parameter table address ; parameter ; dw offset address ; dw segment address ; dw DMA direction + data length - 1 ; mov AL,21h out dmamode,AL ; mode (channel_0 enable) mov AX,[BX] ; offset mov CX,2[BX] ; segment mov DX,CX shl CX,1 shl CX,1 shl CX,1 shl CX,1 shr DH,1 shr DH,1 shr DH,1 shr DH,1 add AX,CX adc DH,DL sub DH,DL out dma0adr,AL ; set addr. (0--7) mov AL,AH out dma0adr,AL ; set addr. (8--15) mov AL,DH out dma0seg,AL ; set addr. (16--19) mov AX,4[BX] out dma0cnt,AL ; set count (0--7) mov AL,AH out dma0cnt,AL ; set count (8--15) ret eject dseg ;********************************************* ;* * ;* Data Areas * ;* * ;********************************************* errtbl dw er0,er1,er2,er3,er4 dw er5,er6,er8,er8,er9 dw er4,er11,er12,er13,er14 ; er0 db cr,lf,' : Null Error ??',0 er1 db cr,lf,' : Not System Disk:',0 er2 db cr,lf,' : Drive Not Ready:',0 er3 db cr,lf,' : Recalibrate Error:',0 er4 db cr,lf,' : Seek Error:',0 er5 db cr,lf,' : Data Address Mark Not Found:',0 er6 db cr,lf,' : ID Address Mark Not Found:',0 er8 db cr,lf,' : Write Protected:',0 er9 db cr,lf,' : Bad Track:',0 er11 db cr,lf,' : Sector Not Found:',0 er12 db cr,lf,' : Data Field CRC Error:',0 er13 db cr,lf,' : ID Field CRC Error:',0 er14 db cr,lf,' : Deleted Record:',0 ; ; ; sector translation table ; transct db 01*2+0,02*2+0,03*2+0,04*2+0 db 05*2+0,06*2+0,07*2+0,08*2+0 db 09*2+0,10*2+0,11*2+0,12*2+0 db 13*2+0,14*2+0,15*2+0,16*2+0 db 01*2+1,02*2+1,03*2+1,04*2+1 db 05*2+1,06*2+1,07*2+1,08*2+1 db 09*2+1,10*2+1,11*2+1,12*2+1 db 13*2+1,14*2+1,15*2+1,16*2+1 ; ; rdwtcmd db 9 ; length db 0 ; function code db 0 ; unit number db 0 ; track address db 0 ; head address db 0 ; sector address db n ; record (sector) length db eot ; end of trak db gpl ; gap length db dtl ; data length rcalcmd db 2 ; length db fdc_recal ; recalibrate function code db 0 ; unit unmber seekcmd db 3 ; length db fdc_seek ; seek function code db 0 ; unit number db 0 ; track address siscmd db 1 ; length db fdc_sis ; sense interrupt status function code sdscmd db 2 ; length db fdc_sds ; sense device status function code db 0 ; unit number rcalflg db 0,0,0,0 ; recalibrate flag ; retry rb 1 ; retry counter last_com rw 1 last_dma rw 1 dmapara rw 3 rsltreg rb 7 rqdisk rb 1 hst_dsk rb 1 ; host disk number hst_trk rw 1 ; host track number hst_sec rb 1 ; host sector number hst_seg rw 1 ; segment of destination hst_off rw 1 ; offset of destination erflag rb 1 ; error reporting dma_seg rw 1 ; last dma segment dma_off rw 1 ; last dma offset hst_buf rb hstsiz ; host buffer disk_busy db 0 ; disk busy flag ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;