title 'Unskew / Reskew' include exerror.equ include system.lib include diskhdr.equ FIRST_CALL_FLAG equ 01H dseg extrn disk_modes:byte cseg public read_write extrn current_reskew:word extrn io_select:near extrn idrive:byte, itrack:word, isector:byte,idmaoff:word, idmaseg:word ;---------- read_write: ;unskews and reads or writes multi sectors ;---------- ; ; input: SI = read or write routine address ; ; output: AX = return code mov cl, idrive mov dl, FIRST_CALL_FLAG ; this is not the first select call io_select ;get DPH address or bx,bx! jnz dsk_ok ;check if valid ret_error: mov ah,ATTA_FAILED mov al,1 ; return error if not ret dsk_ok: mov ax,xlt[bx] mov xltbl,ax ;save translation table address mov bx,dpb[bx] push bx xor bx,bx mov bl,idrive mov bl,disk_modes[bx] cmp bl,0 ; Is this a CCP/M DPB? pop bx jz yes1 add bx,12 ; add offset to make DOS DPB look like CCP/M yes1: mov ax,spt[bx] mov maxsec,ax ;save maximum sector per track mov cl,psh[bx] mov ax,128 shl ax,cl ;compute physical record size mov secsiz,ax ; and save it call initdmatbl ;initialize dma offset table cmp mcnt,0 je rw_sects rw_1: mov ax,sector ;is sector < max sector/track cmp ax,maxsec! jb same_trk call rw_sects ; no - read/write sectors on track call initdmatbl ; reinitialize dma offset table inc track ; next track xor ax,ax mov sector,ax ; initialize sector to 0 same_trk: mov bx,xltbl ;get translation table address or bx,bx! jz no_trans ;if xlt <> 0 xlat al ; translate sector number no_trans: xor bh,bh mov bl,al ;sector # is used as the index shl bx,1 ; into the dma offset table mov ax,dmaoff mov dmatbl[bx],ax ;save dma offset in table add ax,secsiz ;increment dma offset by the mov dmaoff,ax ; physical sector size inc sector ;next sector dec mcnt ;decrement multi sector count jnz rw_1 ;if mcnt <> 0 store next sector dma rw_sects: ;read/write sectors in dma table mov ah,DMA_OVERRUN mov al,1 ;preset error code xor bx,bx ;initialize sector index rw_s1: cmp current_reskew, 0 je no_reskew push bx! push ax mov ax, bx mov bx, current_reskew mov ah, 0 xlat al mov di, ax pop ax! pop bx jmps re_skew_1 no_reskew: mov di,bx re_skew_1: shl di,1 ;compute index into dma table cmp word ptr dmatbl[di],0ffffh je no_rw ;nop if invalid entry push bx! push si ;save index and routine address mov ax,track ;get track # from IOPB mov itrack,ax mov ax,di ;sector # is index value shr ax, 1 mov isector,al mov ax,dmatbl[di] ;get dma offset from table mov idmaoff,ax mov ax,dmaseg ;get dma segment from IOPB mov idmaseg,ax call si ;call read/write routine pop si! pop bx ;restore routine address and index or al,al! jnz err_ret ;if error occured return no_rw: inc bx ;next sector index cmp bx,maxsec ;if not end of table jb rw_s1 ; go read/write next sector err_ret: ret ;return with error code in AL eject initdmatbl: ;initialize DMA offset table ;---------- mov di,offset dmatbl mov cx,maxsec ;length = maxsec + 1 sectors may inc cx ; index relative to 0 or 1 mov ax,0ffffh push es ;save UDA push ds! pop es rep stosw ;initialize table to 0ffffh pop es ;restore UDA ret dseg ;***************************************************** ;* ;* DISK DATA AREA ;* ;***************************************************** xltbl dw 0 ;translation table address maxsec dw 0 ;max sectors per track secsiz dw 0 ;sector size dmatbl rw 50 ;dma address table end