eject ; Dec 3, 1983 reorg14 equ offset $ ; save for code start ; this module now also includes the FIDDS hooks ;**************************************************************** ;* * ;* HARD DISK DATA STRUCTURES * ;* * ;**************************************************************** ; GLOBAL CONSTANTS SLOW_SEEK equ 0 ;if -1, forces 3 ms step rate IBM_SYS_ID equ 0AA55h ;partition label id word HD_SYS_ID equ 0DBh ;(yours truly) HD_VFY_ERR equ 0AAh ;artificial ROS error code block_size equ 2048 ;remap block size ;also used for dpb phys sector ; XT HARD DISK DATA STRUCTURE DEFINITIONS DSEG ; This IOPB is used to communicate with the ROS access routine "hd_rom" ; Note:some parameters are not EXACTLY as defined by IBM. org 0 ;IBM_iopb STRUCT IBM_fn rb 1 ;ibm ROS function code (0 - 14d) IBM_errcode rb 1 ;what is returned by ROS in AH IBM_lun rb 1 ;unit number (0h or 1h) IBM_head rb 1 ;head number only (0 - maxheads) IBM_cylinder rw 1 ;entire cylinder number (0 - maxcyl) IBM_sector rb 1 ;sector number only (0 - maxsector) IBM_count rb 1 ;number of sectors to xfer (1 - 80h) IBM_xfer_ofs rw 1 ;transfer buffer offset address IBM_xfer_seg rw 1 ;transfer buffer segment address IBM_XFER_PTR equ dword ptr ibm_xfer_ofs HD_IOPB_SIZE equ offset $ ;IBM_iopb ENDS ; definition of IBM XT hard disk partition table record org 0 ;XT_PT_record STRUCT XT_PT_bootfl rb 1 ;80h if bootable XT_PT_start_head rb 1 ;partition start info XT_PT_start_sector rb 1 ; high 2 bits of cyl also XT_PT_start_cylinder rb 1 ; low 8 bits only XT_PT_system rb 1 ;system indicator (DB for cpm) XT_PT_end_head rb 1 ;partition end info XT_PT_end_sector rb 1 ; high 2 bits of cyl also XT_PT_end_cylinder rb 1 ; low 8 bits only XT_PT_rel_sect rw 2 ;start in absolute sectors XT_PT_size rw 2 ;size in sectors XT_PT_REC_SIZE equ offset $ ;XT_PT_record ENDS ; definition of the overall IBM XT hard disk partition sector org 0 ;XTLBL_table STRUCT XTLBL_code rb 1beh ;contains bootstrap code XTLBL_part1 rb XT_PT_REC_SIZE ;partition record 1 XTLBL_part2 rb XT_PT_REC_SIZE ;partition record 2 XTLBL_part3 rb XT_PT_REC_SIZE ;partition record 3 XTLBL_part4 rb XT_PT_REC_SIZE ;partition record 4 XTLBL_id rw 1 ;contains signature (0aa55h) ;XTLBL_table ENDS ; This defines the CP/M label for a volume org 0 ;HDLB_label STRUCT HDLB_chks rw 1 ;checksum HDLB_id rb 31 ;contains dr copyright HDLB_pstart rw 1 ;partition start cylinder HDLB_plength rw 1 ;partition length in cylinders HDLB_nheads rb 1 ;number of heads HDLB_ibm_spt rb 1 ;ibm sectors per track HDLB_cpm_options rb 1 ;lsb = 1 means write verify HDLB_cpm_nsect rb 1 ;no longer used HDLB_cpm_dpb: ;DPB HDLB_cpm_spt rw 1 ;as per usual abbreviations HDLB_cpm_bsh rb 1 HDLB_cpm_blm rb 1 HDLB_cpm_exm rb 1 HDLB_cpm_dsm rw 1 HDLB_cpm_drm rw 1 HDLB_cpm_al0 rb 1 HDLB_cpm_al1 rb 1 HDLB_cpm_cks rw 1 HDLB_cpm_off rw 1 HDLB_cpm_psh rb 1 HDLB_cpm_prm rb 1 HDLB_cpm_rsvd rw 2 ;for future use HDLB_cpm_fudge rw 1 ;for cpm_off shift remainder HDLB_map_ctl: ;remap table begins HDLB_map_spb rw 1 ;# of ibm sectors per remap block HDLB_map_max rw 1 ;# total length of table in entries HDLB_map_cnt rw 1 ;# of currently active entries HDLB_map_spare_end rw 1 ;last spare cpm relative block number HDLB_map_table rw 1 ;beginning of remap table entries HD_LABEL_SIZE equ 512 ;HDLB_label ENDS org 0 ; this defines a table entry in the XIOS hard disk information table. ; it stores current status and limit information for the physical disk ;HDINF_vector STRUCT HDINF_exists rb 1 ;means that hardware exists HDINF_logged rb 1 ;currently logged in HDINF_fixed rb 1 ;login indicated it is a fixed drive HDINF_heads rb 1 ;number of heads (according to ROS) HDINF_spt rb 1 ;sectors/track (according to ROS) HDINF_cyl rw 1 ;max cylinders (according to ROS) HDINF_enddir rw 1 ;last block of dir (in remap units) HDINF_label_ofs rw 1 ;points to its label buffer HDINF_SIZE equ offset $ ;HDINF_vector ENDS eject ;**************************************************************** ;* * ;* HARD DISK DRIVER ROUTINES * ;* * ;**************************************************************** ; These routines hook into M.P. Vano's drivers for CCP/M-86 ; version 1.0. Every attempt has been made to mess with ; his code as little as possible. Some changes were made ; for different sector sizes and different dph's, but most ; of it is in the form envisioned by its creator. ; A new parameter HDLB_cpm_fudge has been added to take ; care of a problem arising in disk drives with other than ; a multiple of 4 heads. Grouping tracks in fours to fool ; CP/M into handling 2K physical sectors creates a problem ; in this case. The 2 bit shift of HDLB_cpm_off can relult ; in bits falling on the floor. HDLB_cpm_fudge saves those ; bits, and adds them back when converting to physical ; track number in hd_io: cseg org reorg14 ; Select hard disk, save spt for multi sector count select_hd: sub cl,byte ptr num_flop mov aux_drive,cl ; save drive code mov aux_code,dl ; and which select mov ax,0 ; select function code call hd_driver ; login and select test ax,ax ; if bad select jz sel_hd1 ; then skip sector count mov si,.8[bx] ; get dpb pointer mov ax,[si] ; get sectors per track mov max_sector,ax ; and save for mcnt mov ax,bx ; restore dph sel_hd1: ret ; Hard disk read routine read_hd: mov aux_func,2 ; read function code jmp read_write_hd ; jump to shared code ; Write to hard disk write_hd: mov aux_func,4 ; write function code read_write_hd: ; shared code call aux_param_set ; set up param block mov ax,num_flop sub aux_drive,al ; correct the drive code rw_hd1: mov ax,aux_func ; restore function code call hd_driver test al,al ; check for errors jnz rw_hd3 ; skip if bad dec aux_code ; check multi-count first jz rw_hd3 ; and skip if done mov ax,aux_sector ; increment the current inc ax ; sector (and track if cmp ax,max_sector ; necessary) for multi jb rw_hd2 ; sector operations inc aux_track sub ax,ax ; reset sector rw_hd2: mov aux_sector,ax add aux_dma_s,128 ; add to seg to avoid overflow jmps rw_hd1 ; back for another sector rw_hd3: ret ; This routine sets up the "aux" parameter block ; It is shared by the FIDDS driver aux_param_set: mov al,drive mov aux_drive,al mov al,mcnt mov aux_code,al ; use code for multi-count mov ax,track mov aux_track,ax mov ax,sector mov aux_sector,ax mov ax,dma_seg mov aux_dma_s,ax mov ax,dma_off mov aux_dma_o,ax ; save the works ret eject ; ; XTCODE.LIB: XT INTERIM XIOS HARD DRIVER CODE MODULE ; ; written for DRI by M.P. Vano ; Vano Associates, Inc. ; 24 May 1983 ; ; ; This driver uses the XT ROM BIOS and so cannot relinquish the CPU ; during disk IO operations. This was done at the request of DRI to ; ensure compatibility with the ever-mysterious future plans of IBM. ; ; NOTE that although many data structures and routines of a highly ; general nature are used by this module, the behaviour of this driver ; is not defined except within the frame of reference of the existing ; 4 disk drives set by drive parameters in the XT ROS tables. In ; particular, the use of REMAP blocks of a size other than 2k will not ; succeed unless the XIOS is re-assembled for a different buffer size. ; In addition, binary multiples only are assumed for the ratio of ; CP/M to physical sector sizes supported. ;**************************************************************************** HD_HW_INTERRUPT equ 0dh ;IBM controller interrupt HD_INTERRUPT equ 13h ;IBM entry point for hard disk HD_PARMS_INTERRUPT equ 41h ;points to hard disk parms HD_FD_INTERRUPT equ 40h ;ROS revectors floppy io here HD_ROS_DATASEG equ 40h HD_OPTION_ADDR equ 76h ;ibm controller option control HD_PTR equ dword ptr HD_INTERRUPT * 4 hd_control_byte equ byte ptr HD_ROS_DATA_SEG*16 + HD_OPTION_ADDR ; Hard disk IO calls get vectored here from AUX DISK handler. The entry ; conditions are similar to an ATTACH-A-MATIC except that the aux drive ; parameter pointer is NOT setup. ; ; The GLOBAL XIOS variables AUX_CODE, AUX_TRACK, AUX_DRIVE,AUX_SECTOR ; AUX_LONGWORD must be directly accessed to specify the operation. ; AX has the function to execute as per attach-a-matic usage. ; ; CALLS: hd_seldsk,hd_read,hd_write hd_driver: mov hd_function,ax ;save for debug use push es ! push ds mov hd_uda,es mov bx,ax ;save fnc code for jump mov ax,HDINF_SIZE ;usually correct mov cl,AUX_DRIVE ! and cl,1 ;keep in index range mul cl ;si--> info vector[AUX_DRIVE] mov si,offset hd_disk_info add si,ax ; stack switch has been deleted here call hd_fn_table[bx] ;do case(fn) ; pop ds ! pop es ret ; function # 0 2 4 hd_fn_table dw hd_seldsk, hd_read, hd_write ; if (!logged_in(info_ptr)) return 0 else return &(dph_array[vol]) ; At entry, SI--> info array ptr for that drive and ; external globals AUX_DRIVE and AUX_CODE ; Since AUX_DRIVE is always valid when called, SI's HDINF pointer ; may be trusted. ; ; CALLS: hd_seldsk hd_seldsk: call hd_login ;if (!hd_login(info_ptr) return 0) or al,al mov ax,0 jz hd_seldsk_ret mov al,AUX_DRIVE ;else return &dph_array[DPH_SIZE][,vol] mov ah,dph_size mul ah add ax,offset hd_dph0 hd_seldsk_ret: mov bx,ax ret ; checks if current hard disk is logged in properly. If it is, ; it returns true. otherwise it tries to log it in and if it can't ; it returns false. The same happens for out of range requests. ; NOTE that this routine is called from INIT also. It takes as input ; the global AUX_DRIVE and the HDINF pointer for that drive in SI. ; ; CALLS: hd_get_partition,hd_read_label,hd_patch_dpb hd_login: test HDINF_exists[si],0ffh ;is the hardware there? jz hd_login_err ;if not, don't go any farther test HDINF_logged[si],1 ;has it ever been logged-in? jz hd_log_it_in ; if not, go try to do it test HDINF_fixed[si],1 ;else don't not be too hasty... jnz hd_login_ok ; labels on fixed can't change test AUX_CODE,1 ;even a removable only needs jnz hd_login_ok ;re-login on first access ; hd_log_it_in: ;really needs to be logged in mov HDINF_logged[si],0 ;mark it unlogged call hd_get_partition ;read IBM's master table or al,al jnz hd_login_err ;can't read table or no cp/m call hd_read_label ;else go look for XIOS label or al,al ;can't read or doesn't exist jnz hd_login_err call hd_patch_dpb ;fix up dpbs for ver 2 hd_login_ok: mov al,0ffh ! ret ;else tell caller we found it hd_login_err: xor al,al ! ret ;return false if we fail ; read partition table into label area and find partition if one exists ; uses cp/m label buffer as temporary bufer ; returns 0 in al if succeeds, else nz ; CALLS: hd_rom hd_get_partition: mov bx,offset hd_rd_partition_iopb ;setup iopb mov al,AUX_DRIVE ;setup fields that vary mov IBM_lun[bx],al mov IBM_cylinder[bx],0 mov IBM_sector[bx],1 ;always has label mov ax,HDINF_label_ofs[si] ;get the correct buffer mov IBM_xfer_ofs[bx],ax mov IBM_xfer_seg[bx],ds call hd_rom ;read partition table or al,al jnz hd_get_partition_ret ;oops, disk error. ; push si mov si,HDINF_label_ofs[si] ;inspect table cmp XTLBL_id[si],0aa55h ;is it there at all? jnz hd_bad_partition lea si,XTLBL_part1[si] ;scan for cp/m mov cx,4 hd_partition_hunt: cmp XT_PT_system[si],HD_SYSID ; is it our magic code? je hd_partition_found add si,XT_PT_REC_SIZE ;else keep on looking loop hd_partition_hunt jmps hd_bad_partition ;else return the bad news ; hd_partition_found: ;setup same iopb for label read mov al,XT_PT_start_cylinder[si] ;adjust the disk address mov ah,XT_PT_start_sector[si] ;fix up cylinder address rol ah,1 ! rol ah,1 ! and ah,3 mov IBM_cylinder[bx],ax mov hd_pstart_cyl,ax ;save to check later mov IBM_sector[bx],4 ;cp/m label is always here ; mov al,XT_PT_end_cylinder[si] mov ah,XT_PT_end_sector[si] rol ah,1 ! rol ah,1 ! and ah,3 mov hd_pend_cyl,ax ;save to check later test XT_PT_start_head[si],0ffh ;should start at head 0 jnz hd_bad_partition ;else exit with error mov al,XT_PT_start_sector[si] ;only 1 or 2 are legal dec al and al,not 0c1h ;ignore irrelevant bits jnz hd_bad_partition pop si ;else it must be ok xor al,al jmps hd_get_partition_ret ;so exit with success code ; hd_bad_partition: pop si mov al,0ffh hd_get_partition_ret: ret ; reads cpm label into label area and checks for integrity ; iopb has already been set up by hd_get_partition ; returns 0 in al if succeeds, else nz., ; CALLS: hd_rom,hd_check_label hd_read_label: mov bx,offset hd_rd_partition_iopb ;setup iopb call hd_rom ;try to read label or al,al ;disk error? jnz hd_read_label_ret ;(probably MICROSOFT sabotage) ; call hd_check_label ;check label's integrity or al,al jnz hd_read_label_ret ;label or programmer is strange ; mov di,HDINF_label_ofs[si] ;update HDINF mov al,0ffh ;assume fixed disk cmp HDLB_cpm_cks[di],8000h ;fixed? je hd_read_label1 ;yep, go ahead not al ;can't win them all hd_read_label1: mov HDINF_fixed[si],al ;set fixed flag as needed mov HDINF_logged[si],0ffh ;I pronounce thee "logged" xor al,al hd_read_label_ret: ret ; verifies integrity of cp/m label block of disk si--> HDLB pointer of ; returns 0 if succeeds, else nz value in ax ; CALLS: NOTHING hd_check_label: push si ! mov si,HDINF_label_ofs[si] ;get pointer to label ; push si ;checksum it first mov cx,HD_LABEL_SIZE/2 xor bx,bx ;clear checksum accum. hd_check_cks: lodsw add bx,ax loop hd_check_cks ;verify its checksum pop si jnz hd_check_error ;exit if bad checksum ; push si ! push es push ds ! pop es mov cx,length (hd_idstring) ;check the id string lea si,HDLB_id[si] mov di,offset hd_idstring repe cmpsb pop es ! pop si mov ax,0 ! je hd_check_exit ;exit here if id matches hd_check_error: ;else error mov ax,-1 hd_check_exit: pop si ret ; correct the hard disk dpb's for concurrent version 2.0 ; this changes physical sector size from 128 to 2048 bytes ; spt = old spt / 4; psh = 2; prm = 3 hd_patch_dpb: push si ; save info ptr just in case mov si,HDINF_label_ofs[si] ; point to label (and dpb's) mov cl,2 ; for divide by 4 shr HDLB_cpm_spt[si],cl ; for larger physical sectors mov ax,HDLB_cpm_off[si] and ax,0003h ; save remainder from shift mov HDLB_cpm_fudge[si],ax ; for retranslate to physical mov cl,2 shr HDLB_cpm_off[si],cl ; group tracks by 4's mov HDLB_cpm_psh[si],4 ; physical sector shift mov HDLB_cpm_prm[si],15 ; physical sector mask mov HDLB_map_spb[si],4 ; 512 * 4 = 2k block pop si ret ; hard disk physical read hd_read: call hd_xlate_request ; do block remap mov bx,offset hd_rd_iopb ; read parameters call hd_dma_check ; check for overflow jc hd_read1 ; if no problem then jmp hd_dma_io ; read right to dma hd_read1: call hd_local_io ; if dma boundary error or al,al ; read to local first jnz hd_read2 ; done if error push es ; if read is good push si ; then move to dma mov si,offset hd_local_buf les di,AUX_LONGWORD mov cx,block_size/2 rep movsw pop si pop es hd_read2: ret ; hard disk physical write hd_write: call hd_xlate_request ; do block remap mov bx,offset hd_wr_iopb ; go load iopb and do it call hd_dma_check ; check for boundary error jnc hd_write1 ; skip if dma ok push ds ; if boundary trouble then push es ; move data to local buffer push si mov di,offset hd_local_buf push ds pop es ; local destination lds si,AUX_LONGWORD mov cx,block_size/2 rep movsw pop si pop es pop ds call hd_local_io ; write from local buffer jmps hd_write2 ; skip to error check hd_write1: call hd_dma_io hd_write2: or al,al jnz hd_write_exit ; exit here if failed ; push si mov si,HDINF_label_ofs[si] test HDLB_cpm_options[si],1 pop si jz hd_write_exit ;no, just exit (al still valid) ; mov bx,offset hd_vfy_iopb ;else run verify cycle mov IBM_fn[bx],2 ;IBM read opcode call hd_local_io or al,al ;did read-after-write fail? jnz hd_write_exit ;yes, no point in comparing ; mov IBM_fn[bx],4 ;fake verify opcode for msgs push es ;else compare buffers push si les di,AUX_LONGWORD ;dma segment:offset mov si,offset hd_local_buf mov cx,block_size/2 repe cmpsw pop si pop es mov al,0 ;assume success je hd_write_exit ;if matched, exit mov IBM_errcode[bx],HD_VFY_ERR ;else fake a physical error call hd_error_handler ;and see what operator wants cmp al,'R' ;retry? je hd_write ;yep, go back to the top hd_write_exit: ret ; translate global AUX_TRACK,AUX_SECTOR and hd_disk into remapped units ; and finds alternate block if that block is in remap table ; (updates global variables hd_req_block, hd_req_sec) ; CALLS: NOTHING hd_xlate_request: push si mov si,HDINF_label_ofs[si] ;get label for this disk ; mov ax,AUX_TRACK ;ax=CPM_TRACK-cpm_offset sub ax,HDLB_cpm_off[si] mul HDLB_cpm_spt[si] ; * cpm_spt add ax,AUX_SECTOR ; + CPM_SECTOR ; ; using 2k physical sectors, ax now equals logical block number ; mov cx,HDLB_map_cnt[si] ;see if that block is in table jcxz hd_no_remap ;(skip if table is empty) push es ! mov dx,ds ! mov es,dx cld ! lea di,HDLB_map_table[si] ;by scanning table repne scasw pop es jne hd_noremap ;no, leave block number alone inc cx ! sub cx,HDLB_map_cnt[si] ;else calculate replacement mov ax,HDLB_map_spare_end[si] add ax,cx hd_noremap: mov hd_req_block,ax ;update parameter and exit pop si ret ; check dma addresses for boundary errors. set carry if bad hd_dma_check: mov ax,AUX_DMA_S ; get segment mov cl,4 ; convert to offset shl ax,cl ; ignoring ms nibble add ax,AUX_DMA_O ; add in segment add ax,block_size ; set carry on overflow ret ; entry point for read or write. transfers to and from dma buffers hd_dma_io: mov ax,AUX_DMA_O mov IBM_xfer_ofs[bx],ax ; save offset mov ax,AUX_DMA_S mov IBM_xfer_seg[bx],ax ; save segment jmps hd_io ; entry point for local read or write hd_local_io: mov IBM_xfer_ofs[bx],offset hd_local_buf mov IBM_xfer_seg[bx],ds ; local segment ; jmps hd_io ; fall through ; fills in the volume,head and cyl fields in passed IBM_IOPB from ; current request using CURRENT HDINF pointer and executes rom operation ; CALLS: hd_rom hd_io: push si mov si,HDINF_label_ofs[si] mov al,AUX_DRIVE mov IBM_lun[bx],al mov ax,hd_req_block ;back to IBM format ; mul HDLB_map_spb[si] ;ibm_block=(block * remap_spb) ; mov ch,0 ;for full divide mov cl,HDLB_ibm_spt[si] ;ibm_rel_track=ibm_block/ibm_spt xor dx,dx ! div cx ;CAUTION!! 16 bit result ; inc dl ;save remainder as ibm sector mov IBM_sector[bx],dl ; (except they start with 1) ; mov dx,HDLB_cpm_off[si] ;get fake track offset shl dx,1 ; and change it back to physical shl dx,1 ; track number add ax,dx ;correct offset add ax,HDLB_cpm_fudge[si] ;remainder from offset shift ; mov cl,HDLB_nheads[si] ;ibm_cyl= ibm_track/nheads xor dx,dx ! div cx ;CAUTION!! 16 bit result mov IBM_cylinder[bx],ax mov IBM_head[bx],dl ;ibm_head=ibm_track % nheads pop si ; jmps hd_rom ;fall through ; provides easy access to HDISK ROM ; call with ds:bx--> IBM_iopb structure as defined elsewhere ; returns zero set if succeeds, else non-zero ; CALLS: hd_error_handler hd_rom: push es ! push si ;save uda and HDINF_ptr then execute mov cx,3 ;set retry count ; hd_rom_retry: ;inner retry loop push cx ! push bx ;save retry counter & IOPB mov ah,IBM_fn[bx] mov al,IBM_count[bx] ;load up registers for ROM call mov dh,IBM_head[bx] mov dl,IBM_lun[bx] or dl,80h ;Next ANSI hard disk command standard! mov cx,IBM_cylinder[bx] ; SCRewed-Up Microcomputer xchg ch,cl ; Parameter Interface - SCRUMPI ? ror cl,1 ! ror cl,1 ; (SERIOUSLY now, why would anyone do and cl,0c0h ; something this way?) or cl,IBM_sector[bx] les bx,IBM_XFER_PTR[bx] pushf ! callf HD_ROM_ENTRY ;fake an SWI call to ROM pop bx ! pop cx ;restore IOPB ptr and retry counter mov IBM_errcode[bx],ah ;save error return mov al,0 ! jnc hd_rom1 ;and exit if no error ; push cx ! push bx ! ;reset drive on any error ?? mov ah,0dh ;registers are still ok pushf ! callf HD_ROM_ENTRY pop bx ! pop cx loop hd_rom_retry ;then try automatic retries first ; mov al,IBM_errcode[bx] ;else get error code back and exit hd_rom1: ;result shold be in al here pop si ! pop es or al,al ! jz hd_rom_done ;return if no error test hd_init_flag,1 ;if during MPM initialization, jz hd_rom_done ; return error immediately call hd_error_handler ;else report it to operator cmp al,'R' ! jz hd_rom ;does he wish to try more? hd_rom_done: ret ;else return to caller ; dummy ROM BIOS SWI used by hard disk ROM (always succeeds) ; CALLS: NOTHING hd_dummy_int: sti ! xor ax,ax ! retf 2 ; Display hard disk error and gets operator's response. ; entry: al = error code ; exit: al = 00h for ignore ; FFh for accept ; 'R' for retry hd_error_handler: mov disk_error,al ; save for sub message jmp do_disk_error ; in the floppy code eject ;******************************************************** ;* * ;* FIELD INSTALLABLE DEVICE DRIVER HOOKS * ;* * ;******************************************************** ; FIDDS select disk sel_fid: mov aux_drive,cl ; save drive number mov aux_code,dl ; and select code sub ax,ax ; ax = 0 for select jmps fidds_go ; interrupt away read_fid: call aux_param_set ; drive, track, sect, etc. mov ax,2 ; ax = 2 for read jmps fidds_go ; interrupt away write_fid: call aux_param_set ; same as for read mov ax,4 ; ax = 4 for write ; jmps fidds_go ; interrupt away ; FIDDS take off point fidds_go: mov ax,num_flop add ax,num_hard ; calc fidds offset sub aux_drive,al ; zero base the drive code mov dx,ds ; dx:bx -> param block mov bx,offset aux_drive int fidds_interrupt ; see you later... ret ; Dummy FIDDS interrupt routine for non-disks i_dummy_fidds: sub ax,ax ; zero for no select iret ; Interrupt to return the lowest numbered unused system ; flag to FIDDS, to be used for a flagwait to eternity. i_fidds_flag: ; mov al,0 ;; FORCE THE ZERO FLAG, FIDDS NOT SUPPORTED mov cs:top_flag,al ;; AND MAKE SURE IT STAYS THAT WAY ; ; mov al,cs:top_flag ; get the next available ; test al,al ; if it's zero, jz i_f_flag_done ; then forget it inc al ; increment to the next cmp al,cs:n_flags ; if we've gone too far jb i_f_flag_ok ; then reset to zero mov al,0 i_f_flag_ok: mov cs:top_flag,al ; for next time i_f_flag_done: iret top_flag db last_flag ; used by i_fidds_flag eject reorg_hard_data equ offset $ dseg org reorg_hard_data ; *** XT hard disk driver data segment *** ; this block of data is shared by the ; XT hard disk driver and the FIDDS hooks aux_drive rb 1 ; corrected drive code aux_code rb 1 ; select / rw multi-count aux_track rw 1 aux_sector rw 1 aux_dma_o rw 1 aux_dma_s rw 1 aux_longword equ dword ptr aux_dma_o aux_func rw 1 ; hd function code max_sector rw 1 ; for mcnt loops ; general information variables hd_ndisks db 0 ;amount of IRON found only! hd_uda dw 0 ;stores UDA at entry to hd routines hd_init_flag db 0 ;set at end of initialization hd_pstart_cyl dw 0 ;used to cross-check labels hd_pend_cyl dw 0 ; for consistency with each other hd_function dw 0 ;used fo debug trace info only ; desired block buffer contents ; hd_req_vol is global AUX_DRIVE hd_req_block dw 0 ;requested BLOCK / physical sector ; tables of pertinent information about each possible disk ; each contains an entry defined by data structure HDINF_vector hd_disk_info: hd_info0 db 0,0,0,0,0 dw 0,0,offset hd_label0 hd_info1 db 0,0,0,0,0 dw 0,0,offset hd_label1 ; iopbs used to do ROM BIOS IO ; CAUTION: these are only templates, it is the user's responsibility ; to make sure they are FULLY filled in with meaningful information hd_wr_iopb db 3,0,0,0 ;fn,err,lun,head dw 0 ;cylinder db 0,4 ;sector,count dw 0,0 ;xfer offset,seg hd_rd_iopb db 2,0,0,0 ;fn,err,lun,head dw 0 ;cylinder db 0,4 ;sector,count dw 0,0 ;xfer offset,seg hd_vfy_iopb db 2,0,0,0 ;fn,err,lun,head dw 0 ;cylinder db 0,4 ;sector,count dw 0,0 ;xfer offset,seg hd_rd_partition_iopb db 2,0,0,0 ;fn,err,lun,head dw 0 ;cylinder db 0,1 ;sector,count dw 0,0 ;xfer offset,seg ; string used to verify label authenticity hd_idstring db '(C) 1983 DIGITAL RESEARCH, INC.' ; pointer to ROS interrupt entry for xt hard disk hd_rom_ofs rw 1 hd_rom_seg rw 1 HD_ROM_ENTRY equ dword ptr hd_rom_ofs org offset $+1 and 0fffeh ;word align it ; allocation vectors, etc. for XT hard disks hd_dph0 dw 0,0,0,0,HD_DPB_INIT dw 0,0ffffh,0ffffh,0ffffh,0ffffh hd_dph1 dw 0,0,0,0,HD_DPB_INIT dw 0,0ffffh,0ffffh,0ffffh,0ffffh dph_size equ 20 ; this is a dummy dpb which is used by genccpm for ; dph allocation, check vector, and hash table calculations HD_DPB_INIT dw 11h ; spt db 05h ; bsh 4k blocks db 1Fh ; blm " db 01h ; exm dw 0A20h ; dsm 10 meg maximum dw 03FFh ; drm dw 0FFFFh ; al0 and al1 dw 8000h ; cks fixed disk dw 01h ; off db 04h ; psh db 0Fh ; phm org offset $+15 and 0fff0h ;align them ; leave space for both label structures hd_label0 rb 512 hd_label1 rb 512 HD_DPB0 equ byte ptr hd_label0 + offset HDLB_cpm_dpb HD_DPB1 equ byte ptr hd_label1 + offset HDLB_cpm_dpb org offset $+1 and 0fffeh ;word align them ; The XT hard disk now shares its buffer with the floppies ; Sector buffer used by read/write routines when requested ; multi sector I/O operation crosses a 64K page boundary. ; Also used to read floppy size code from track 0 sector 0. hd_local_buf rb 0 local_buffer rb bytes_per_sector - 1 floppy_type rb 1 rest_of_buf rb block_size - bytes_per_sector