title CP/M Ver 2.2 BIOS for SCSI Host Adaptor name ('bios22') ; date 20-Jun-83 ; by David Wagstaff ; copyright 1983 by Griffin Tech. All rights reserved ; ; .z80 ; z-80 coding is used aseg ; Absolute addressing is needed ; subttl Introduction, Externals, Internals and Macros ; ; ; This module contains the Basic Input/Output System for ; version 2.2 of the CP/M operating system. ; Portions of the Serial port I/O have not beened coded for ovious reasons ; therefore, this task is left to the customer of this product. ; The equate 'SCSI$BASE' has be equated to the base address for the SCSI ; interface board, the current value is 050h. ; The equate 'MSIZE' should be set to the size of the operating system ; to be gen'ed, typicaly this should be about 60k. ; ; ; ; ** >> Editing History << ** ; ; Ver. Date Modification ; ---- -------- ---------------------------------------- ; 00 06/20/83 1) Created. ; ; ; .xlist mdbe macro value,sp ; macro to print version or date defb (value shr 12)+'0' defb ((value shr 8) and 0fh)+'0' defb sp defb ((value shr 4) and 0fh)+'0' defb (value and 0fh) +'0' endm ;*** debug macro mesg,values ; macro to debugging bios local dm,dr,space,skip ; 'mesg' is a ASCII string local hlx,dex,bcx,afx,ard ; to be printd, 'values' is local crlf ; a list of memory location jp ard ; to dump to the terminal. hlx: defw 00 ; A register dump will also bcx: defw 00 ; be printed on the console. dex: defw 00 afx: defw 00 ard: ld (afx),a ld (hlx),hl ld (dex),de ld (bcx),bc push af push hl push bc push de ifnb irp val, ld hl,(val) call ?pdec ld hl,space call ?prtmsg endm endif ld hl,dm call ?prtmsg ld hl,skip call ?prtmsg irp val, ld hl,(val) call ?pdec ld hl,space call ?prtmsg endm ld hl,crlf call ?prtmsg pop de pop bc pop hl pop af jp dr dm: defb mesg defb cr,lf,eom space: defb " ",eom skip: defb "Register Dump af, hl, de, bc" crlf: defb cr,lf,eom dr: endm ; .list ; ; ; subttl Equates and Constants page ; ; *** ASCII constants and User Options *** ; aseg bell equ 0007h ; sound console bell cr equ 000dh ; cariage return lf equ 000ah ; linefeed ffd equ 000ch ; formfeed xon equ 0011h ; ^q xoff equ 0013h ; ^s eom equ 0000h ; end of message marker false equ 0000h ; true equ not false ; retry equ 0010 ; Retrys before Hard-Error msize equ 0060 ; 60k system. ; ; ; *** Port Assignments *** ; SCSI$base equ 0050h ; SCSI Interface board base QUAD$eia equ 0010h ; Base port for QUAD. eia board crtstatus equ QUAD$eia+4 ; Status port for console crtdata equ QUAD$eia+5 ; Data port for console ; txrdy equ 0001h ; Tx. Ready bit in 8251 usart rxrdy equ 0002h ; Rx. Ready bit in 8251 usart ; ; *** SCSI Port assignments *** ; ; * bit,byte and port assigments for * ; * SCSI host interface adaptor * ; datai equ SCSI$base ; data in register datao equ SCSI$base+2 ; data out register bstat equ SCSI$base+1 ; bus status selport equ SCSI$base ; select port adr. clrint equ SCSI$base+1 ; clr. intrrupt port dmaport equ SCSI$base+3 ; dma address port cparity equ SCSI$base+4 ; clear parity port busy equ 80h ; controler busy bit cd equ 40h ; command/data bit direc equ 20h ; directon bit req equ 10h ; request bit msg equ 08h ; end message bit perr equ 04h ; perr error bit bdack equ 02h ; board ack. signal lint equ 01h ; interupte bit ; ; *** Cartriage storage information for IOMEGA system *** ; ncyn equ 306 ; # track/drive nscyn equ 64 ; # sectors/track ?nbsct equ 2 ; # blocks/sector nbblk equ 256 ; # bytes/block nbrec equ 128 ; cp/m record size bls equ 2048 ; cp/m block size drm equ 512-1 ; # dir. entrys -1 bysct equ nbblk*?nbsct ; # bytes/sector nbcyn equ nscyn*bysct ; # bytes/track nrsct equ bysct/nbrec ; # recs/sector nrcyn equ nscyn*nrsct ; # recs/track nrecbls equ bls/nbrec ; # recs/bls nblscyn equ nrcyn/nrecbls ; # bls/track dsma equ nblscyn*(ncyn/2); size of an logcal drive A: dsmb equ nblscyn*((ncyn/2)-offset) ; size of B: offset equ 0001 ; track offset for System Track ; ; * IOMEGA command set * ; fmtztrk equ 10000b ; format z-track flgsct equ 10010b ; flag sector flgtrk equ 10100b ; flag track c?seek equ 00110b ; seek track c?home equ 01000b ; ?home drive reqst equ 01010b ; reqest status reqes equ 01100b ; reqest extended status ctest equ 01110b ; test contrl. status rddata equ 00001b ; read data rdid equ 10101b ; read id rddtof equ 11001b ; read data with offset rddiag equ 10001b ; read diagnostic wrtdata equ 00011b ; write data wrtid equ 00111b ; write id wrtdiag equ 10011b ; write diagnositc ; ; ; ; *** CP/M Enviroment Constants *** ; tpa equ 0100h ; Address of start of tpa bias equ (msize-20)*1024 ; ccp equ 3400h+bias ; Base of CCP bdos equ ccp+0806h ; Base of BDOS bios equ ccp+1600h ; Base of this bios iobyte equ 0003h ; Address of IOBYTE cdrive equ 0004h ; Current disk indicator nsects equ (bios-ccp)/128 ; # of sectors/ ccp ; ; ; *** IOmega blocking size equates *** ; bufsz equ 2048 ; Data blocking size mgablks equ bufsz/256 ; # of iomega blocks cpmblks equ bufsz/nbrec ; # of cp/m records mask equ 07h ; see following table ; ; ******************************************** ; * the value of "mask" determines the block * ; * buffer size of the deblocking routines. * ; * the value of "mask" are: * ; * bufsz mask * ; * ----- ---- * ; * 2048 07h * ; * 4096 0fh * ; * 8192 1fh * ; * 16384 3fh * ; ******************************************** ; ; ; ; org bios ; start at bios cseg ; ; subttl Jump Vector Table for BIOS Functions page ; jp ?boot ; Cold Start jp ?wboot ; Warm boot jp ?const ; Console Status jp ?conin ; Console Input jp ?conout ; Console Output jp ?list ; Printer Output jp ?punch ; AUX: output routine jp ?reader ; AUX: input routine jp ?home ; Recalibrate Drive jp ?seldsk ; Select Drive jp ?settrk ; Set Track Number jp ?setsec ; Set Sector Number jp ?setdma ; Set DMA address jp ?read ; Read a Sector jp ?write ; Write a Sector jp ?listst ; Return Printer Status jp ?sectran ; Sector Translator routine ; subttl Comman Data Storage Definations page ; ; *** >>> Comman Data Storage Defination Area <<< *** ; ; *** Disk parameter block definations *** ; dpAblk: defw nrcyn ; DRIVE A: Type defb 4,15 defb 0 defw dsma defw drm defw 0ff00h defw (drm/4)+1 defw 1 ;**** dpBblk: defw nrcyn ; DRIVE B: Type defb 4,15 defb 0 defw dsmb defw drm defw 0ff00h ; debug = 0ffffh defw (drm/4)+1 defw 9ah ;**** ; ; ; *** >>> Disk Parameter header tables <<< *** ; dpbase: ; defw 0000,0000 ; Drive A: defw 0000,0000 ; defw dirbf,dpAblk ; defw chkA,allA ; ; defw 0000,0000 ; Drive B: defw 0000,0000 ; defw dirbf,dpBblk ; defw chkB,allB ; ; subttl Boot and Warm Boot Routines page ; ; ; *** >>> Start of BOOT and WARM BOOT Routines <<< *** ; ?boot: ;-op: Handle misc. initilization and signon message printing ;-pp: none ;-rc: none ;- xor a ; clear IOBYTE ld (iobyte),a ; ld (cdrive),a ; and current disk ld hl,signon ; go print sign-on message call ?prtmsg ; ?gocpm: ld a,0c3h ; a = op. code for 'jp' ld (0000h),a ; vector @ 0000h ld (0005h),a ;& vector @ 0005h ld hl,bios+3 ; location of wboot routine ld (00001h),hl ; save it ld hl,bdos ; location of BDOS ld (0006h),hl ; save to system vector ld a,(cdrive) ; get the current disk ld c,a ; to register c jp ccp ; and pass control to the CCP ;* ;** ;* .xlist signon: defb cr,lf,lf,lf defb "BIOS220 --- CP/M Ver. 2.2 BIOS 20-Jun-83",cr,lf crlf: defb cr,lf,eom .list ;* ;** ;* page ;+ ?wboot: ;-op: Warm Boot CP/M system. ;-pp: System Tracks of Drive A: has a valid system on it. ;-rc: CCP is reloaded into core from system tracks ;- ld sp,0080h ; set-up the stack to free area call ?flush ; flush disk cache ld hl,-1 ; force new reads ld (@rblk),hl ; ld a,'W' ; mark as warm boot ld (@wrtact),a ; ld c,0 ; select drive A: call ?seldsk ; call ?home ; recalibrate drive ; ;* At this point we must reload in everything but the BIOS * ; ld a,(cdrive) ; a= current disk number wbt1: push af ; save current disk ld hl,0001 ; set to ready block 1 ld (@actsct),hl ; ld hl,ccp ; hl @ base of CCP wbt2: ld (@rpntr),hl ; save load adr. to dma pointer ld a,8 ; go read in 8 blocks (8*256) bytes call ?rdblk ; go do it jr nz,wbterr ; brif error ld hl,(@rpntr) ; up-date dma pointer ld de,nbblk*8 ; de = transfer size add hl,de ; ld a,(@actsct) ; point next data block add a,08 ; ld (@actsct),a ; cp 11h ; see if the end has been reached jr nz,wbt2 ; brif not done ld a,false ; mark as not write active ld (@wrtact),a ; pop af ; recover current disk number ld (cdrive),a ; jp ?gocpm ; an pass control to CCP ;* wbterr: ld a,'W' ; a = code for warm boot error call ?dskerr ; go print the message pop af ; recover all old number jp wbt1 ; and try again ;* ;** ;* subttl Character I/O routines page ; ; *** >>> Start of Character I/O routines *** ; ?const: ;-op: See if console has character ready ;-pp: none ;-rc: a = 00 : no character ready ;- ff : character ready ;- ; >>> supply code here for your hardware configuration <<< ; Sample code is provided for a 8251 type usart ; in a,(crtstatus) ; get status cpl ; our hardware complements status register and rxrdy ; ret z ; exit if not ready or 0ffh ; else with with true ret ;* ;** ;* ;+ ?conin: ;-op: get character from the console ;-pp: none ;-rc: a = character (parity bit striped, i.e. only 7-bits present) ;- call ?const ; Wait for character ready or a ; jr z,?conin ; ; ; >>> Supply Code here for your hardware configuration <<< ; >>> register a will receive character, port has character ready <<< ; Sample code is provided for a 8251 type usart. ; in a,(crtdata) ; grab the data byte cpl ; our hardware complements the data register ret ; and then exit ;* ;** ;* ;+ ?conout: ;-op: send character to console ;-pp: c = character ;-rc: none ;- ; >>> Supply code here for your hardware configuration <<< ; Sample code is provided for a 8251 type usart in a,(crtstatus) ; wait for tx. ready and txrdy ; jr nz,?conout ; remember our hardware ld a,c ; a = character to send out (crtdata),a ; eject the character ret ; and then exit ;* ;** ;* ;+ ?list: ?punch: ;-op: handle output to list and punch devices ;-pp: c = character to send ;-rc: none ;- ; >>> Supply code here for your hardware configuration <<< ret ; This just acts as a bit-bucket ;* ;** ;* ;+ ?listst: ;-op: Return Status of Printer Ready ;-pp: none ;-rc: a = 00 : printer not ready ;- ff : printer is ready ;- ; >>> Supply Code Here for your hardware configuration <<< ; ld a,true ; this is just a default ret ; and then exit ;* ;** ;* ;+ ?reader: ;-op: handle input from a secondary input device ;-pp: none ;-rc: a = inputed character. ;- ; >>> Supply code here for your hardware configuration <<< ld a,'Z' and 3fh ; this just returns EOF ret ; ;* ;** ;* ; ; subttl Disk Support Routines page ; *** >>> Disk Support Routines <<< *** ; ;+ ?home: ;-op: This function performs no-operation in ;- this system. ;- ret ; just exit ;* ;** ;* ;+ ?seldsk: ;-op: Select a drive for further operations ;-pp: c = drive to select ;-rc: hl @ dph for drive else 0000 if bad drive ;- ld hl,0000 ; ready for error exit ld a,c ; a = drive code cp 2 ; ret nc ; exit if bad select code ld (cdrive),a ; save new current disk ld l,a ; hl = drive code rept 4 add hl,hl ; hl = hl * 16 endm ld de,dpbase ; de = base of table add hl,de ; perform the index operation ret ; and then exit ;* ;** ;* ;+ ?settrk: ;-op: Set-up Track pointer ;-pp: bc = track for next operation ;-rc: none ;- ld (@trk),bc ; save current track ret ; and exit ;* ;** ;* ;+ ?setsec: ;-op: Set-up Sector pointer ;-pp: bc = Sector for next operation ;-rc: none ;- ld (@sect),bc ; save current sector ret ; and then exit ;* ;** ;* ;+ ?setdma: ;-op: Set-UP DMA address pointer ;-pp: bc = address of dma area ;-rc: none ;- ld (@dma),bc ; save current dma address ret ; and then exit ;* ;** ;* ;+ ?read: ;-op: Read a sector ;-pp: Disk read parmaters set (i.e. track, sector and drive) ;-rc: a = 0 : no errors occured ;- = 0ffh : errors detected ;- ld hl,rdbuf ; point to read buffer ld (@rpntr),hl call compute ; get log. block # (hl =) ex de,hl ; is block loaded?? ld hl,(@wblk) ; is sector wrt. active?? or a ; sbc hl,de ; jr z,rd4 ; brif so ld hl,(@rblk) ; is block already loaded?? or a ; (in read buffer that is) sbc hl,de ; jr z,rd1 ; brif if loaded jr rd2 ; brif not ;* rd4: ld hl,wrtbuf ; index into wrt. buff. jp rd3 ; go do it rd1: ld hl,rdbuf ; index into rd. buff. rd3: add hl,bc ; bc = index, hl @ sector dat ld de,(@dma) ; de = address dma ld bc,nbrec ; bc = size of CP/M record ldir ; perform the transfer xor a ; exit with no errors ret ; and exit ;* rd2: ld (@actsct),de ; set-up for read ld (@rblk),de ; set pointer ld a,(@wrtact) ; see if warm boot active cp 'W' ; jr z,rd2.0 ; brif so res 0,l ; clear unit flag rd2.0: ld a,mgablks ; xxx blocks only call ?rdblk ; go do it ret nz ; return on error jp rd1 ; go index into table ;* ;** ;* page ;+ ?write: ;-op: write a sector ;-pp: disk perameters are set (i.e. track, sector and drive) ;- reg c has write type 0,1,2 ;-rc: a = 0 : no errors detected ;- = 0ffh : errors detected ;- ld a,c ; a= write type ld (@wrtype),a ; save for later call compute ; go compute mga block wt03: ex de,hl ; de = block ld hl,(@wblk) ; see if the same as loaded or a ; clear carry sbc hl,de ; test jr z,wt02 ; brif so push de ; save goal blk# call ?flush ; flush out old block number pop hl ; hl= new block # ld (@actsct),hl ; up-date pointers ld (@wblk),hl ; ld hl,wrtbuf ; dma to write buffer ld (@rpntr),hl ; ; if bufsz-2048 ld a,mgablk ; read in a block call ?rdblk ; go read it in else ; block size = 2048 ld a,(@wrtype) ; see if write type is type 2 cp 2 ; ld a,mgablk ; ready for pre-read if necessary call nz,?rdblk ; brif so endif ; ret nz ; return on error wt02: ld hl,wrtbuf ; hl @ sector buffer add hl,bc ; add in the offset ex de,hl ; de @ sector ld hl,(@dma) ; hl @ data ld bc,nbrec ; bc = # bytes/CP/M record ldir ; do the trnsfr ; ld a,true ; set write active to true ld (@wrtact),a ; ld a,(@wrtype) ; get back write type dec a ; check for directory ld a,0 ; for safty call z,?flush ; go flush data if so or a ; set flags ret ; and exit ;* ;** ;* page ;+ compute: ;-op: compute phys. block number ;-pp: track and sector are set ;-rc: hl = phys. block number ;- bc = index into block (0..bufsz) ;- ; ld hl,@trk ; hl @ track # ld e,0 ; clear low de ld d,m ; load low track inc hl ; point hi track ld a,(hl) ; a= hi track rra ; divide by two rr d ; rr e ; ex de,hl ; hl= track*128 ld a,(@sect) ; a = sector number srl a ; divide by 2 ld c,0 ; c= 0 or 80h rr c ; add a,l ; ld b,a ; and not mask ; ld l,a ; ld a,b ; and mask ; ld b,a ; ld (@ofs),bc ; save offset ld a,(cdrive) ; for selection or a ; check for unit 0 ret z ; return if so set 0,l ; else set unit 1 flag ret ; and exit ;* ;** ;* ;+ ?flush: ;-op: flush write buffer if needed ;-pp: @wblk is set and valid ;- if @wrtact flag is set to true ;- ; ld hl,wrtbuf ; set dma to write buffer ld (@rpntr),hl ; ld a,(@wrtact) ; cp false ; buffer write active?? ret z ; return if not ld hl,(@wblk) ; ld (@actsct),hl ; actsec = wblkn ld a,mgablks ; write only xx block call wrtblk ; go write it ld a,false ; buffer not write active ld (@wrtact),a ; ld hl,(@rblk) ; is read/write to same lä de,(@wblk© » or a ; sbc hl,de ; jr nz,flsh1 ; brif not ld hl,-1 ; force read ld (@rblk),hl ; flsh1: xor a ; record no error ret ; and exit ;* ;** ;* ; ; subttl SCSI Host Interface Adaptor Support Routines page ; ; *** >>> SACI Host Interface Adaptor Support Routines <<< *** ; ;+ ?rdblk: ;-op: read in x sectors ;-pp: a = number of blocks to read ;- @actsct is valid ;- ld e,rddata ; e = read data command jr precmd ; go prepare for it ;* ;** ;* ;+ wrtblk: ;-op: write out x blocks ;-pp: a = number of blocks to write ;- @actsct is valid ;- ld e,wrtdata ; e = write data cmd. ;+ precmd: ;-op: create command block ;-pp: a = number of block involved ;- e = first command byte ;- push de ; save command ld hl,cmdtbl ; hl @ command block ld (hl),e ; store command byte inc hl ; point next ld de,(@actsct) ; de = log. block number push af ; save block count ld a,(@wrtact) ; see if in warm boot cp 'W' ; jr z,pc10 ; brif so ld a,e ; mask out garbage and not mask ; ld e,a ; pc10: pop af ; recover block count ld (hl),d ; save it inc hl ; ld (hl),e ; inc hl ; ld (hl),0 ; always < 256 log. blocks inc hl ld (hl),a ; save # blocks to trnsfr inc hl ld (hl),0 ; clear extra byte ld hl,cmdtbl ; hl @ cmd. block call ?docmd ; go do it pop de ; recover command ret z ; return if ok call SCSI$error ;go print disk error ld a,0ffh ;mark the error or a ; ret ;and exit ;* ;** ;* ;+ SCSI$error: ;-op: Handle SCSI Disk Errors ;- ld a,'D' ; code for data error call ?dskerr ; do the disk error ret ; and then exit ;* ;** ;* ; page ; ;* start of protocal handling routnes * ; ;+ ?docmd: ;-op: issue command to SCSI host adaptor ;-pp: hl @ command bytes to send ;- @actsec & @rpntr are valid ;-rc: no - zero : error in command (a = error bits) ;- zero : command was executed successfully ;- ld (lcmd@),hl ; save command @ ld a,retry ; get retry count ld (trycntr),a ; reset counter out (cparity),a ; reset parity error dcmd1: push bc ; save counter call ?putdma ; set dma address call ?select ; go select controler pop bc ; recover bc ; wait: ; ;* here we must wait for execution * ; in a,(bstat) ; a <--- buss status and cd+req ; check for data jr nz,wait ; brif still data in a,(datai) ; a <-- completion status push af ; save ending status wait1: in a,(bstat) ; wait for req. and msg. and req+msg ; jr nz,wait1 ; in a,(datai) ; get byte of zero pop af ; recover status and 00011111b ; mask out errors jr nz,wait4 ; brif not ok in a,(bstat) ; check for parity and perr ; out (clrint),a ; clear interrupt ld a,0ffh ; jr nz,wait4 ; brif error xor a ; exit with zero ret ; and exit ;* ;* wait7: pop af ; clear out stack wait4: bit 2,a ; hardware busy?? jr z,wait6 ; brif not ld a,'R' ; code for ready error call ?dskerr ; jr wait5 ; and continue ;* wait6: ld hl,trycntr ; see if retry up dec (hl) ; jr z,wait2 ; brif retry is up wait5: ld hl,(lcmd@) ; recover last command jp dcmd1 ; and try again ;* wait2: out (clrint),a ; clear interrupt or a ; exit with non-zero ret ; and exit ;* ;** ;* ;+ ?putdma: ;-op: send dma address to host adapter ;-pp: rpntr has dma address ;- ld a,(hidma) ; set hi-byte out (dmaport),a ; high byte always zero ld de,(@rpntr) ; de @ dma address ld a,d out (dmaport),a ; send byte 1 ld a,e out (dmaport),a ; send byte 2 ret ; and exit ;* ;** ;* ;+ ?select: ;-op: select controler ;- in a,(bstat) ; is controler busy?? and busy ; wait for not busy jr z,?select ; wait if so sel2: ld a,01h ; select controler #1 out (datao),a ; out (selport),a ; and select controler sel1: in a,(bstat) ; wait for req and req ; jr nz,sel1 ; ld d,a ; d=0, mark first command ; ;* now fall on thru to output command bytes * ; ;+ ?outcmd: ;-op: issue command bytes to host adaptor ;-pp: hl @ command bytes ;- in a,(bstat) ; grab buss status ld c,a ; save status and cd ; see if data ret nz ; exit if data ld a,c ; check for direc and direc ; ret z ; exit if input ld a,req+bdack ; bit 0,d ; see if first cmd. jr nz,?oc5 ; brif not ld a,req ; else just check for req. ?oc5: and c ; check for ready jr nz,?outcmd ; brif not (1.75/1.17) ?oc1: ld a,(hl) ; get command byte (1.75/1.17) out (datao),a ; send to controler (2.75/1.83) inc hl ; point next (1.5/1.0) ld d,1 ; mark not first command jr ?outcmd ; and do it again! ;* ;** ;* ; subttl MISC. Routines and Functions page ; ; *** Misc. Routines and Functions *** ; ; ;+ ?sectran: ;-op: perform sector translation ;-pp: de @ tran. table ;- bc = sector number ;- hl = tran. sector number ;- ld h,b ; simple 1 to 1 translation ld l,c ; ret ; add exit ;* ;** ;* ; ;+ ?prtmsg: ;-op: Print message string at hl ;-pp: hl @ message string terminated with a zero byte. ;-rc: none ;- ld a,(hl) ; check for EOS or a ; ret z ; exit if so ld c,a ; c = character inc hl ; point next character push hl ; and save call ?conout ; and issue to terminal handler pop hl ; recover pointer jr ?prtmsg ; and continue ;* ;** ;* ;+ ?dskerr: ;-op: Disk Error Handler ;-pp: A = error code letter ;-rc: none ;- push af ; save error letter on stack ld hl,dem ; hl @ disk error message call ?prtmsg ; go print message header pop af ; c = error code lettre ld c,a ; call ?conout ; and print it ret ; and exit ;* dem: defb cr,lf,lf defb "Disk I/O Error :",0 ;* ;** ;* ; subttl BIOS Data Storage Area page ; ; *** >>> BIOS Data Storage Area <<< *** ; ; @rpntr: defw 00 ; Address of Internal Deblocking buffer @wblk: defw 00 ; Current Write block number @rblk: defw 00 ; Current Read block number @actsct: defw 00 ; Block number to Read/Write @wrtact: defb false ; True if block is write active lcmd@: defw 00 ; Address of last IOMEGA command trycntr: defb 00 ; Retry counter for IOMEGA i/o op.s hidma: defb 00h ; Page address of IOMEGA buffer area @dma: defw 00 ; Current DMA addess @trk: defw 00 ; Current Track Number @sect: defw 00 ; Current Sector Number cmdtbl: defs 11 ; Iomega Command Table Storage @wrtype: defb 00h ; current write type @ofs: defw 00 ; Current disk cache index dirbf: defs 128 ; directory buffer chkA: defs (drm/4)+1 ; directory checksum for drive A: chkB: defs (drm/4)+1 ; directory checksum for drive B: allA: defw (dsma/8)+1 ; Allocation map for drive A: allB: defw (dsmb/8)+1 ; Allocation map for Drive B: rdbuf: defw bufsz ; address of read data buffer wrtbuf: defs bufsz ; address of write data buffer @extra: defb 00 ; extra byte ; end end