; 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 0000 ORG 0000H FFFD = pdisp equ $-3 FFFA = xdos equ pdisp-3 013A = 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. ; 0000 C34B00 jmp coldstart ;from cold start loader. 0003 C34B00 jmp warmstart ;from warm boot. 0006 C32B01 jmp constd ;check console kb status. 0009 C33601 jmp conind ;read console char. 000C C34101 jmp conotd ;write console char. 000F C38C01 jmp list ;write listing char. 0012 C35301 jmp rtnempty ;write punch char. 0015 C35301 jmp rtnempty ;read reader char. 0018 C34404 jmp home ;move disk to zero. 001B C3EF03 jmp seldsk ;select disk drive. 001E C34604 jmp settrk ;seek to track in reg a. 0021 C39C04 jmp setsec ;set sector number. 0024 C3A104 jmp setdma ;set disk starting address. 0027 C3AD04 jmp read ;read selected sector. 002A C30D05 jmp write ;write selected sector. 002D C3A001 jmp pollpt ;return list status. 0030 C3A704 jmp sectran 0033 C3C401 jmp selmemory 0036 C3A301 jmp polldevice 0039 C3CC01 jmp startclock 003C C3D201 jmp stopclock 003F C3D701 jmp exitregion 0042 C3DE01 jmp maxconsole 0045 C3E101 jmp systeminit 0048 C34002 jmp idle coldstart: warmstart: 004B 0E00 mvi c,0 004D C3FAFF jmp xdos ; ; data byte for number of disk drives ; 0050 02 nodsks: db ndisks ; ; ; fixed data tables for tw0-drive standard ; ibm-compatible 8" disks ; ; disk parameter header for disk 00 0051 71000000 dpbase: dw trans,0000h 0055 00000000 dw 0000h,0000h 0059 A9058B00 dw dirbf,dpblk 005D 48062906 dw chk00,all00 ; disk parameter header for disk 01 0061 71000000 dw trans,0000h 0065 00000000 dw 0000h,0000h 0069 A9058B00 dw dirbf,dpblk 006D 77065806 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 ; 0071 01070D13 trans: db 1,7,13,19 ;sectors 1,2,3,4 0075 19050B11 db 25,5,11,17 ;sectors 5,6,7,8 0079 1703090F db 23,3,9,15 ;sectors 9,10,11,12 007D 1502080E db 21,2,8,14 ;sectors 13,14,15,16 0081 141A060C db 20,26,6,12 ;sectors 17,18,19,20 0085 1218040A db 18,24,4,10 ;sectors 21,22,23,24 0089 1016 db 16,22 ;sectors 25,26 ; dpblk: ;disk parameter block, common to all disks 008B 1A00 dw spt ;sectors per track if not dubsid 008D 03 db 3 ;block shift factor 008E 07 db 7 ;block mask 008F 00 db 0 ;null mask 0090 F200 dw 242 ;disk size-1 0092 3F00 dw 63 ;directory max 0094 C0 db 192 ;alloc 0 0095 00 db 0 ;alloc 1 0096 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 0098 0200 dw off ;track offset ; ; end of fixed tables ; ; ; signon message ; smsg: 009A 0C0A0D db 12,10,13 009D 4578706C6F db 'Explorer-85 ' 00A9 0A0D db 10,13 00AB 4D756C7469db'Multi processor' 00BA 0A0D db 10,13 00BC 54696D652Ddb'Time-Sharing' 00C8 0A0D db 10,13 00CA 436F6D7075db'Computer System' if dubsid endif 00D9 0A0D db 10,13 00DB 0A0D db 10,13 00DD 0A0D db 10,13 00DF 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: 00E0 3E88 MVI A,88H 00E2 D3CF OUT 0CFH 00E4 3E00 MVI A,00H 00E6 D3CC OUT 0CCH 00E8 3E06 MVI A,06H 00EA D3CD OUT 0CDH 00EC 3E01 MVI A,01H 00EE D3CE OUT 0CEH 00F0 3ECD mvi a,mode51 00F2 D3C5 out cntl51 00F4 D3C9 OUT CNTL51+4 00F6 3E27 mvi a,cmd51 00F8 D3C5 out cntl51 00FA D3C9 OUT CNTL51+4 00FC DBC4 in rxd51 00FE DBC8 IN RXD51+4 0100 3ECF MVI A,0CFH 0102 D3C1 OUT CMD1 0104 3ECE MVI A,0CEH ;OUT CMD2 0106 3ECE MVI A,0CEH ;OUT CMD3 0108 3E27 MVI A,27H 010A D3C1 OUT CMD1 010C 3E27 MVI A,27H ;OUT CMD2 010E 3E27 MVI A,27H ;OUT CMD3 ; if intrp ;if interrupts allowed, ei ;enable them here. endif boot2: 0110 AF xra a ;clear scratch area. 0111 320400 sta cdisk 0114 0E05 mvi c,endz-startz ;get length of zero area. 0116 219E05 lxi h,startz ;get scratch address. 0119 77 bootl: mov m,a ;put zero in memory. 011A 23 inx h ;increment pointer. 011B 0D dcr c ;decrement counter. 011C C21901 jnz bootl ;loop till done. 011F 3650 mvi m,llimit ;set line limit 0121 23 inx h ;point to latch byte 0122 3600 mvi m,0 ;set latch code = 0. gocpm: ; ; set jumps into cp/m in lower memory. ; 0124 218000 lxi h,80h ;set default dma adr. 0127 229C05 shld dmaadd 012A C9 ret; ; constd: 012B CD4C01 call ptbljmp 012E 6001 dw pt0st 0130 4D03 DW PT1ST 0132 8203 DW PT2ST 0134 B703 DW PT3ST conind: 0136 CD4C01 call ptbljmp 0139 6301 dw pt0in 013B 5603 DW PT1IN 013D 8B03 DW PT2IN 013F C003 DW PT3IN conotd: 0141 CD4C01 call ptbljmp 0144 6D01 dw pt0out 0146 6203 DW PT1OUT 0148 9703 DW PT2OUT 014A CC03 DW PT3OUT ptbljmp: 014C 7A mov a,d 014D FE04 cpi nmbcns 014F DA5501 jc tbljmp 0152 F1 pop psw rtnempty: 0153 AF xra a 0154 C9 ret tbljmp: 0155 87 add a 0156 E1 pop h 0157 5F mov e,a 0158 1600 mvi d,0 015A 19 dad d 015B 5E mov e,m 015C 23 inx h 015D 56 mov d,m 015E EB xchg 015F E9 pchl polci0: pt0st: 0160 C3E102 jmp const pt0in: 0163 0E83 mvi c,poll 0165 1E06 mvi e,plci0 0167 CDFAFF call xdos 016A C3EA02 jmp conin pt0out: 016D DBC5 in cstat 016F E604 ani cptr 0171 C27901 jnz co0rdy 0174 C5 push b 0175 CD7C01 call pt0wait 0178 C1 pop b co0rdy: 0179 C3F602 jmp conot pt0wait: 017C 0E83 mvi c,poll 017E 1E02 mvi e,plco0 0180 C3FAFF jmp xdos 0183 C9 ret polco0: 0184 DBC5 in cstat 0186 E604 ani cptr 0188 C8 rz 0189 3EFF mvi a,0ffh 018B C9 ret list: 018C CD4603 call ltbsy 018F B7 ora a 0190 C29C01 jnz lptrdy 0193 C5 push b 0194 0E83 mvi c,poll 0196 1E00 mvi e,pllpt 0198 CDFAFF call xdos 019B C1 pop b lptrdy: 019C 79 mov a,c 019D D3C8 out ldata 019F C9 ret pollpt: 01A0 C34603 jmp ltbsy 000A = nmbdev equ 10 polldevice: 01A3 79 mov a,c 01A4 FE0A cpi nmbdev 01A6 DAAB01 jc devok 01A9 3E0A mvi a,nmbdev devok: 01AB CD5501 call tbljmp 01AE A001 dw pollpt 01B0 3D04 dw poldsk 01B2 8401 dw polco0 01B4 7A03 DW POLCO1 01B6 AF03 DW POLCO2 01B8 E403 DW POLCO3 01BA 6001 DW POLCI0 01BC 4D03 DW POLCI1 01BE 8203 DW POLCI2 01C0 B703 DW POLCI3 01C2 5301 dw rtnempty selmemory: 01C4 210300 lxi h,3; 01C7 09 dad b; 01C8 7E mov a,m; 01C9 D340 out 040h; 01CB C9 ret startclock: 01CC 3EFF mvi a,0ffh 01CE 32DF02 sta tickn 01D1 C9 ret stopclock: 01D2 AF xra a 01D3 32DF02 sta tickn 01D6 C9 ret exitregion: 01D7 3AE002 lda preemp 01DA B7 ora a 01DB C0 rnz 01DC FB ei 01DD C9 ret maxconsole: 01DE 3E04 mvi a,nmbcns 01E0 C9 ret systeminit: 01E1 F3 di 01E2 223C02 shld svdjt; 01E5 69 mov l,c 01E6 2600 mvi h,0; 01E8 29 dad h; 01E9 29 dad h; 01EA 29 dad h; 01EB 223E02 shld svdbpa; ; 01EE CDE000 call boot1 ; 01F1 3E40 mvi a,40h; 01F3 CD2002 call stmvtr; 01F6 3E20 mvi a,20h; 01F8 CD2002 call stmvtr; 01FB 3E10 mvi a,10h; 01FD CD2002 call stmvtr; 0200 3E08 mvi a,08h; 0202 CD2002 call stmvtr; 0205 3E04 mvi a,04h; 0207 CD2002 call stmvtr; 020A 3E02 mvi a,02h; 020C CD2002 call stmvtr; 020F 3E01 mvi a,01h; 0211 CD2002 call stmvtr; ; ; bootr: 0214 219A00 lxi h,smsg; 0217 CD6A05 call pmsg; 021A 3E9F mvi a,9fh; 021C D3EF out 0efh; 021E FB ei 021F C9 ret stmvtr: 0220 D340 out 040h; 0222 CD1001 call boot2; 0225 3EC3 mvi a,0c3h; 0227 320000 sta 0; 022A 2A3C02 lhld svdjt; 022D 220100 shld 1; 0230 3EC3 mvi a,0c3h; 0232 322000 sta 0020h; 0235 214302 lxi h,intlhnd; 0238 222100 shld 0021h; 023B C9 ret; 023C svdjt: ds 2; 023E svdbpa: ds 2; idle: 0240 FB ei 0241 76 hlt 0242 C9 ret 0085 = flagset equ 133 008E = dsptch equ 142 intlhnd: 0243 F5 push psw 0244 3E9F mvi a,9fh 0246 D3EF out 0efh 0248 3AA702 lda slice 024B 3D dcr a 024C 32A702 sta slice 024F CA5502 jz t16ms 0252 F1 pop psw 0253 FB ei 0254 C9 ret t16ms: 0255 3E10 mvi a,16 0257 32A702 sta slice 025A F1 pop psw 025B 22D902 shld svdhl 025E E1 pop h 025F 22DD02 shld svdret 0262 F5 push psw 0263 210000 lxi h,0 0266 39 dad sp 0267 22DB02 shld svdsp 026A 31D902 lxi sp,intstk+48 026D D5 push d 026E C5 push b 026F 3EFF mvi a,0ffh 0271 32E002 sta preemp 0274 3ADF02 lda tickn 0277 B7 ora a 0278 CA8202 jz notickn 027B 0E85 mvi c,flagset 027D 1E01 mvi e,1 027F CDFAFF call xdos notickn: 0282 21A802 lxi h,cnt64 0285 35 dcr m 0286 C29202 jnz notlsec 0289 3657 mvi m,57h 028B 0E85 mvi c,flagset 028D 1E02 mvi e,2 028F CDFAFF call xdos notlsec: 0292 AF xra a 0293 32E002 sta preemp 0296 C1 pop b 0297 D1 pop d 0298 2ADB02 lhld svdsp 029B F9 sphl 029C F1 pop psw 029D 2ADD02 lhld svdret 02A0 E5 push h 02A1 2AD902 lhld svdhl 02A4 C3FDFF jmp pdisp ; ; 02A7 10 slice: db 16 02A8 40 cnt64: db 64 02A9 intstk: ds 48 02D9 0000 svdhl: dw 0 02DB 0000 svdsp: dw 0 02DD 0000 svdret: dw 0 02DF 00 tickn: db 0 02E0 00 preemp: db 0 ; check console input status. ; const: 02E1 DBC5 in cstat ;get status 02E3 E602 ani ckbr ;look at flag bit stat$ret: 02E5 3E00 mvi a,0 ;set a=0, for return 02E7 C8 rz 02E8 2F cma ;if ready (pressed) a=ff 02E9 C9 ret ; ; read a character from console. ; conin: 02EA CDE102 call const ;get console status 02ED B7 ora a 02EE CAEA02 jz conin ;not ready yet 02F1 DBC4 in cdata ;get data byte mask: 02F3 E67F ani 7fh ;make most sig. bit = 0. 02F5 C9 ret ; ; write a character to the console device. ; conot: IF COLCNT 02F6 E5 push h 02F7 CD3B03 call conota ;output the char 02FA 21A305 lxi h,lcount ;get char. counter 02FD 79 mov a,c ;get char. 02FE FE0C CPI 12 ;IS IT FORM FEED 0300 C21803 JNZ ISITCR ;JP TO ISITCR 0303 C5 PUSH B 0304 E5 PUSH H 0305 0602 MVI B,2 0307 210000 LXI H,0 WAIT1: 030A 2D DCR L 030B C20A03 JNZ WAIT1 030E 25 DCR H 030F C20A03 JNZ WAIT1 0312 05 DCR B 0313 C20A03 JNZ WAIT1 0316 E1 POP H 0317 C1 POP B ISITCR: 0318 FE0D cpi 13 ;is it 'cr' 031A CA3703 jz slimit 031D FE0A cpi 10 ;is it 'lf' 031F CA2803 jz lfeed 0322 FE08 cpi 8 ;is it 'bs' 0324 C22903 jnz getcnt 0327 34 inr m lfeed: 0328 34 inr m getcnt: 0329 35 dcr m 032A C23903 jnz conxit 032D 0E0D mvi c,13 ;echo a 'cr' 032F CD3B03 call conota 0332 0E0A mvi c,10 ;and a 'lf' 0334 CD3B03 call conota slimit: 0337 3650 mvi m,llimit ;reset counter conxit: 0339 E1 pop h 033A C9 ret ENDIF conota: 033B DBC5 in cstat ;read console status 033D E604 ani cptr 033F CA3B03 jz conota ;loop until ready 0342 79 mov a,c ;get character 0343 D3C4 out cdata ;print it 0345 C9 ret ; ; write a character on listing device ; ltbsy: 0346 DBC9 in lstat ;read lister status 0348 E604 ani lrbit ;look at ready bit 034A C3E502 jmp stat$ret POLCI1: PT1ST: 034D DBC1 IN STS1 034F E602 ANI CKBR 0351 3E00 MVI A,0 0353 C8 RZ 0354 2F CMA 0355 C9 RET ; PT1IN: 0356 0E83 MVI C,POLL 0358 1E07 MVI E,PLCI1 035A CDFAFF CALL XDOS 035D DBC0 IN DATA1 035F E67F ANI 7FH 0361 C9 RET ; PT1OUT: 0362 DBC1 IN STS1 0364 E604 ANI CPTR 0366 C26E03 JNZ CO1RDY 0369 C5 PUSH B 036A CD7203 CALL PT1WAIT 036D C1 POP B CO1RDY: 036E 79 MOV A,C 036F D3C0 OUT DATA1 0371 C9 RET PT1WAIT: 0372 0E83 MVI C,POLL 0374 1E03 MVI E,PLCO1 0376 C3FAFF JMP XDOS 0379 C9 RET ; POLCO1: 037A DBC1 IN STS1 037C E604 ANI CPTR 037E C8 RZ 037F 3EFF MVI A,0FFH 0381 C9 RET ; POLCI2: PT2ST: 0382 DBE1 IN STS2 0384 E602 ANI CKBR 0386 3E00 MVI A,0 0388 C8 RZ 0389 2F CMA 038A C9 RET ; PT2IN: 038B 0E83 MVI C,POLL 038D 1E08 MVI E,PLCI2 038F CDFAFF CALL XDOS 0392 DBE0 IN DATA2 0394 E67F ANI 7FH 0396 C9 RET ; PT2OUT: 0397 DBE1 IN STS2 0399 E604 ANI CPTR 039B C2A303 JNZ CO2RDY 039E C5 PUSH B 039F CDA703 CALL PT2WAIT 03A2 C1 POP B CO2RDY: 03A3 79 MOV A,C 03A4 D3E0 OUT DATA2 03A6 C9 RET PT2WAIT: 03A7 0E83 MVI C,POLL 03A9 1E04 MVI E,PLCO2 03AB C3FAFF JMP XDOS 03AE C9 RET ; POLCO2: 03AF DBE1 IN STS2 03B1 E604 ANI CPTR 03B3 C8 RZ 03B4 3EFF MVI A,0FFH 03B6 C9 RET ; POLCI3: PT3ST: 03B7 DBE3 IN STS3 03B9 E602 ANI CKBR 03BB 3E00 MVI A,0 03BD C8 RZ 03BE 2F CMA 03BF C9 RET ; PT3IN: 03C0 0E83 MVI C,POLL 03C2 1E09 MVI E,PLCI3 03C4 CDFAFF CALL XDOS 03C7 DBE2 IN DATA3 03C9 E67F ANI 7FH 03CB C9 RET ; PT3OUT: 03CC DBE3 IN STS3 03CE E604 ANI CPTR 03D0 C2D803 JNZ CO3RDY 03D3 C5 PUSH B 03D4 CDDC03 CALL PT3WAIT 03D7 C1 POP B CO3RDY: 03D8 79 MOV A,C 03D9 D3E2 OUT DATA3 03DB C9 RET PT3WAIT: 03DC 0E83 MVI C,POLL 03DE 1E05 MVI E,PLCO3 03E0 C3FAFF JMP XDOS 03E3 C9 RET ; POLCO3: 03E4 DBE3 IN STS3 03E6 E604 ANI CPTR 03E8 C8 RZ 03E9 3EFF MVI A,0FFH 03EB C9 RET ; ; ; read paper tape ; reader: 03EC 3E1A mvi a,1ah ;cp/m eof returned for them. ; ; punch paper tape. ; punch: 03EE 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. ; 03EF 210000 seldsk: lxi h,0000h ;error return code 03F2 F3 di 03F3 00 nop 03F4 00 nop 03F5 00 nop 03F6 00 nop 03F7 00 nop 03F8 00 nop 03F9 00 nop 03FA 00 nop 03FB 3A5000 lda nodsks ;get no. of dsks if not onedsk 03FE 3D dcr a endif 03FF B9 cmp c 0400 D8 rc ;err ret if diskno > nodsks new$old: 0401 79 mov a,c ;get new dsk no. 0402 219E05 lxi h,diskno ;get adr of old dsk no. 0405 BE cmp m ;new = old? 0406 CA2804 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: 0409 5E mov e,m ;put old dsk no. in d&e. 040A 1600 mvi d,0 040C 21A105 lxi h,trtab ;get addr. of track table. 040F E5 push h 0410 19 dad d ;add dsk no. to address. 0411 DBE9 in track ;read 1771 track reg. 0413 77 mov m,a ;put into table. 0414 59 mov e,c ;new disk no. in d$e. 0415 E1 pop h ;get addr. of track table 0416 19 dad d ;add dsk no. to addr. 0417 7E mov a,m ;get new track no. 0418 D3E9 out track ;put into 1771 track reg. 041A 79 mov a,c ;update old dsk no. 041B 329E05 sta diskno 041E 213904 LXI H,SELECT$TABLE 0421 0600 MVI B,0 0423 09 DAD B 0424 7E MOV A,M 0425 32A405 sta latch ;save new latch code. endif getdph: 0428 2A9E05 lhld diskno 042B 29 dad h ;*2 042C 29 dad h ;*4 042D 29 dad h ;*8 042E 29 dad h ;*16 042F 115100 lxi d,dpbase 0432 19 dad d ; = dpbase(diskno*16) 0433 00 nop 0434 00 nop 0435 00 nop 0436 00 nop 0437 00 nop 0438 C9 ret ;return from seldsk. SELECT$TABLE: 0439 00 DB 0 043A 06 DB 6 043B 0A DB 10 043C 12 DB 18 ; poldsk: 043D DBE8 in dstat ;read disk status. 043F 0F rrc ;look at bit 0. 0440 D8 rc ;not done. 0441 3EFF mvi a,0ffh ;done and ready flag. 0443 C9 ret ;return to xdos ; move dsk to track zero. ; 0444 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 0446 E5 push h ;save h&l. 0447 2AA405 lhld latch ;get new & old latch. 044A 7D mov a,l ;get new latch. 044B D3EC out dcont ;select drv. now. 044D 32A505 sta clatch ;remember current latch. 0450 BC cmp h ;is it same as old? 0451 3EFF mvi a,0ffh ;if not, set flag = ff 0453 C25704 jnz sflag 0456 2F cma ;if new = old, flag = 0. 0457 32A005 sflag: sta hlsf ;set head-load/select flag. 045A E1 pop h ;restore h&l. endif 045B 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 045C 329A05 sta trk ;update old with new. ; ; move head to the track in register a. ; 045F C5 seek: push b ;save b&c. 0460 47 mov b,a ;save destination track. 0461 3E0A mvi a,rtcnt ;get retry count. 0463 32A705 sretry: sta sercnt ;store in error counter. 0466 DBE9 in track ;read present track no. 0468 4F mov c,a ;save in c. 0469 79 mov a,c ;delay. 046A B8 cmp b ;same as new track no.? 046B 78 mov a,b ;restore a from b. 046C C27104 jnz nothr ;jump if not there. 046F C1 there: pop b ;restore b&c. 0470 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. ; 0471 F5 push psw ;save accum and flags 0472 3ED0 mvi a,0d0h ;delay count = 208 0474 3D busy1: dcr a ;decrease count. 0475 C27404 jnz busy1 ;loop till done 0478 F1 pop psw ;restore accum and flags. 0479 D3EB out ddata ;track to data register. 047B DBE8 busy: in dstat ;read dsk status. 047D 0F rrc ;look a bit 0. 047E DA7B04 jc busy ;wait till not busy. 0481 3E1E mvi a,14h+stprat+hlab ;get step rate, do 0483 D3E8 out dcom ;seek with verify. 0485 DBEC in wait ;wait for intrq. 0487 DBE8 in dstat ;read status. 0489 E691 ani 91h ;look at bits. 048B CA6F04 jz there ;ok, if zero. 048E 3AA705 lda sercnt ;get err cnt. 0491 3D dcr a ;decrement cnt. 0492 C26304 jnz sretry ;retry seek. 0495 C1 pop b ;restore b&c 0496 219205 lxi h,skmsg ;print "seek". 0499 C3D504 jmp ermsg ;do common messages. ; ; set dsk sector no. ; 049C 79 setsec: mov a,c ;get sector no. 049D 329B05 sta sect ;put at sect # addr. 04A0 C9 ret ;return from setsec. ; ; set dsk dma address. ; 04A1 60 setdma: mov h,b ;move b&c to h&l. 04A2 69 mov l,c 04A3 229C05 shld dmaadd ;put dma addr address. 04A6 C9 ret ;return from setdma. ; ; translate the sector given by using the ; translate table given by ; sectran: 04A7 EB xchg ; = trans 04A8 09 dad b ; = trans(sector) 04A9 6E mov l,m ; = trans(sector) 04AA 2600 mvi h,0 ; = trans(sector) 04AC C9 ret ;with value in ; ; read the sector at sect, from the present track. ; use starting address at dmaadd. ; 04AD 3E0A read: mvi a,rtcnt ;get retry count. 04AF CD3805 rretry: call rw$retry ;store in error ctr. 04B2 C688 adi 88h ;add code for read sect. 04B4 D3E8 reade: out dcom ;send command to 1771. 04B6 DBEC rloop: in wait ;wait for drq or intrq. 04B8 B7 ora a ;set flags 04B9 F2C304 jp rddone ;done if intrq. 04BC DBEB in ddata ;get byte from dsk. 04BE 77 mov m,a ;put byte into memory. 04BF 23 inx h ;increment memory pointer. 04C0 C3B604 jmp rloop ;keep reading. 04C3 DBE8 rddone: in dstat ;read dsk status. if intrp ;if interrupts allowed, ei ;allow again here. endif 04C5 E69D ani 9dh ;look at error bits. 04C7 C8 rz ;return if none. 04C8 CDE104 call erchk ;chekk(for(smek mrroz. 04CB 3AA605 lda ercnt ;get error count 04CE 3D dcr a ;decrement count. 04CF C2AF04 jnz rretry ;try(to reid(ioain. 04D2 218105 lxi h,rdmsg ;print "read ". 04D5 CD6A05 ermsg: call pmsg ;print origin message. ermsg1: 04D8 217A05 lxi h,errmsg ;print "error." 04DB CD6A05 call pmsg 04DE 3E09 mvi a,9 ;{e| foz xerm err msg 04E0 C9 ret ; ; erchk - check for record not found error. ; erchk: 04E1 E610 ani 10h ;if record not found, 04E3 C8 rz ;return, no errors ; check for seek to correct track, ; and change if necessary. 04E4 3EC4 chksk: mvi a,0c4h ;send command to 1771 04E6 D3E8 out dcom ;to read address. 04E8 DBEC in wait ;wait for drq or intrq. 04EA DBEB in ddata ;read the track address. 04EC 47 mov b,a ;save in reg b. 04ED DBEC chks2: in wait ;wait for intrq. 04EF B7 ora a ;se| flags. 04F0 F2F804 jp chks3 ;done with read adr op. 04F3 DBEB in ddata ;read another byte. 04F5 C3ED04 jmp chks2 ;do it again. 04F8 DBE8 chks3: in dstat ;read dsk status. 04FA B7 ora a ;set flags. 04FB CA0405 jz chks4 ;read adr ok if 0. 04FE CD4404 call home ;otherwise, home first. 0501 C30705 jmp chks5 0504 78 chks4: mov a,b ;update track reg. 0505 D3E9 out track 0507 3A9A05 chks5: lda trk ;get required track no. 050A C35F04 jmp seek ;move head to it. ; ; write the sector at sect, on the present track. ; use starting address at dmaadd. ; 050D 3E0A write: mvi a,rtcnt ;get retry count. 050F CD3805 wretry: call rw$retry ;store in error counter. 0512 C6A8 adi 0a8h ;add code for write. 0514 D3E8 write2: out dcom 0516 DBEC wloop: in wait ;wait for ready. 0518 B7 ora a ;set flags. 0519 F22305 jp wdone ;hop when done. 051C 7E mov a,m ;get byte from mem. 051D D3EB out ddata ;write onto dsk. 051F 23 inx h ;increment mem ptr. 0520 C31605 jmp wloop ;keep writing. 0523 DBE8 wdone: in dstat ;read dsk status. if intrp ;if interrupts allowed, ei ;enable again here. endif 0525 E6FD ani 0fdh ;look at these bits. 0527 C8 rz ;return if no err. 0528 CDE104 call erchk ;check/correct seek err. 052B 3AA605 lda ercnt ;get error count. 052E 3D dcr a ;decrement count. 052F C20F05 jnz wretry ;try to write again. 0532 218905 lxi h,wtmsg ;print "write ". 0535 C3D504 jmp ermsg ; ; read / write retry subroutine ; rw$retry: 0538 32A605 sta ercnt ;store in error counter 053B 2A9C05 lhld dmaadd ;get starting addr. 053E 3ED0 mvi a,0d0h ;cause interrupt. 0540 D3E8 out dcom 0542 E3 xthl ;some delay 0543 E3 xthl if intrp ;if interrupts allowed, di ;disable them here. endif 0544 3A9B05 lda sect ;get sector no. 0547 D3EA out sectp ;set sector into 1771. ; ; hdld - get head-load bit if required. ; 0549 3AA005 hdld: lda hlsf ;get head-load flag. 054C B7 ora a ;is a = 0? 054D CA6105 jz hdld1 ;hop if so. 0550 2F cma ;set a = 0. 0551 32A005 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. ; 0554 DBE9 in track ;get present track 0556 D3EB out ddata ;and tell 1771 about it. 0558 3E1E mvi a,14h+stprat+hlab ;get the step rate. 055A D3E8 out dcom ;send it to floppy controller. 055C DBEC in wait ;wait for intrq. 055E 3E04 hdldy: mvi a,4 ;set bit to load head. 0560 C9 ret ;return from hdld. 0561 DBE8 hdld1: in dstat ;read 1771 status. 0563 E620 ani 20h ;look at hl bit. 0565 CA5E05 jz hdldy ;load if not loaded. 0568 AF xra a ;otherwise, a = 0. 0569 C9 ret ;return from hdld. ; ; print the message at h&l until a zero. ; 056A 7E pmsg: mov a,m ;get a char. 056B B7 ora a ;if it's zero, 056C C8 rz ;return 056D 4F mov c,a ;otherwise, 056E CDF602 call conot ;print it. 0571 23 inx h ;increment h&l, 0572 C36A05 jmp pmsg ;and get another. ; ; cbios messages ; 0575 426F6F7420btmsg: db 'Boot ' 057A 4572726F72errmsg: db 'Error.',0 0581 0D0A526561rdmsg: db 0dh,0ah,'Read ',0 0589 0D0A577269wtmsg: db 0dh,0ah,'Write ',0 0592 0D0A536565skmsg: db 0dh,0ah,'Seek ',0 if onedsk mntmsg: db 0dh,0ah,'Mount ',0 endif ; bios scratch area. ; org $ 059A trk: ds 1 ;current track no. 059B sect: ds 1 ;current sector no. 059C dmaadd: ds 2 ;disk transfer address ; ; the next several bytes, between startz and ; endz, are set to zero at cold boot time. ; 059E org $ startz: ;start of zeroed area. 059E diskno: ds 2 ;disk no. (to cp/m). ; special flags. 05A0 hlsf: ds 1 ;head-load select flag. ; ; trtab - disk track table - present position of ; heads for up to ndisks drvs ; 05A1 trtab: ds ndisks endz: ;end of zeroed area. ; 05A3 org $ 05A3 lcount: ds 1 ;character counter 05A4 latch: ds 1 ;new code for latch 05A5 clatch: ds 1 ;current code in latch. 05A6 ercnt: ds 1 ;err/r count for retries 05A7 sercnt: ds 1 ;seek retry counter 05A8 temp: ds 1 ;temporary storage ; ; scratch ram area for bdos use ; 05A9 = begdat equ $ ;beginning of data area 05A9 dirbf: ds 128 ;scratch directory area if not dubsid 0629 all00: ds 31 ;allocation vector 0 0648 chk00: ds 16 ;check vector 0 0658 all01: ds 31 ;allocation vector 1 0677 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 ; 0687 = enddat equ $ ;end of data area 0687 00 db 0 00DF = datsiz equ $-begdat ;size of data area 0688 00 db 0 0689 end