; 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. ; 0040 = msize equ 64 ;memory size in kbytes. 0002 = ndisks equ 2 ;number of disk drives 0016 = vers equ 22 ;cp/m version number 0012 = bvers equ 18 ;bios version number FFFE = onedsk equ not((((ndisks-1)+3)and 4)shr 2) if onedsk disk4 equ false disk3 equ false endif if not onedsk 0000 = disk4 equ (ndisks and 0000$0100b) shr 2 0000 = 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 0050 = cpl equ 80 ;characters/line 0050 = llimit equ cpl ;characters/line ; 00C5 = cstat equ 0C5H ;console status port 00C5 = ccom equ 0C5H ;console command port 00C4 = cdata equ 0C4H ;console data port 00C9 = lstat equ 0C9H ;list status port. 00C9 = lcom equ 0C9H ;list command port. 00C8 = ldata equ 0C8H ;list data port. 00C0 = DATA1 EQU 0C0H 00C1 = STS1 EQU 0C1H 00C1 = CMD1 EQU 0C1H 00E0 = DATA2 EQU 0E0H 00E1 = STS2 EQU 0E1H 00E1 = CMD2 EQU 0E1H 00E2 = DATA3 EQU 0E2H 00E3 = STS3 EQU 0E3H 00E3 = CMD3 EQU 0E3H ; 0009 = PLCI3 EQU 9 0005 = PLCO3 EQU 5 0008 = PLCI2 EQU 8 0004 = PLCO2 EQU 4 0007 = PLCI1 EQU 7 0003 = PLCO1 EQU 3 0006 = plci0 equ 6 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 0004 = nmbcns equ 4 0100 ORG 0100H 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 C34B01 jmp coldstart ;from cold start loader. 0103 C34B01 jmp warmstart ;from warm boot. 0106 C32B02 jmp constd ;check console kb status. 0109 C33602 jmp conind ;read console char. 010C C34102 jmp conotd ;write console char. 010F C38C02 jmp list ;write listing char. 0112 C35302 jmp rtnempty ;write punch char. 0115 C35302 jmp rtnempty ;read reader char. 0118 C34405 jmp home ;move disk to zero. 011B C3EF04 jmp seldsk ;select disk drive. 011E C34605 jmp settrk ;seek to track in reg a. 0121 C39C05 jmp setsec ;set sector number. 0124 C3A105 jmp setdma ;set disk starting address. 0127 C3AD05 jmp read ;read selected sector. 012A C30D06 jmp write ;write selected sector. 012D C3A002 jmp pollpt ;return list status. 0130 C3A705 jmp sectran 0133 C3C402 jmp selmemory 0136 C3A302 jmp polldevice 0139 C3CC02 jmp startclock 013C C3D202 jmp stopclock 013F C3D702 jmp exitregion 0142 C3DE02 jmp maxconsole 0145 C3E102 jmp systeminit 0148 C34003 jmp idle coldstart: warmstart: 014B 0E00 mvi c,0 014D C3FA00 jmp xdos ; ; data byte for number of disk drives ; 0150 02 nodsks: db ndisks ; ; ; fixed data tables for tw0-drive standard ; ibm-compatible 8" disks ; ; disk parameter header for disk 00 0151 71010000 dpbase: dw trans,0000h 0155 00000000 dw 0000h,0000h 0159 A9068B01 dw dirbf,dpblk 015D 48072907 dw chk00,all00 ; disk parameter header for disk 01 0161 71010000 dw trans,0000h 0165 00000000 dw 0000h,0000h 0169 A9068B01 dw dirbf,dpblk 016D 77075807 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 ; 0171 01070D13 trans: db 1,7,13,19 ;sectors 1,2,3,4 0175 19050B11 db 25,5,11,17 ;sectors 5,6,7,8 0179 1703090F db 23,3,9,15 ;sectors 9,10,11,12 017D 1502080E db 21,2,8,14 ;sectors 13,14,15,16 0181 141A060C db 20,26,6,12 ;sectors 17,18,19,20 0185 1218040A db 18,24,4,10 ;sectors 21,22,23,24 0189 1016 db 16,22 ;sectors 25,26 ; dpblk: ;disk parameter block, common to all disks 018B 1A00 dw spt ;sectors per track if not dubsid 018D 03 db 3 ;block shift factor 018E 07 db 7 ;block mask 018F 00 db 0 ;null mask 0190 F200 dw 242 ;disk size-1 0192 3F00 dw 63 ;directory max 0194 C0 db 192 ;alloc 0 0195 00 db 0 ;alloc 1 0196 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 0198 0200 dw off ;track offset ; ; end of fixed tables ; ; ; signon message ; smsg: 019A 0C0A0D db 12,10,13 019D 4578706C6F db 'Explorer-85 ' 01A9 0A0D db 10,13 01AB 4D756C7469db'Multi processor' 01BA 0A0D db 10,13 01BC 54696D652Ddb'Time-Sharing' 01C8 0A0D db 10,13 01CA 436F6D7075db'Computer System' if dubsid endif 01D9 0A0D db 10,13 01DB 0A0D db 10,13 01DD 0A0D db 10,13 01DF 00 db 0 BOOT1: ; ; boot ; this section is executed whenever reset and run ; after the coldstart loader reads in ; the cp/m system. ; 00C5 = STAT51 EQU 0C5H 00C5 = cntl51 equ 0C5H 00C4 = rxd51 equ 0C4H 00CD = MODE51 EQU 0CDH 0027 = CMD51 EQU 27H boot: 01E0 3E88 MVI A,88H 01E2 D3CF OUT 0CFH 01E4 3E00 MVI A,00H 01E6 D3CC OUT 0CCH 01E8 3E06 MVI A,06H 01EA D3CD OUT 0CDH 01EC 3E01 MVI A,01H 01EE D3CE OUT 0CEH 01F0 3ECD mvi a,mode51 01F2 D3C5 out cntl51 01F4 D3C9 OUT CNTL51+4 01F6 3E27 mvi a,cmd51 01F8 D3C5 out cntl51 01FA D3C9 OUT CNTL51+4 01FC DBC4 in rxd51 01FE DBC8 IN RXD51+4 0200 3ECF MVI A,0CFH 0202 D3C1 OUT CMD1 0204 3ECE MVI A,0CEH ;OUT CMD2 0206 3ECE MVI A,0CEH ;OUT CMD3 0208 3E27 MVI A,27H 020A D3C1 OUT CMD1 020C 3E27 MVI A,27H ;OUT CMD2 020E 3E27 MVI A,27H ;OUT CMD3 ; if intrp ;if interrupts allowed, ei ;enable them here. endif boot2: 0210 AF xra a ;clear scratch area. 0211 320400 sta cdisk 0214 0E05 mvi c,endz-startz ;get length of zero area. 0216 219E06 lxi h,startz ;get scratch address. 0219 77 bootl: mov m,a ;put zero in memory. 021A 23 inx h ;increment pointer. 021B 0D dcr c ;decrement counter. 021C C21902 jnz bootl ;loop till done. 021F 3650 mvi m,llimit ;set line limit 0221 23 inx h ;point to latch byte 0222 3600 mvi m,0 ;set latch code = 0. gocpm: ; ; set jumps into cp/m in lower memory. ; 0224 218000 lxi h,80h ;set default dma adr. 0227 229C06 shld dmaadd 022A C9 ret; ; constd: 022B CD4C02 call ptbljmp 022E 6002 dw pt0st 0230 4D04 DW PT1ST 0232 8204 DW PT2ST 0234 B704 DW PT3ST conind: 0236 CD4C02 call ptbljmp 0239 6302 dw pt0in 023B 5604 DW PT1IN 023D 8B04 DW PT2IN 023F C004 DW PT3IN conotd: 0241 CD4C02 call ptbljmp 0244 6D02 dw pt0out 0246 6204 DW PT1OUT 0248 9704 DW PT2OUT 024A CC04 DW PT3OUT ptbljmp: 024C 7A mov a,d 024D FE04 cpi nmbcns 024F DA5502 jc tbljmp 0252 F1 pop psw rtnempty: 0253 AF xra a 0254 C9 ret tbljmp: 0255 87 add a 0256 E1 pop h 0257 5F mov e,a 0258 1600 mvi d,0 025A 19 dad d 025B 5E mov e,m 025C 23 inx h 025D 56 mov d,m 025E EB xchg 025F E9 pchl polci0: pt0st: 0260 C3E103 jmp const pt0in: 0263 0E83 mvi c,poll 0265 1E06 mvi e,plci0 0267 CDFA00 call xdos 026A C3EA03 jmp conin pt0out: 026D DBC5 in cstat 026F E604 ani cptr 0271 C27902 jnz co0rdy 0274 C5 push b 0275 CD7C02 call pt0wait 0278 C1 pop b co0rdy: 0279 C3F603 jmp conot pt0wait: 027C 0E83 mvi c,poll 027E 1E02 mvi e,plco0 0280 C3FA00 jmp xdos 0283 C9 ret polco0: 0284 DBC5 in cstat 0286 E604 ani cptr 0288 C8 rz 0289 3EFF mvi a,0ffh 028B C9 ret list: 028C CD4604 call ltbsy 028F B7 ora a 0290 C29C02 jnz lptrdy 0293 C5 push b 0294 0E83 mvi c,poll 0296 1E00 mvi e,pllpt 0298 CDFA00 call xdos 029B C1 pop b lptrdy: 029C 79 mov a,c 029D D3C8 out ldata 029F C9 ret pollpt: 02A0 C34604 jmp ltbsy 000A = nmbdev equ 10 polldevice: 02A3 79 mov a,c 02A4 FE0A cpi nmbdev 02A6 DAAB02 jc devok 02A9 3E0A mvi a,nmbdev devok: 02AB CD5502 call tbljmp 02AE A002 dw pollpt 02B0 3D05 dw poldsk 02B2 8402 dw polco0 02B4 7A04 DW POLCO1 02B6 AF04 DW POLCO2 02B8 E404 DW POLCO3 02BA 6002 DW POLCI0 02BC 4D04 DW POLCI1 02BE 8204 DW POLCI2 02C0 B704 DW POLCI3 02C2 5302 dw rtnempty selmemory: 02C4 210300 lxi h,3; 02C7 09 dad b; 02C8 7E mov a,m; 02C9 D340 out 040h; 02CB C9 ret startclock: 02CC 3EFF mvi a,0ffh 02CE 32DF03 sta tickn 02D1 C9 ret stopclock: 02D2 AF xra a 02D3 32DF03 sta tickn 02D6 C9 ret exitregion: 02D7 3AE003 lda preemp 02DA B7 ora a 02DB C0 rnz 02DC FB ei 02DD C9 ret maxconsole: 02DE 3E04 mvi a,nmbcns 02E0 C9 ret systeminit: 02E1 F3 di 02E2 223C03 shld svdjt; 02E5 69 mov l,c 02E6 2600 mvi h,0; 02E8 29 dad h; 02E9 29 dad h; 02EA 29 dad h; 02EB 223E03 shld svdbpa; ; 02EE CDE001 call boot1 ; 02F1 3E40 mvi a,40h; 02F3 CD2003 call stmvtr; 02F6 3E20 mvi a,20h; 02F8 CD2003 call stmvtr; 02FB 3E10 mvi a,10h; 02FD CD2003 call stmvtr; 0300 3E08 mvi a,08h; 0302 CD2003 call stmvtr; 0305 3E04 mvi a,04h; 0307 CD2003 call stmvtr; 030A 3E02 mvi a,02h; 030C CD2003 call stmvtr; 030F 3E01 mvi a,01h; 0311 CD2003 call stmvtr; ; ; bootr: 0314 219A01 lxi h,smsg; 0317 CD6A06 call pmsg; 031A 3E9F mvi a,9fh; 031C D3EF out 0efh; 031E FB ei 031F C9 ret stmvtr: 0320 D340 out 040h; 0322 CD1002 call boot2; 0325 3EC3 mvi a,0c3h; 0327 320000 sta 0; 032A 2A3C03 lhld svdjt; 032D 220100 shld 1; 0330 3EC3 mvi a,0c3h; 0332 322000 sta 0020h; 0335 214303 lxi h,intlhnd; 0338 222100 shld 0021h; 033B C9 ret; 033C svdjt: ds 2; 033E svdbpa: ds 2; idle: 0340 FB ei 0341 76 hlt 0342 C9 ret 0085 = flagset equ 133 008E = dsptch equ 142 intlhnd: 0343 F5 push psw 0344 3E9F mvi a,9fh 0346 D3EF out 0efh 0348 3AA703 lda slice 034B 3D dcr a 034C 32A703 sta slice 034F CA5503 jz t16ms 0352 F1 pop psw 0353 FB ei 0354 C9 ret t16ms: 0355 3E10 mvi a,16 0357 32A703 sta slice 035A F1 pop psw 035B 22D903 shld svdhl 035E E1 pop h 035F 22DD03 shld svdret 0362 F5 push psw 0363 210000 lxi h,0 0366 39 dad sp 0367 22DB03 shld svdsp 036A 31D903 lxi sp,intstk+48 036D D5 push d 036E C5 push b 036F 3EFF mvi a,0ffh 0371 32E003 sta preemp 0374 3ADF03 lda tickn 0377 B7 ora a 0378 CA8203 jz notickn 037B 0E85 mvi c,flagset 037D 1E01 mvi e,1 037F CDFA00 call xdos notickn: 0382 21A803 lxi h,cnt64 0385 35 dcr m 0386 C29203 jnz notlsec 0389 3657 mvi m,57h 038B 0E85 mvi c,flagset 038D 1E02 mvi e,2 038F CDFA00 call xdos notlsec: 0392 AF xra a 0393 32E003 sta preemp 0396 C1 pop b 0397 D1 pop d 0398 2ADB03 lhld svdsp 039B F9 sphl 039C F1 pop psw 039D 2ADD03 lhld svdret 03A0 E5 push h 03A1 2AD903 lhld svdhl 03A4 C3FD00 jmp pdisp ; ; 03A7 10 slice: db 16 03A8 40 cnt64: db 64 03A9 intstk: ds 48 03D9 0000 svdhl: dw 0 03DB 0000 svdsp: dw 0 03DD 0000 svdret: dw 0 03DF 00 tickn: db 0 03E0 00 preemp: db 0 ; check console input status. ; const: 03E1 DBC5 in cstat ;get status 03E3 E602 ani ckbr ;look at flag bit stat$ret: 03E5 3E00 mvi a,0 ;set a=0, for return 03E7 C8 rz 03E8 2F cma ;if ready (pressed) a=ff 03E9 C9 ret ; ; read a character from console. ; conin: 03EA CDE103 call const ;get console status 03ED B7 ora a 03EE CAEA03 jz conin ;not ready yet 03F1 DBC4 in cdata ;get data byte mask: 03F3 E67F ani 7fh ;make most sig. bit = 0. 03F5 C9 ret ; ; write a character to the console device. ; conot: IF COLCNT 03F6 E5 push h 03F7 CD3B04 call conota ;output the char 03FA 21A306 lxi h,lcount ;get char. counter 03FD 79 mov a,c ;get char. 03FE FE0C CPI 12 ;IS IT FORM FEED 0400 C21804 JNZ ISITCR ;JP TO ISITCR 0403 C5 PUSH B 0404 E5 PUSH H 0405 0602 MVI B,2 0407 210000 LXI H,0 WAIT1: 040A 2D DCR L 040B C20A04 JNZ WAIT1 040E 25 DCR H 040F C20A04 JNZ WAIT1 0412 05 DCR B 0413 C20A04 JNZ WAIT1 0416 E1 POP H 0417 C1 POP B ISITCR: 0418 FE0D cpi 13 ;is it 'cr' 041A CA3704 jz slimit 041D FE0A cpi 10 ;is it 'lf' 041F CA2804 jz lfeed 0422 FE08 cpi 8 ;is it 'bs' 0424 C22904 jnz getcnt 0427 34 inr m lfeed: 0428 34 inr m getcnt: 0429 35 dcr m 042A C23904 jnz conxit 042D 0E0D mvi c,13 ;echo a 'cr' 042F CD3B04 call conota 0432 0E0A mvi c,10 ;and a 'lf' 0434 CD3B04 call conota slimit: 0437 3650 mvi m,llimit ;reset counter conxit: 0439 E1 pop h 043A C9 ret ENDIF conota: 043B DBC5 in cstat ;read console status 043D E604 ani cptr 043F CA3B04 jz conota ;loop until ready 0442 79 mov a,c ;get character 0443 D3C4 out cdata ;print it 0445 C9 ret ; ; write a character on listing device ; ltbsy: 0446 DBC9 in lstat ;read lister status 0448 E604 ani lrbit ;look at ready bit 044A C3E503 jmp stat$ret POLCI1: PT1ST: 044D DBC1 IN STS1 044F E602 ANI CKBR 0451 3E00 MVI A,0 0453 C8 RZ 0454 2F CMA 0455 C9 RET ; PT1IN: 0456 0E83 MVI C,POLL 0458 1E07 MVI E,PLCI1 045A CDFA00 CALL XDOS 045D DBC0 IN DATA1 045F E67F ANI 7FH 0461 C9 RET ; PT1OUT: 0462 DBC1 IN STS1 0464 E604 ANI CPTR 0466 C26E04 JNZ CO1RDY 0469 C5 PUSH B 046A CD7204 CALL PT1WAIT 046D C1 POP B CO1RDY: 046E 79 MOV A,C 046F D3C0 OUT DATA1 0471 C9 RET PT1WAIT: 0472 0E83 MVI C,POLL 0474 1E03 MVI E,PLCO1 0476 C3FA00 JMP XDOS 0479 C9 RET ; POLCO1: 047A DBC1 IN STS1 047C E604 ANI CPTR 047E C8 RZ 047F 3EFF MVI A,0FFH 0481 C9 RET ; POLCI2: PT2ST: 0482 DBE1 IN STS2 0484 E602 ANI CKBR 0486 3E00 MVI A,0 0488 C8 RZ 0489 2F CMA 048A C9 RET ; PT2IN: 048B 0E83 MVI C,POLL 048D 1E08 MVI E,PLCI2 048F CDFA00 CALL XDOS 0492 DBE0 IN DATA2 0494 E67F ANI 7FH 0496 C9 RET ; PT2OUT: 0497 DBE1 IN STS2 0499 E604 ANI CPTR 049B C2A304 JNZ CO2RDY 049E C5 PUSH B 049F CDA704 CALL PT2WAIT 04A2 C1 POP B CO2RDY: 04A3 79 MOV A,C 04A4 D3E0 OUT DATA2 04A6 C9 RET PT2WAIT: 04A7 0E83 MVI C,POLL 04A9 1E04 MVI E,PLCO2 04AB C3FA00 JMP XDOS 04AE C9 RET ; POLCO2: 04AF DBE1 IN STS2 04B1 E604 ANI CPTR 04B3 C8 RZ 04B4 3EFF MVI A,0FFH 04B6 C9 RET ; POLCI3: PT3ST: 04B7 DBE3 IN STS3 04B9 E602 ANI CKBR 04BB 3E00 MVI A,0 04BD C8 RZ 04BE 2F CMA 04BF C9 RET ; PT3IN: 04C0 0E83 MVI C,POLL 04C2 1E09 MVI E,PLCI3 04C4 CDFA00 CALL XDOS 04C7 DBE2 IN DATA3 04C9 E67F ANI 7FH 04CB C9 RET ; PT3OUT: 04CC DBE3 IN STS3 04CE E604 ANI CPTR 04D0 C2D804 JNZ CO3RDY 04D3 C5 PUSH B 04D4 CDDC04 CALL PT3WAIT 04D7 C1 POP B CO3RDY: 04D8 79 MOV A,C 04D9 D3E2 OUT DATA3 04DB C9 RET PT3WAIT: 04DC 0E83 MVI C,POLL 04DE 1E05 MVI E,PLCO3 04E0 C3FA00 JMP XDOS 04E3 C9 RET ; POLCO3: 04E4 DBE3 IN STS3 04E6 E604 ANI CPTR 04E8 C8 RZ 04E9 3EFF MVI A,0FFH 04EB C9 RET ; ; ; read paper tape ; reader: 04EC 3E1A mvi a,1ah ;cp/m eof returned for them. ; ; punch paper tape. ; punch: 04EE 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=18ms, 3=20m{. ; 00E8 = disk equ 0e8h ;disk base address. 00E8 = dcom equ disk ;disk command pozt. 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. ; 04EF 210000 seldsk: lxi h,0000h ;error return code 04F2 F3 di 04F3 00 nop 04F4 00 nop 04F5 00 nop 04F6 00 nop 04F7 00 nop 04F8 00 nop 04F9 00 nop 04FA 00 nop 04FB 3A5001 lda nodsks ;get no. of dsks if not onedsk 04FE 3D dcr a endif 04FF B9 cmp c 0500 D8 rc ;err ret if diskno > nodsks new$old: 0501 79 mov a,c ;get new dsk no. 0502 219E06 lxi h,diskno ;get adr of old dsk no. 0505 BE cmp m ;new = old? 0506 CA2805 jz getdph ;yes, return = dph if onedsk push a ;save disk number. lxi h,mntmsg ;get adr of mount mess. call pmsg ;print "mount". pop a ;get dsk number. sta diskno ;update old with new. adi 'a' ;add ascii for 'a'. mov c,a ;put into c. call conot ;print it. call conin ;read a character endif if not onedsk selmor: 0509 5E mov e,m ;put old dsk no. in d&e. 050A 1600 mvi d,0 050C 21A106 lxi h,trtab ;get addr. of track table. 050F E5 push h 0510 19 dad d ;add dsk no. to address. 0511 DBE9 in track ;read 1771 track reg. 0513 77 mov m,a ;put into table. 0514 59 mov e,c ;new disk no. in d$e. 0515 E1 pop h ;get addr. of track table 0516 19 dad d ;add dsk no. to addr. 0517 7E mov a,m ;get new track no. 0518 D3E9 out track ;put into 1771 track reg. 051A 79 mov a,c ;update old dsk no. 051B 329E06 sta diskno 051E 213905 LXI H,SELECT$TABLE 0521 0600 MVI B,0 0523 09 DAD B 0524 7E MOV A,M 0525 32A406 sta latch ;save new latch code. endif getdph: 0528 2A9E06 lhld diskno 052B 29 dad h ;*2 052C 29 dad h ;*4 052D 29 dad h ;*8 052E 29 dad h ;*16 052F 115101 lxi d,dpbase 0532 19 dad d ; = dpbase(diskno*16) 0533 00 nop 0534 00 nop 0535 00 nop 0536 00 nop 0537 00 nop 0538 C9 ret ;return from seldsk. SELECT$TABLE: 0539 00 DB 0 053A 06 DB 6 053B 0A DB 10 053C 12 DB 18 ; poldsk: 053D DBE8 in dstat ;read disk status. 053F 0F rrc ;look at bit 0. 0540 D8 rc ;not done. 0541 3EFF mvi a,0ffh ;done and ready flag. 0543 C9 ret ;return to xdos ; move dsk to track zero. ; 0544 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 0546 E5 push h ;save h&l. 0547 2AA406 lhld latch ;get new & old latch. 054A 7D mov a,l ;get new latch. 054B D3EC out dcont ;select drv. now. 054D 32A506 sta clatch ;remember current latch. 0550 BC cmp h ;is it same as old? 0551 3EFF mvi a,0ffh ;if not, set flag = ff 0553 C25705 jnz sflag 0556 2F cma ;if new = old, flag = 0. 0557 32A006 sflag: sta hlsf ;set head-load/select flag. 055A E1 pop h ;restore h&l. endif 055B 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 055C 329A06 sta trk ;update old with new. ; ; move head to the track in register a. ; 055F C5 seek: push b ;save b&c. 0560 47 mov b,a ;save destination track. 0561 3E0A mvi a,rtcnt ;get retry count. 0563 32A706 sretry: sta sercnt ;store in error counter. 0566 DBE9 in track ;read present track no. 0568 4F mov c,a ;save in c. 0569 79 mov a,c ;delay. 056A B8 cmp b ;same as new track no.? 056B 78 mov a,b ;restore a from b. 056C C27105 jnz nothr ;jump if not there. 056F C1 there: pop b ;restore b&c. 0570 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. ; 0571 F5 push psw ;save accum and flags 0572 3ED0 mvi a,0d0h ;delay count = 208 0574 3D busy1: dcr a ;decrease count. 0575 C27405 jnz busy1 ;loop till done 0578 F1 pop psw ;restore accum and flags. 0579 D3EB out ddata ;track to data register. 057B DBE8 busy: in dstat ;read dsk status. 057D 0F rrc ;look a bit 0. 057E DA7B05 jc busy ;wait till not busy. 0581 3E1E mvi a,14h+stprat+hlab ;get step rate, do 0583 D3E8 out dcom ;seek with verify. 0585 DBEC in wait ;wait for intrq. 0587 DBE8 in dstat ;read status. 0589 E691 ani 91h ;look at bits. 058B CA6F05 jz there ;ok, if zero. 058E 3AA706 lda sercnt ;get err cnt. 0591 3D dcr a ;decrement cnt. 0592 C26305 jnz sretry ;retry seek. 0595 C1 pop b ;restore b&c 0596 219206 lxi h,skmsg ;print "seek". 0599 C3D505 jmp ermsg ;do common messages. ; ; set dsk sector no. ; 059C 79 setsec: mov a,c ;get sector no. 059D 329B06 sta sect ;put at sect # addr. 05A0 C9 ret ;return from setsec. ; ; set dsk dma address. ; 05A1 60 setdma: mov h,b ;move b&c to h&l. 05A2 69 mov l,c 05A3 229C06 shld dmaadd ;put dma addr address. 05A6 C9 ret ;return from setdma. ; ; translate the sector given by using the ; translate table given by ; sectran: 05A7 EB xchg ; = trans 05A8 09 dad b ; = trans(sector) 05A9 6E mov l,m ; = trans(sector) 05AA 2600 mvi h,0 ; = trans(sector) 05AC C9 ret ;with value in ; ; read the sector at sect, from the present track. ; use starting address at dmaadd. ; 05AD 3E0A read: mvi a,rtcnt ;get retry count. 05AF CD3806 rretry: call rw$retry ;store in error ctr. 05B2 C688 adi 88h ;add code for read sect. 05B4 D3E8 reade: out dcom ;send command to 1771. 05B6 DBEC rloop: in wait ;wait for drq or intrq. 05B8 B7 ora a ;set flags 05B9 F2C305 jp rddone ;done if intrq. 05BC DBEB in ddata ;get byte from dsk. 05BE 77 mov m,a ;put byte into memory. 05BF 23 inx h ;increment memory pointer. 05C0 C3B605 jmp rloop ;keep reading. 05C3 DBE8 rddone: in dstat ;read dsk status. if intrp ;if interrupts allowed, ei ;allow again here. endif 05C5 E69D ani 9dh ;look at error bits. 05C7 C8 rz ;return if none. 05C8 CDE105 call erchk ;chekk(for(smek mrroz. 05CB 3AA606 lda ercnt ;get error count 05CE 3D dcr a ;decrement count. 05CF C2AF05 jnz rretry ;try(to reid(ioain. 05D2 218106 lxi h,rdmsg ;print "read ". 05D5 CD6A06 ermsg: call pmsg ;print origin message. ermsg1: 05D8 217A06 lxi h,errmsg ;print "error." 05DB CD6A06 call pmsg 05DE 3E09 mvi a,9 ;{e| foz xerm err msg 05E0 C9 ret ; ; erchk - check for record not found error. ; erchk: 05E1 E610 ani 10h ;if record not found, 05E3 C8 rz ;return, no errors ; check for seek to correct track, ; and change if necessary. 05E4 3EC4 chksk: mvi a,0c4h ;send command to 1771 05E6 D3E8 out dcom ;to read address. 05E8 DBEC in wait ;wait for drq or intrq. 05EA DBEB in ddata ;read the track address. 05EC 47 mov b,a ;save in reg b. 05ED DBEC chks2: in wait ;wait for intrq. 05EF B7 ora a ;se| flags. 05F0 F2F805 jp chks3 ;done with read adr op. 05F3 DBEB in ddata ;read another byte. 05F5 C3ED05 jmp chks2 ;do it again. 05F8 DBE8 chks3: in dstat ;read dsk status. 05FA B7 ora a ;set flags. 05FB CA0406 jz chks4 ;read adr ok if 0. 05FE CD4405 call home ;otherwise, home first. 0601 C30706 jmp chks5 0604 78 chks4: mov a,b ;update track reg. 0605 D3E9 out track 0607 3A9A06 chks5: lda trk ;get required track no. 060A C35F05 jmp seek ;move head to it. ; ; write the sector at sect, on the present track. ; use starting address at dmaadd. ; 060D 3E0A write: mvi a,rtcnt ;get retry count. 060F CD3806 wretry: call rw$retry ;store in error counter. 0612 C6A8 adi 0a8h ;add code for write. 0614 D3E8 write2: out dcom 0616 DBEC wloop: in wait ;wait for ready. 0618 B7 ora a ;set flags. 0619 F22306 jp wdone ;hop when done. 061C 7E mov a,m ;get byte from mem. 061D D3EB out ddata ;write onto dsk. 061F 23 inx h ;increment mem ptr. 0620 C31606 jmp wloop ;keep writing. 0623 DBE8 wdone: in dstat ;read dsk status. if intrp ;if interrupts allowed, ei ;enable again here. endif 0625 E6FD ani 0fdh ;look at these bits. 0627 C8 rz ;return if no err. 0628 CDE105 call erchk ;check/correct seek err. 062B 3AA606 lda ercnt ;get error count. 062E 3D dcr a ;decrement count. 062F C20F06 jnz wretry ;try to write again. 0632 218906 lxi h,wtmsg ;print "write ". 0635 C3D505 jmp ermsg ; ; read / write retry subroutine ; rw$retry: 0638 32A606 sta ercnt ;store in error counter 063B 2A9C06 lhld dmaadd ;get starting addr. 063E 3ED0 mvi a,0d0h ;cause interrupt. 0640 D3E8 out dcom 0642 E3 xthl ;some delay 0643 E3 xthl if intrp ;if interrupts allowed, di ;disable them here. endif 0644 3A9B06 lda sect ;get sector no. 0647 D3EA out sectp ;set sector into 1771. ; ; hdld - get head-load bit if required. ; 0649 3AA006 hdld: lda hlsf ;get head-load flag. 064C B7 ora a ;is a = 0? 064D CA6106 jz hdld1 ;hop if so. 0650 2F cma ;set a = 0. 0651 32A006 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. ; 0654 DBE9 in track ;get present track 0656 D3EB out ddata ;and tell 1771 about it. 0658 3E1E mvi a,14h+stprat+hlab ;get the step rate. 065A D3E8 out dcom ;send it to floppy controller. 065C DBEC in wait ;wait for intrq. 065E 3E04 hdldy: mvi a,4 ;set bit to load head. 0660 C9 ret ;return from hdld. 0661 DBE8 hdld1: in dstat ;read 1771 status. 0663 E620 ani 20h ;look at hl bit. 0665 CA5E06 jz hdldy ;load if not loaded. 0668 AF xra a ;otherwise, a = 0. 0669 C9 ret ;return from hdld. ; ; print the message at h&l until a zero. ; 066A 7E pmsg: mov a,m ;get a char. 066B B7 ora a ;if it's zero, 066C C8 rz ;return 066D 4F mov c,a ;otherwise, 066E CDF603 call conot ;print it. 0671 23 inx h ;increment h&l, 0672 C36A06 jmp pmsg ;and get another. ; ; cbios messages ; 0675 426F6F7420btmsg: db 'Boot ' 067A 4572726F72errmsg: db 'Error.',0 0681 0D0A526561rdmsg: db 0dh,0ah,'Read ',0 0689 0D0A577269wtmsg: db 0dh,0ah,'Write ',0 0692 0D0A536565skmsg: db 0dh,0ah,'Seek ',0 if onedsk mntmsg: db 0dh,0ah,'Mount ',0 endif ; bios scratch area. ; org $ 069A trk: ds 1 ;current track no. 069B sect: ds 1 ;current sector no. 069C dmaadd: ds 2 ;disk transfer address ; ; the next several bytes, between startz and ; endz, are set to zero at cold boot time. ; 069E org $ startz: ;start of zeroed area. 069E diskno: ds 2 ;disk no. (to cp/m). ; special flags. 06A0 hlsf: ds 1 ;head-load select flag. ; ; trtab - disk track table - present position of ; heads for up to ndisks drvs ; 06A1 trtab: ds ndisks endz: ;end of zeroed area. ; 06A3 org $ 06A3 lcount: ds 1 ;character counter 06A4 latch: ds 1 ;new code for latch 06A5 clatch: ds 1 ;current code in latch. 06A6 ercnt: ds 1 ;err/r count for retries 06A7 sercnt: ds 1 ;seek retry counter 06A8 temp: ds 1 ;temporary storage ; ; scratch ram area for bdos use ; 06A9 = begdat equ $ ;beginning of data area 06A9 dirbf: ds 128 ;scratch directory area if not dubsid 0729 all00: ds 31 ;allocation vector 0 0748 chk00: ds 16 ;check vector 0 0758 all01: ds 31 ;allocation vector 1 0777 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 ; 0787 = enddat equ $ ;end of data area 0787 00 db 0 00DF = datsiz equ $-begdat ;size of data area 0788 00 db 0 0789 end