; mp/m basic input/output operating system (bios) ; ; ; FFFF = true equ 0ffffh ;define value of true. 0000 = false equ not true ;define value of false. ; 0030 = msize equ 48 ;memory size in kbytes. 0001 = ndisks equ 1 ;number of disk drives 0016 = vers equ 22 ;cp/m version number 0012 = bvers equ 18 ;bios version number FFFF = onedsk equ not((((ndisks-1)+3)and 4)shr 2) if onedsk 0000 = disk4 equ false 0000 = disk3 equ false endif if not onedsk disk4 equ (ndisks and 0000$0100b) shr 2 disk3 equ ndisks and 0000$0001b endif 0000 = dubsid equ false ;true for double sided drives. 0000 = intrp equ false ;set true for intrrupts allowed. FFFF = COLCNT EQU TRUE ;SET TRUE FOR NETRONICS TERMINAL 0020 = cpl equ 32 ;characters/line 0020 = llimit equ cpl ;characters/line ; 00E1 = cstat equ 0E1H ;console status port 00E1 = ccom equ 0E1H ;console command port 00E0 = cdata equ 0E0H ;console data port 00E3 = lstat equ 0E3H ;list status port. 00E3 = lcom equ 0E3H ;list command port. 00E2 = ldata equ 0E2H ;list data port. ; 0003 = plci0 equ 3 0002 = plco0 equ 2 0001 = pldsk equ 1 0000 = pllpt equ 0 0083 = poll equ 131 ; 0002 = ckbr equ 0000$0010b ;status bit on port 0. 0004 = cptr equ 0000$0100b ;printer ready bit. 0004 = lrbit equ cptr ;lister ready bit. ; 0003 = iobyte equ 3 ;address of i/o byte. 0004 = cdisk equ 4 ;current selected disk 2F00 = cbase equ 12032 ;bias for larger than 20k. 6300 = cpmb equ cbase+3400h ;start of cp/m 2.2 6B06 = bdos equ cpmb+806h ;start of bdos 2.2 7900 = bios equ cpmb+1600h ;base of bios 2.2 0001 = nmbcns equ 1 0100 org 100h 00FD = pdisp equ $-3 00FA = xdos equ pdisp-3 013C = nsects equ ($-cpmb)/128 ;number of sectors in it. 004D = trks equ 77 ;# of tracks/disk 001A = spt equ 26 ;sectors/track 0002 = off equ 2 ;# of reserved system trks ; ; i/o jump vector ; this is where cp/m calls whenever it needs ; to do any input/output operation. ; user programs may use these entry points ; also, but note that the location of this ; vector changes with the memory size. ; 0100 C34C01 jmp coldstart ;from cold start loader. 0103 C33502 wboote: jmp wboot ;from warm boot. 0106 C38102 jmp constd ;check console kb status. 0109 C38602 jmp conind ;read console char. 010C C38B02 jmp conotd ;write console char. 010F C3D002 jmp list ;write listing char. 0112 C39702 jmp rtnempty ;write punch char. 0115 C39702 jmp rtnempty ;read reader char. 0118 C3B504 jmp home ;move disk to zero. 011B C33E04 jmp seldsk ;select disk drive. 011E C3B704 jmp settrk ;seek to track in reg a. 0121 C30D05 jmp setsec ;set sector number. 0124 C31205 jmp setdma ;set disk starting address. 0127 C31E05 jmp read ;read selected sector. 012A C37E05 jmp write ;write selected sector. 012D C3E402 jmp pollpt ;return list status. 0130 C31805 jmp sectran 0133 C3FC02 jmp selmemory 0136 C3E702 jmp polldevice 0139 C3FD02 jmp startclock 013C C30303 jmp stopclock 013F C30803 jmp exitregion 0142 C30F03 jmp maxconsole 0145 C31203 jmp systeminit 0148 00 db 0 0149 C32E03 jmp idle coldstart: warmstart: 014C 0E00 mvi c,0 014E C3FA00 jmp xdos ; ; data byte for number of disk drives ; 0151 01 nodsks: db ndisks ; ; ; fixed data tables for tw0-drive standard ; ibm-compatible 8" disks ; ; disk parameter header for disk 00 0152 72010000 dpbase: dw trans,0000h 0156 00000000 dw 0000h,0000h 015A 22068C01 dw dirbf,dpblk 015E C106A206 dw chk00,all00 ; disk parameter header for disk 01 0162 72010000 dw trans,0000h 0166 00000000 dw 0000h,0000h 016A 22068C01 dw dirbf,dpblk 016E F006D106 dw chk01,all01 if disk3 or disk4 ; disk parameter header for disk 02 dw trans,0000h dw 0000h,0000h dw dirbf,dpblk dw chk02,all02 endif if disk4 ; disk parameter header for disk 03 dw trans,0000h dw 0000h,0000h dw dirbf,dpblk dw chk03,all03 endif ; ; ; sector translate vector ; 0172 01070D13 trans: db 1,7,13,19 ;sectors 1,2,3,4 0176 19050B11 db 25,5,11,17 ;sectors 5,6,7,8 017A 1703090F db 23,3,9,15 ;sectors 9,10,11,12 017E 1502080E db 21,2,8,14 ;sectors 13,14,15,16 0182 141A060C db 20,26,6,12 ;sectors 17,18,19,20 0186 1218040A db 18,24,4,10 ;sectors 21,22,23,24 018A 1016 db 16,22 ;sectors 25,26 ; dpblk: ;disk parameter block, common to all disks 018C 1A00 dw spt ;sectors per track if not dubsid 018E 03 db 3 ;block shift factor 018F 07 db 7 ;block mask 0190 00 db 0 ;null mask 0191 F200 dw 242 ;disk size-1 0193 3F00 dw 63 ;directory max 0195 C0 db 192 ;alloc 0 0196 00 db 0 ;alloc 1 0197 1000 dw 16 ;check size endif if dubsid db 4 ;block shift factor db 15 ;block mask db 0 ;null mask dw 246 ;disk size-1 dw 127 ;directory max db 192 ;alloc 0 db 0 ;alloc 1 dw 32 ;check size endif 0199 0200 dw off ;track offset ; ; end of fixed tables ; ; ; signon message ; smsg: 019B 0C0A0D db 12,10,13 019E 4578706C6F db 'Explorer-85 ' 01AA 0A0D db 10,13 01AC 4D756C7469db'Multi processor' 01BB 0A0D db 10,13 01BD 54696D652Ddb'Time-Sharing' 01C9 0A0D db 10,13 01CB 436F6D7075db'Computer System' if dubsid endif 01DA 0A0D db 10,13 01DC 0A0D db 10,13 01DE 0A0D db 10,13 01E0 00 db 0 ; ; boot ; this section is executed whenever reset and run ; after the coldstart loader reads in ; the cp/m system. ; 00E1 = STAT51 EQU 0E1H 00E1 = cntl51 equ 0E1H 00E0 = rxd51 equ 0E0H 00CE = mode51 equ 0ceH 0027 = cmd51 equ 27H boot: 01E1 3ECE mvi a,mode51 01E3 D3E1 out cntl51 01E5 D3E3 OUT CNTL51+2 01E7 3E27 mvi a,cmd51 01E9 D3E1 out cntl51 01EB D3E3 OUT CNTL51+2 01ED DBE0 in rxd51 01EF DBE2 IN RXD51+2 boot1: if intrp ;if interrupts allowed, ei ;enable them here. endif 01F1 AF xra a ;clear scratch area. 01F2 320400 sta cdisk 01F5 0E04 mvi c,endz-startz ;get length of zero area. 01F7 211806 lxi h,startz ;get scratch address. 01FA 77 bootl: mov m,a ;put zero in memory. 01FB 23 inx h ;increment pointer. 01FC 0D dcr c ;decrement counter. 01FD C2FA01 jnz bootl ;loop till done. 0200 3620 mvi m,llimit ;set line limit 0202 23 inx h ;point to latch byte 0203 3600 mvi m,0 ;set latch code = 0. 0205 219B01 lxi h,smsg ;print signon message. 0208 CDDB05 call pmsg gocpm: ; ; set jumps into cp/m in lower memory. ; 020B 3EC3 mvi a,0c3h ;put jmp to wboot 020D 320000 sta 0 ;adr at zero. 0210 210301 lxi h,wboote 0213 220100 shld 1 0216 320500 sta 5 0219 21066B lxi h,bdos ;put jump to bdos 021C 220600 shld 6 ;at adr 5,6,7. 021F 218000 lxi h,80h ;set default dma adr. 0222 221606 shld dmaadd 0225 3A0400 lda cdisk ;get disk number to 0228 4F mov c,a ;pass to ccp in c. 0229 C31503 jmp bootr ;jump to ccp. ; 022C 21E605 rderr: lxi h,btmsg ;get address of "boot error". 022F CDDB05 call pmsg ;print it. 0232 CDD803 call conin ;read a char from console. ; ; warm-boot: read all of cp/m back in ; except bios, then jump to ccp. ; 0235 318000 wboot: lxi sp,80h ;set stack pointer. if intrp ;if interrupts allowed, ei ;allow them here. endif 0238 3A1806 lda diskno ;save disk no. 023B 322106 sta temp 023E 0E00 mvi c,0 ;select disk zero. 0240 CD3E04 call seldsk 0243 CDB504 call home ;move to track zero. 0246 C22C02 jnz rderr ;if error, print message. 0249 C37802 jmp aldon 024C 010200 lxi b,2 ;track (b) = 0, sector (c) = 2. 024F 210063 lxi h,cpmb ;get starting address. if intrp ;if intrrupts allowed, di ;disable them here. endif 0252 C5 rdblk: push b ;save b&c. 0253 48 mov c,b ;go to track in b. 0254 CDB704 call settrk 0257 C1 pop b ;restore b&c. 0258 C22C02 jnz rderr ;if error, print message. 025B 221606 rblk1: shld dmaadd ;set starting address. 025E CD0D05 call setsec ;read starting at sector in c. 0261 CD1E05 call read 0264 C22C02 jnz rderr ;if error, print message. 0267 15 dcr d ;decrement sector count. 0268 CA7802 jz aldon ;all done when d=0. 026B 0C inr c ;increment sector number. 026C 79 mov a,c ;if sector no. 026D FE1B cpi spt+1 ;if not sectors/track + 1 026F DA5B02 jc rblk1 ;keep reading on this track. 0272 0E01 mvi c,1 ;otherwise, reset sector = 1. 0274 04 inr b ;increment track no. 0275 C35202 jmp rdblk ;and read next track. 0278 3A2106 aldon: lda temp ;restore disk no. if intrp ;if interrupts allowed, ei ;allow them again here. endif 027B 321806 sta diskno 027E C3FA00 jmp xdos ;go back to cp/m. constd: 0281 CD9002 call ptbljmp 0284 A402 dw pt0st conind: 0286 CD9002 call ptbljmp 0289 A702 dw pt0in conotd: 028B CD9002 call ptbljmp 028E B102 dw pt0out ptbljmp: 0290 7A mov a,d 0291 FE01 cpi nmbcns 0293 DA9902 jc tbljmp 0296 F1 pop psw rtnempty: 0297 AF xra a 0298 C9 ret tbljmp: 0299 87 add a 029A E1 pop h 029B 5F mov e,a 029C 1600 mvi d,0 029E 19 dad d 029F 5E mov e,m 02A0 23 inx h 02A1 56 mov d,m 02A2 EB xchg 02A3 E9 pchl polci0: pt0st: 02A4 C3CF03 jmp const pt0in: 02A7 0E83 mvi c,poll 02A9 1E03 mvi e,plci0 02AB CDFA00 call xdos 02AE C3D803 jmp conin pt0out: 02B1 DBE1 in cstat 02B3 E604 ani cptr 02B5 C2BD02 jnz co0rdy 02B8 C5 push b 02B9 CDC002 call pt0wait 02BC C1 pop b co0rdy: 02BD C3E403 jmp conot pt0wait: 02C0 0E83 mvi c,poll 02C2 1E02 mvi e,plco0 02C4 C3FA00 jmp xdos 02C7 C9 ret polco0: 02C8 DBE1 in cstat 02CA E604 ani cptr 02CC C8 rz 02CD 3EFF mvi a,0ffh 02CF C9 ret list: 02D0 CD3404 call ltbsy 02D3 B7 ora a 02D4 C2E002 jnz lptrdy 02D7 C5 push b 02D8 0E83 mvi c,poll 02DA 1E00 mvi e,pllpt 02DC CDFA00 call xdos 02DF C1 pop b lptrdy: 02E0 79 mov a,c 02E1 D3E2 out ldata 02E3 C9 ret pollpt: 02E4 C33404 jmp ltbsy 0004 = nmbdev equ 4 polldevice: 02E7 79 mov a,c 02E8 FE04 cpi nmbdev 02EA DAEF02 jc devok 02ED 3E04 mvi a,nmbdev devok: 02EF CD9902 call tbljmp 02F2 E402 dw pollpt 02F4 9404 dw poldsk 02F6 C802 dw polco0 02F8 A402 dw polci0 02FA 9702 dw rtnempty selmemory: 02FC C9 ret startclock: 02FD 3EFF mvi a,0ffh 02FF 32CD03 sta tickn 0302 C9 ret stopclock: 0303 AF xra a 0304 32CD03 sta tickn 0307 C9 ret exitregion: 0308 3ACE03 lda preemp 030B B7 ora a 030C C0 rnz 030D FB ei 030E C9 ret maxconsole: 030F 3E01 mvi a,nmbcns 0311 C9 ret systeminit: 0312 CDF101 call boot1 bootr: 0315 FB ei 0316 F5 push psw 0317 C5 push b 0318 D5 push d 0319 E5 push h 031A 3EC3 mvi a,0c3h 031C 322000 sta 0020h 031F 213103 lxi h,intlhnd 0322 222100 shld 0021h 0325 3E9F mvi a,9fh 0327 D3EF out 0efh 0329 F1 pop psw 032A C1 pop b 032B D1 pop d 032C E1 pop h 032D C9 ret idle: 032E FB ei 032F 76 hlt 0330 C9 ret 0085 = flagset equ 133 008E = dsptch equ 142 intlhnd: 0331 F5 push psw 0332 3E9F mvi a,9fh 0334 D3EF out 0efh 0336 3A9503 lda slice 0339 3D dcr a 033A 329503 sta slice 033D CA4303 jz t16ms 0340 F1 pop psw 0341 FB ei 0342 C9 ret t16ms: 0343 3E10 mvi a,16 0345 329503 sta slice 0348 F1 pop psw 0349 22C703 shld svdhl 034C E1 pop h 034D 22CB03 shld svdret 0350 F5 push psw 0351 210000 lxi h,0 0354 39 dad sp 0355 22C903 shld svdsp 0358 31C703 lxi sp,intstk+48 035B D5 push d 035C C5 push b 035D 3EFF mvi a,0ffh 035F 32CE03 sta preemp 0362 3ACD03 lda tickn 0365 B7 ora a 0366 CA7003 jz notickn 0369 0E85 mvi c,flagset 036B 1E01 mvi e,1 036D CDFA00 call xdos notickn: 0370 219603 lxi h,cnt64 0373 35 dcr m 0374 C28003 jnz notlsec 0377 3657 mvi m,57h 0379 0E85 mvi c,flagset 037B 1E02 mvi e,2 037D CDFA00 call xdos notlsec: 0380 AF xra a 0381 32CE03 sta preemp 0384 C1 pop b 0385 D1 pop d 0386 2AC903 lhld svdsp 0389 F9 sphl 038A F1 pop psw 038B 2ACB03 lhld svdret 038E E5 push h 038F 2AC703 lhld svdhl 0392 C3FD00 jmp pdisp ; ; 0395 10 slice: db 16 0396 40 cnt64: db 64 0397 intstk: ds 48 03C7 0000 svdhl: dw 0 03C9 0000 svdsp: dw 0 03CB 0000 svdret: dw 0 03CD 00 tickn: db 0 03CE 00 preemp: db 0 ; check console input status. ; const: 03CF DBE1 in cstat ;get status 03D1 E602 ani ckbr ;look at flag bit stat$ret: 03D3 3E00 mvi a,0 ;set a=0, for return 03D5 C8 rz 03D6 2F cma ;if ready (pressed) a=ff 03D7 C9 ret ; ; read a character from console. ; conin: 03D8 CDCF03 call const ;get console status 03DB B7 ora a 03DC CAD803 jz conin ;not ready yet 03DF DBE0 in cdata ;get data byte mask: 03E1 E67F ani 7fh ;make most sig. bit = 0. 03E3 C9 ret ; ; write a character to the console device. ; conot: IF COLCNT 03E4 E5 push h 03E5 CD2904 call conota ;output the char 03E8 211C06 lxi h,lcount ;get char. counter 03EB 79 mov a,c ;get char. 03EC FE0C CPI 12 ;IS IT FORM FEED 03EE C20604 JNZ ISITCR ;JP TO ISITCR 03F1 C5 PUSH B 03F2 E5 PUSH H 03F3 0602 MVI B,2 03F5 210000 LXI H,0 WAIT1: 03F8 2D DCR L 03F9 C2F803 JNZ WAIT1 03FC 25 DCR H 03FD C2F803 JNZ WAIT1 0400 05 DCR B 0401 C2F803 JNZ WAIT1 0404 E1 POP H 0405 C1 POP B ISITCR: 0406 FE0D cpi 13 ;is it 'cr' 0408 CA2504 jz slimit 040B FE0A cpi 10 ;is it 'lf' 040D CA1604 jz lfeed 0410 FE08 cpi 8 ;is it 'bs' 0412 C21704 jnz getcnt 0415 34 inr m lfeed: 0416 34 inr m getcnt: 0417 35 dcr m 0418 C22704 jnz conxit 041B 0E0D mvi c,13 ;echo a 'cr' 041D CD2904 call conota 0420 0E0A mvi c,10 ;and a 'lf' 0422 CD2904 call conota slimit: 0425 3620 mvi m,llimit ;reset counter conxit: 0427 E1 pop h 0428 C9 ret ENDIF conota: 0429 DBE1 in cstat ;read console status 042B E604 ani cptr 042D CA2904 jz conota ;loop until ready 0430 79 mov a,c ;get character 0431 D3E0 out cdata ;print it 0433 C9 ret ; ; write a character on listing device ; ltbsy: 0434 DBE3 in lstat ;read lister status 0436 E604 ani lrbit ;look at ready bit 0438 C3D303 jmp stat$ret ; ; read paper tape ; reader: 043B 3E1A mvi a,1ah ;cp/m eof returned for them. ; ; punch paper tape. ; punch: 043D C9 ret ;don't service them, just return. ; ; ; ; lisk i/o for the western digital 1771 ; controller chip ; ; version of 3-29-80 ; ; ; ; ; hlab set 8 ;8 for hd ld at beg of seek. stprat set 2 ;rate 1=6ms, 2=10ms, 3=20ms. ; 00E8 = disk equ 0e8h ;disk base address. 00E8 = dcom equ disk ;disk command port. 00E8 = dstat equ disk ;disk status port. 00E9 = track equ disk+1 ;disk track port. 00EA = sectp equ disk+2 ;disk sector port. 00EB = ddata equ disk+3 ;disk data port. 00EC = wait equ disk+4 ;disk wait port. 00EC = dcont equ disk+4 ;disk control port. 000A = rtcnt equ 10 ;retry count. ; ; ; select dsk number according to register c. ; 043E 210000 seldsk: lxi h,0000h ;error return code 0441 F3 di 0442 00 nop ;call check 0443 00 nop 0444 00 nop 0445 00 nop 0446 00 nop 0447 00 nop ;call rdfacil 0448 00 nop 0449 00 nop 044A 00 nop 044B 00 nop 044C 3A5101 lda nodsks ;get no. of dsks if not onedsk dcr a endif 044F B9 cmp c 0450 D8 rc ;err ret if diskno > nodsks new$old: 0451 79 mov a,c ;get new dsk no. 0452 211806 lxi h,diskno ;get adr of old dsk no. 0455 BE cmp m ;new = old? 0456 CA6D04 jz getdph ;yes, return = dph if onedsk 0459 F5 push a ;save disk number. 045A 210B06 lxi h,mntmsg ;get adr of mount mess. 045D CDDB05 call pmsg ;print "mount". 0460 F1 pop a ;get dsk number. 0461 321806 sta diskno ;update old with new. 0464 C661 adi 'a' ;add ascii for 'a'. 0466 4F mov c,a ;put into c. 0467 CDE403 call conot ;print it. 046A CDD803 call conin ;read a character endif if not onedsk selmor: mov e,m ;put old dsk no. in d&e. mvi d,0 lxi h,trtab ;get addr. of track table. push h dad d ;add dsk no. to address. in track ;read 1771 track reg. mov m,a ;put into table. mov e,c ;new disk no. in d$e. pop h ;get addr. of track table dad d ;add dsk no. to addr. mov a,m ;get new track no. out track ;put into 1771 track reg. mov a,c ;update old dsk no. sta diskno LXI H,SELECT$TABLE MVI B,0 DAD B MOV A,M sta latch ;save new latch code. endif getdph: 046D 2A1806 lhld diskno 0470 29 dad h ;*2 0471 29 dad h ;*4 0472 29 dad h ;*8 0473 29 dad h ;*16 0474 115201 lxi d,dpbase 0477 19 dad d ; = dpbase(diskno*16) 0478 00 nop ;call rlfacil 0479 00 nop 047A 00 nop 047B 00 nop 047C 00 nop 047D 00 nop 047E C9 ret ;return from seldsk. SELECT$TABLE: 047F 00 DB 0 0480 06 DB 6 0481 0A DB 10 0482 12 DB 18 ; rdfacil: 0483 F5 push psw 0484 C5 push b 0485 D5 push d 0486 E5 push h 0487 3E00 mvi a,000h 0489 219304 lxi h,store 048C 77 mov m,a 048D F1 pop psw 048E C1 pop b 048F D1 pop d 0490 E1 pop h 0491 F3 di 0492 C9 ret store: 0493 FF db 0ffh poldsk: 0494 219304 lxi h,store 0497 7E mov a,m 0498 C9 ret rlfacil: 0499 F5 push psw 049A E5 push h 049B 3EFF mvi a,0ffh 049D 219304 lxi h,store 04A0 77 mov m,a 04A1 F1 pop psw 04A2 E1 pop h 04A3 C9 ret check: 04A4 F5 push psw 04A5 C5 push b 04A6 D5 push d 04A7 E5 push h 04A8 0E83 mvi c,poll 04AA 1E01 mvi e,pldsk 04AC CDFA00 call xdos 04AF F1 pop psw 04B0 C1 pop b 04B1 D1 pop d 04B2 E1 pop h 04B3 F3 di 04B4 C9 ret ; move dsk to track zero. ; 04B5 0E00 home: mvi c,0 ;seek to track zero. ; ; set track no. to whatever is in register c. ; also perform move to correct track (seek). ; settrk: if not dubsid ;if not double-sided dsk 04B7 E5 push h ;save h&l. 04B8 2A1D06 lhld latch ;get new & old latch. 04BB 7D mov a,l ;get new latch. 04BC D3EC out dcont ;select drv. now. 04BE 321E06 sta clatch ;remember current latch. 04C1 BC cmp h ;is it same as old? 04C2 3EFF mvi a,0ffh ;if not, set flag = ff 04C4 C2C804 jnz sflag 04C7 2F cma ;if new = old, flag = 0. 04C8 321A06 sflag: sta hlsf ;set head-load/select flag. 04CB E1 pop h ;restore h&l. endif 04CC 79 mov a,c ;get new track no. if dubsid ;if double-sided dsk rrc ;shift right once push psw ;save revised trk # push h lhld latch ;get new & old latch mov a,l ;put new latch in a jc side2 ;if trk # odd, side #2 ani 1eh ;clear latch bit for side 1 jmp setlat ;go ahead and set latch side2: ori 1 ;set latch bit for side 2 setlat: out dcont ;output to the latch sta clatch ;set current latch code xra h ;compare old with new ani 1eh ;ignore side bit mvi a,0ffh ;if old not = new, jnz setfl ; set flag = ff cma ;if old = new, flag = 0 setfl: sta hlsf ;set flag zero if same pop h pop psw ani 7fh ;clear msb mov c,a ;set c = trk # endif 04CD 321406 sta trk ;update old with new. ; ; move head to the track in register a. ; 04D0 C5 seek: push b ;save b&c. 04D1 47 mov b,a ;save destination track. 04D2 3E0A mvi a,rtcnt ;get retry count. 04D4 322006 sretry: sta sercnt ;store in error counter. 04D7 DBE9 in track ;read present track no. 04D9 4F mov c,a ;save in c. 04DA 79 mov a,c ;delay. 04DB B8 cmp b ;same as new track no.? 04DC 78 mov a,b ;restore a from b. 04DD C2E204 jnz nothr ;jump if not there. 04E0 C1 there: pop b ;restore b&c. 04E1 C9 ret ;return from seek. nothr: ; ; this routine is to allow time for the drive ; tunnel erase to terminate before moving the ; head. the delay is approx. 700 micro-sec. @ ; 4 mhz cpu time, and double this for 2 mhz cpu's. ; 04E2 F5 push psw ;save accum and flags 04E3 3ED0 mvi a,0d0h ;delay count = 208 04E5 3D busy1: dcr a ;decrease count. 04E6 C2E504 jnz busy1 ;loop till done 04E9 F1 pop psw ;restore accum and flags. 04EA D3EB out ddata ;track to data register. 04EC DBE8 busy: in dstat ;read dsk status. 04EE 0F rrc ;look a bit 0. 04EF DAEC04 jc busy ;wait till not busy. 04F2 3E1E mvi a,14h+stprat+hlab ;get step rate, do 04F4 D3E8 out dcom ;seek with verify. 04F6 DBEC in wait ;wait for intrq. 04F8 DBE8 in dstat ;read status. 04FA E691 ani 91h ;look at bits. 04FC CAE004 jz there ;ok, if zero. 04FF 3A2006 lda sercnt ;get err cnt. 0502 3D dcr a ;decrement cnt. 0503 C2D404 jnz sretry ;retry seek. 0506 C1 pop b ;restore b&c 0507 210306 lxi h,skmsg ;print "seek". 050A C34605 jmp ermsg ;do common messages. ; ; set dsk sector no. ; 050D 79 setsec: mov a,c ;get sector no. 050E 321506 sta sect ;put at sect # addr. 0511 C9 ret ;return from setsec. ; ; set dsk dma address. ; 0512 60 setdma: mov h,b ;move b&c to h&l. 0513 69 mov l,c 0514 221606 shld dmaadd ;put dma addr address. 0517 C9 ret ;return from setdma. ; ; translate the sector given by using the ; translate table given by ; sectran: 0518 EB xchg ; = trans 0519 09 dad b ; = trans(sector) 051A 6E mov l,m ; = trans(sector) 051B 2600 mvi h,0 ; = trans(sector) 051D C9 ret ;with value in ; ; read the sector at sect, from the present track. ; use starting address at dmaadd. ; 051E 3E0A read: mvi a,rtcnt ;get retry count. 0520 CDA905 rretry: call rw$retry ;store in error ctr. 0523 C688 adi 88h ;add code for read sect. 0525 D3E8 reade: out dcom ;send command to 1771. 0527 DBEC rloop: in wait ;wait for drq or intrq. 0529 B7 ora a ;set flags 052A F23405 jp rddone ;done if intrq. 052D DBEB in ddata ;get byte from dsk. 052F 77 mov m,a ;put byte into memory. 0530 23 inx h ;increment memory pointer. 0531 C32705 jmp rloop ;keep reading. 0534 DBE8 rddone: in dstat ;read dsk status. if intrp ;if interrupts allowed, ei ;allow again here. endif 0536 E69D ani 9dh ;look at error bits. 0538 C8 rz ;return if none. 0539 CD5205 call erchk ;check for seek error. 053C 3A1F06 lda ercnt ;get error count 053F 3D dcr a ;decrement count. 0540 C22005 jnz rretry ;try to read again. 0543 21F205 lxi h,rdmsg ;print "read ". 0546 CDDB05 ermsg: call pmsg ;print origin message. ermsg1: 0549 21EB05 lxi h,errmsg ;print "error." 054C CDDB05 call pmsg 054F 3E01 mvi a,1 ;set for perm err msg 0551 C9 ret ; ; erchk - check for record not found error. ; erchk: 0552 E610 ani 10h ;if record not found, 0554 C8 rz ;return, no errors ; check for seek to correct track, ; and change if necessary. 0555 3EC4 chksk: mvi a,0c4h ;send command to 1771 0557 D3E8 out dcom ;to read address. 0559 DBEC in wait ;wait for drq or intrq. 055B DBEB in ddata ;read the track address. 055D 47 mov b,a ;save in reg b. 055E DBEC chks2: in wait ;wait for intrq. 0560 B7 ora a ;se| flags. 0561 F26905 jp chks3 ;done with read adr op. 0564 DBEB in ddata ;read another byte. 0566 C35E05 jmp chks2 ;do it again. 0569 DBE8 chks3: in dstat ;read dsk status. 056B B7 ora a ;set flags. 056C CA7505 jz chks4 ;read adr ok if 0. 056F CDB504 call home ;otherwise, home first. 0572 C37805 jmp chks5 0575 78 chks4: mov a,b ;update track reg. 0576 D3E9 out track 0578 3A1406 chks5: lda trk ;get required track no. 057B C3D004 jmp seek ;move head to it. ; ; write the sector at sect, on the present track. ; use starting address at dmaadd. ; 057E 3E0A write: mvi a,rtcnt ;get retry count. 0580 CDA905 wretry: call rw$retry ;store in error counter. 0583 C6A8 adi 0a8h ;add code for write. 0585 D3E8 write2: out dcom 0587 DBEC wloop: in wait ;wait for ready. 0589 B7 ora a ;set flags. 058A F29405 jp wdone ;hop when done. 058D 7E mov a,m ;get byte from mem. 058E D3EB out ddata ;write onto dsk. 0590 23 inx h ;increment mem ptr. 0591 C38705 jmp wloop ;keep writing. 0594 DBE8 wdone: in dstat ;read dsk status. if intrp ;if interrupts allowed, ei ;enable again here. endif 0596 E6FD ani 0fdh ;look at these bits. 0598 C8 rz ;return if no err. 0599 CD5205 call erchk ;check/correct seek err. 059C 3A1F06 lda ercnt ;get error count. 059F 3D dcr a ;decrement count. 05A0 C28005 jnz wretry ;try to write again. 05A3 21FA05 lxi h,wtmsg ;print "write ". 05A6 C34605 jmp ermsg ; ; read / write retry subroutine ; rw$retry: 05A9 321F06 sta ercnt ;store in error counter 05AC 2A1606 lhld dmaadd ;get starting addr. 05AF 3ED0 mvi a,0d0h ;cause interrupt. 05B1 D3E8 out dcom 05B3 E3 xthl ;some delay 05B4 E3 xthl if intrp ;if interrupts allowed, di ;disable them here. endif 05B5 3A1506 lda sect ;get sector no. 05B8 D3EA out sectp ;set sector into 1771. ; ; hdld - get head-load bit if required. ; 05BA 3A1A06 hdld: lda hlsf ;get head-load flag. 05BD B7 ora a ;is a = 0? 05BE CAD205 jz hdld1 ;hop if so. 05C1 2F cma ;set a = 0. 05C2 321A06 sta hlsf ;set flag = 0 if not. ; ; if changing to a new drive, perform a seek to ; the same track to allow the head to unload. ; 05C5 DBE9 in track ;get present track 05C7 D3EB out ddata ;and tell 1771 about it. 05C9 3E1E mvi a,14h+stprat+hlab ;get the step rate. 05CB D3E8 out dcom ;send it to floppy controller. 05CD DBEC in wait ;wait for intrq. 05CF 3E04 hdldy: mvi a,4 ;set bit to load head. 05D1 C9 ret ;return from hdld. 05D2 DBE8 hdld1: in dstat ;read 1771 status. 05D4 E620 ani 20h ;look at hl bit. 05D6 CACF05 jz hdldy ;load if not loaded. 05D9 AF xra a ;otherwise, a = 0. 05DA C9 ret ;return from hdld. ; ; print the message at h&l until a zero. ; 05DB 7E pmsg: mov a,m ;get a char. 05DC B7 ora a ;if it's zero, 05DD C8 rz ;return 05DE 4F mov c,a ;otherwise, 05DF CDE403 call conot ;print it. 05E2 23 inx h ;increment h&l, 05E3 C3DB05 jmp pmsg ;and get another. ; ; cbios messages ; 05E6 426F6F7420btmsg: db 'Boot ' 05EB 4572726F72errmsg: db 'Error.',0 05F2 0D0A526561rdmsg: db 0dh,0ah,'Read ',0 05FA 0D0A577269wtmsg: db 0dh,0ah,'Write ',0 0603 0D0A536565skmsg: db 0dh,0ah,'Seek ',0 if onedsk 060B 0D0A4D6F75mntmsg: db 0dh,0ah,'Mount ',0 endif ; bios scratch area. ; org $ 0614 trk: ds 1 ;current track no. 0615 sect: ds 1 ;current sector no. 0616 dmaadd: ds 2 ;disk transfer address ; ; the next several bytes, between startz and ; endz, are set to zero at cold boot time. ; 0618 org $ startz: ;start of zeroed area. 0618 diskno: ds 2 ;disk no. (to cp/m). ; special flags. 061A hlsf: ds 1 ;head-load select flag. ; ; trtab - disk track table - present position of ; heads for up to ndisks drvs ; 061B trtab: ds ndisks endz: ;end of zeroed area. ; 061C org $ 061C lcount: ds 1 ;character counter 061D latch: ds 1 ;new code for latch 061E clatch: ds 1 ;current code in latch. 061F ercnt: ds 1 ;err/r count for retries 0620 sercnt: ds 1 ;seek retry counter 0621 temp: ds 1 ;temporary storage ; ; scratch ram area for bdos use ; 0622 = begdat equ $ ;beginning of data area 0622 dirbf: ds 128 ;scratch directory area if not dubsid 06A2 all00: ds 31 ;allocation vector 0 06C1 chk00: ds 16 ;check vector 0 06D1 all01: ds 31 ;allocation vector 1 06F0 chk01: ds 16 ;check vector 1 endif if disk3 or disk4 and not dubsid all02: ds 31 ;allocation vector 2 chk02: ds 16 ;check vector 2 endif if disk4 and not dubsid all03: ds 31 ;allocation vector 3 chk03: ds 16 ;check vector 3 endif if dubsid all00: ds 32 ;allocation vector 0 chk00: ds 32 ;check vector 0 all01: ds 32 ;allocation vector 1 chk01: ds 32 ;check vector 1 endif if disk3 or disk4 and dubsid all02: ds 32 ;allocation vector 2 chk02: ds 32 ;check vector 2 endif if disk4 and dubsid all03: ds 32 ;allocation vector 3 chk03: ds 32 ;check vector 3 endif ; 0700 = enddat equ $ ;end of data area 0700 00 db 0 00DF = datsiz equ $-begdat ;size of data area 0701 00 db 0 0702 end