eиы‹іи ѕ…иоµЉµиуѕЌиЯµЉ¶идѕ—иРЉ&·ичй- .Ж±й]я€©ѕ±иіЂ>Ґu№@їdЊИЋА°ьуЄЖҐяђиґsй•№изrх°ў_єЂ ±А‹8 и_r±Ђ Rў]цР$РАРА БЉИ © БўW Sў^Ж`ђжU `<tщ<яtщГЉ©Рв¶»IЪГЉЗцРЉшЉГцРЉШCГ‡Ъиня‡ЪЪГЉЗ:ЖtГЉГ:ВГя Morrow Hard Disk Controller Driver of 10-21-85 Copyright (c) 1985 Tarbell EьЉ„Аtи6FлуГRєяяѓй BsъѓБ ‡СtимяЉКЂБ0ЉБиZГµ°0РДsюАиюНuсГPQіґНYXГД>Ў±Љ&% #цд‹ШЎ§єчу‹ШГЋ‹&^_ZY[XЛu's. ; Static request header equ's. srh equ 0 ; base. srh_len equ 13 ; length. srh_len_fld equ srh ; length field. srh ; pointer to bpb length. units equ srh+srh_len ; pointer to number of units. end_ptr_off equ units+1 ; ending adr pointerr segment. ; Bios parameter block. ; These initial values allow first sector to get read. ; (values shown are for cmi-19bpb ; bios parameter block offset. ; Function Table. funtab label byte dw init ; initialization. dw media_check ; mediata area. partab equ $ ; parameter table from dos. dtaadr label dword dtaoff dw ? ; transfer address offset. dtaseg dw ?ount. count_len equ 2 ; byte/sector length. ssn equ count+count_len ; starting sector number. ssn_len equ 2 ; starting se ; pointer to device strategy. interpt dw devint ; pointer to device interrupt handler. devname db 1 ; number of block devic number of sectors for each fat. hrdspt dw 17 ; sectors per track. hrdtpc dw 6 ; number of heads (tracks per cylinder). hidut. ; messages. iemsg db cr,lf,'Initialization',0 inpmsg db cr,lf,'Read',0 outmsg db cr,lf,'Write',0 ermsg db ' error es_fld equ srh+5 ; reserved area field. md equ srh+srh_len ; media descriptor byte. md_len equ 1 ; media descriptor lengtptr_seg equ bpb_ptr_off+2 ; bpb pointer segment. hdisk proc far assume cs:cseg,es:cseg,ds:cseg begin: start equ $ ;or. db 2 ; sectors per allocation unit. dw 66h ; number of reserved sectors. db 2 ; number of file allocation tables. on-desctructive input no wait. dw in_stat ; input status. dw in_flush ; input flush. dw output ; output (write). dw ou_ucd_fld equ srh+1 ; unit code field. srh_ccd_fld equ srh+2 ; command code field. srh_sta_fld equ srh+3 ; status field. srh_r offset. end_ptr_seg equ end_ptr_off+2 ; ending adr pointer segment. bpb_ptr_off equ end_ptr_seg+2 ; bpb pointer offset. bpb_ and morrow controller) ; The correct block then gets put into here from buffer. bpb equ $ hrdbps dw 512 ; bytes per secta check. dw build_bpb ; build bios parameter block. dw ioctl_in ; ioctl input. dw input ; input (read). dw nd_input ; n ; transfer address segment. totsec dw ? ; number of sectors to transfer. sector dw ? ; starting sector number. vidoff dw ctor length. ret_byte equ md+md_len ; byte returned address. bpba_ptr equ dta+dta_len ; pointer to bpb. bpba_ptr_len equ 4 es. db 7 dup(?) ; 7 bytes of filler. ; reqhdr label dword rhoff dw ? ; request header offset. rhseg dw ? ; request headeden dw 66h ; number of hidden sectors. ; bios parameter block pointer array (one entry for each device) bpb_ptr dw offset on hard disk:' db cr,lf,'Cylinder ',0 hedmsg db ', head ',0 secmsg db ', sector ',0 statmsg db ', status ',0 ; Common dh. dta equ md+md_len ; disk transfer address. dta_len equ 4 ; disk transfer length. count equ dta+dta_len ; byte/sector c Device Header. nextdev dd -1 ; pointer to next device. attrib dw 2000h ; block device (non-ibm format) strateg dw devstrat dw 2048 ; number of directory entries. dw 079ech ; total number of sectors. db 0f8h ; media descriptor byte. dw 3dh ;t_verify ; output (write) with verify. dw out_stat ; output status. dw out_flush ; output flush. dw ioctl_out ; ioctl outp? ; volume id offset. vidseg dw ? ; volume id segment. bufoff dw ? ; buffer offset (in controller driver). ; Current va Device Interrupt Handler. devint: ; save registers. cld push ds push es push ax push bx push cx push dx pusht function. ;---------------- ; Initialization. ;---------------- init: mov es:byte ptr units[bx],nlu lea dx,bpb_pt; si = bpb address in buffer. mov di,offset bpb ; di = local bpb address. mov cx,19 ; cx = number of bytes to move. cldv es:dta[bx],dx ; offset of sector buffer. mov es:dta+2[bx],cs or es:word ptr srh_sta_fld[bx],0100h ; status done. jmp ex stkoff dw ? ; old stack offset. stkseg dw ? ; old stack segment. ; Device Strategy. devstrat proc far mov cs:rhseg,esd function. mov al,es:[bx]+2 ; al = function byte. rol al,1 ; al = table offset. lea di,funtab ; di = function table o or es:word ptr srh_sta_fld[bx],100h ; move bios parameter block from buffer to local storage. ; note: mapper routine ret----------------------- ; Build Bios Parameter Block. ;---------------------------- build_bpb: lea dx,bpb ; dx = bpb potry counter. ; Error parameters returned from driver. ercyl dw ? ; cylinder number. erhead db ? ; head number. ersect dmov ax,offset stktop ; get local stack pointer. mov sp,ax mov ax,cs ; get local stack segment. mov ss,ax ; es:bx = rptr_off[bx],dx ; set ending address. mov es:end_ptr_seg[bx],cs mov cl,0 ; cl = drive number. push bx ; save bx, es. mp errex ; error exit. ;------------- ; Media Check. ;------------- media_check: mov es:byte ptr ret_byte[bx],1 ; lues. nsects dw ? ; sectors left to transfer on cylinder. verify db 0 ; 0=no verify, 1=verify after write. ercnt db ? ; re di push si ; set up local stack. mov stkoff,sp ; save old stack pointer. mov stkseg,ss ; save old stack segment. r ; set address of bpb pointer array. mov es:bpb_ptr_off[bx],dx mov es:bpb_ptr_seg[bx],cs mov dx,offset eop mov es:end_ ; direction = forward. rep movsb ; now move it. jmp exit initer: mov si,offset iemsg ; print 'Intitialization' jit ; restore registers and return. ;------------------------ ; Non-Supported Commands. ;------------------------ io ; save segment of request header pointer. mov cs:rhoff,bx ; save offset of request header pointer. ret devstrat endp ;ffset. xor ah,ah ; ax = table offset. add di,ax ; di = function table entry offset. jmp word ptr [di] ; jump to selecurns offset of buffer with bpb in si. mov ax,cs ; es = cs. mov es,ax mov bufoff,si ; save buffer offset. add si,11 inter. mov es:bpba_ptr[bx],dx ; save ptr to bpb table. mov es:bpba_ptr+2[bx],cs mov dx,bufoff ; dx = buffer address. mob ? ; sector number. erstat db ? ; error status. ; Stack Stuff. dw 50 dup(?) ; stack area. stktop equ $ ; stack top. equest header address. mov ax,cs ; ds = cs. mov ds,ax les bx,reqhdr ; es:bx = request header adr. ; jump to selectepush es call mapper ; initialize hard disk controller. pop es ; restore es, bx. pop bx jc initer ; hop if error. return byte = 1. or es:word ptr srh_sta_fld[bx],0100h ; set done bit. jmp exit ; restore registers and return. ;-----ctl_in: ioctl_out: nd_input: in_stat: in_flush: out_stat: out_flush: jmp exit ; restore registers & return. ; Geret getparm endp ;----------- ; Disk Read. ;----------- input: call getparm ; get entry parameters. inloop: cal ah = write code. call findalt ; perform the transfer. jc outer ; set error flag if carry. inc sector ; increment sesave sector number. mov erstat,al ; save status code. call prtmsg ; print message at si. les bx,reqhdr ; es:bx = reque call prtmsg mov ah,erstat ; print status bits. call prtbin jmp exit ; restore registers and return. ;---------t disk transfer address. mov cs:dtaoff,ax mov ax,es:word ptr dta+2[bx] mov cs:dtaseg,ax mov ax,es:word ptr count[bx] ; gr: mov si,offset inpmsg ; print 'Read' jmp errex ; process error and return. ;------------ ; Disk Write. ;--------h ; set status done no error. jmp exit ; restore registers & return. outer: mov si,offset outmsg ; print 'Write' ; pr, head '. call prtmsg mov ch,0 ; print head number. mov cl,erhead call prtdec mov si,offset secmsg ; print ', sectorsfer address segment. ; nsects = number of sectors to transfer. ; sector = starting sector number. ; vidoff = volume id of ; exit with error if carry. inc sector ; increment sector number. add dtaseg,20h ; add one sector to segment. dec nsec back if not zero. sethdr: les bx,reqhdr ; es:bx = request header adr. mov ax,totsec ; ax = original sector count. sub riginal sector count. sub ax,nsects ; ax = sectors actually transferred. mov es:count[bx],ax mov si,offset ermsg ; printt entry parameters. ; Entry: parameters are at es:bx. ; Exit: dtaoff = disk transfer address offset. ; dtaseg = disk tranl setreg ; put parameters into registers. mov ah,1 ; ah = read code. call findalt ; perform the transfer. jc inper ctor number. add dtaseg,20h ; add one sector to segment. dec nsects ; decrement number of sectors. jnz outloop ; loopst header adr. mov ax,8004h ; set crc error for now. mov es:srh_sta_fld[bx],ax ; put into header. mov ax,totsec ; ax = o------------------- ; Output (Write) with Verify. ;---------------------------- out_verify: mov cs:byte ptr verify,1 ; seet transfer count. mov totsec,ax mov nsects,ax mov ax,es:word ptr ssn[bx] ; get starting sector number. mov sector,ax ---- output: call getparm ; get entry parameters. outloop: call setreg ; put parameters into registers. mov ah,2 ;ocess errors and exit. errex: mov ercyl,bx ; save cylinder requested. mov erhead,dh ; save head number. mov ersect,dl ; '. call prtmsg mov ch,0 ; print sector number. mov cl,ersect call prtdec mov si,offset statmsg ; print ', status '.fset. ; vidseg = volume id segment. getparm proc near ; move parameters into local table. mov ax,es:word ptr dta[bx] ; gets ; decrement number of sectors. jnz inloop ; loop back if not zero. jmp sethdr ; restore registers & return. inpeax,nsects ; ax = sectors actually transfered. mov es:count[bx],ax ; save it for return. or es:word ptr srh_sta_fld[bx],100 ' error on hard disk:' call prtmsg mov cx,ercyl ; print cylinder number. call prtdec mov si,offset hedmsg ; print 't the verify flag. jmp output ; do the rest above. hctlr ; print message at cs:si. ; message is terminated by onversion complete. call prtdec ; recursive call. prtdon: mov cl,dl ; get bcd value. add cl,'0' ; add ascii bias. mrite character on screen. pop cx ; restore registers. pop ax ret conout endp ; Set parameters into registers for trestore rest of registers. pop si pop di pop dx pop cx pop bx pop ax pop es pop ds ret ; return. eop: hcalls to mwseek, home. ; 8-13-85: separated drive equ's from controller driver. ; 8-18-85: added more disk parameter blocke on stack. mov dx,-1 ; becomes number / radix. prtsub: sub cx,10 ; subtract 10. inc dx ; increment remainder. jnc ; decrement bit counter. jnz prtlop ; loop til done. ret prtbin endp ; print character in al on screen. conout proc ax. div bx ; dx = sector number. mov bx,ax ; bx = cylinder number. ret setreg endp ; Exit: Restore registers ; *********** BEGINNING OF MORROW HARD DISK CONTROLLER DRIVER ******* ; EQU's specific to each drive are found in files begprtex ; exit if so. call conout ; print character on screen. inc si ; point si at next character. jmp prtmsg ; loop ti binary form. prtbin proc near mov ch,8 ; 8 bits in a byte. prtlop: mov al,'0' ; assume bit is 0. rol ah,1 ; test ne ptr hrdtpc ; ah = tracks per cylinder (heads). mov al,byte ptr hrdspt ; al = sectors per track. mul ah ; ax = sectors perееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееееa zero. prtmsg proc near cld ; direction = forward. mov al,[si] ; al = byte. test al,al ; is it end of message? jz ov al,cl ; al = char to print. call conout ; print char on screen. pop dx ret prtdec endp ; print number in ah inansfer. setreg proc near les di,dtaadr ; es:di = transfer address. mov cl,0 ; cl = hard disk drive number. mov ah,bytedisk endp cseg ends end begin s. ; 8-22-85: put in set up for 4 logical/physical drives. ; 8-24-85: tightened code in mwptr routine. ; also disablprtsub ; loop till carry out. add cx,10 ; add radix back in. xchg dx,cx ; switch new/current. jz prtdon ; hop if cnear push ax ; save registers. push cx mov bl,1 ; bl = color. mov ah,14 ; ah = code for tty write. int 10h ; w