N Appendix A The Microcomputer Development System Basic Input/Output System (BIOS) 1 ; mds-800 i/o drivers for cp/m 2.2 2 ; (four drive single density version) 3 ; 4 ; version 2.2 february, 1980 5 ; 6 0016 = vers equ 22 ;version 2.2 7 ; 8 ; copyright (c) 1980 9 ; digital research 10 ; box 579, pacific grove 11 ; california, 93950 12 ; 13 ; 14 ffff = true equ 0fffh ;value of "true" 15 0000 = false equ not true ;"false" 16 0000 = test equ false ;true if test bios 17 ; 18 if test 19 bias equ 03400h ;base of ccp in test system 20 endif 21 if not test 22 0000 = bias equ 0000h ;generate relocatable cp/m system 23 endif 24 ; 25 1600 = patch equ 1600h 26 ; 27 1600 org patch 28 0000 = cpmb equ $-patch ;base of cpm console processor 29 0806 = bdos equ 806h+cpmb ;basic dos (resident portion) 30 1600 = cpml equ $-cpmb ;length (in bytes) of cpm system 31 002c = nsects equ cpml/128 ;number of sectors to load 32 0002 = offset equ 2 ;number of disk tracks used by cp/m 33 0004 = cdisk equ 0004h ;address of last logged disk on warm start 34 0080 = buff equ 0080h ;default buffer address A-1 35 000a = retry equ 10 ;max retries on disk i/o before error 36 ; 37 ; perform following functions 38 ; boot cold start 39 ; wboot warm start (save i/o byte) 40 ; (boot and wboot are the same for mds) 41 ; const console status 42 ; reg-a = 00 if no character ready 43 ; reg-a = ff if character ready 44 ; conin console character in (result in reg-a) 45 ; conout console character out (char in reg-c) 46 ; list list out (char in reg-c) 47 ; punch punch out (char in reg-c) 48 ; reader paper tape reader in (result to reg-a) 49 ; home move to track 00 50 ; 51 ; (the following calls set-up the io parameter block for the 52 ; mds, which is used to perform subsequent reads and writes) 53 ; seldsk select disk given by reg-c (0, 1, 2...) 54 ; settrk set track address (0,...76) for subsequent read-write 55 ; setsec set sector address (1,...,26) for subsequent read-write 56 ; setdma set subsequent dma address (initially 80h) 57 ; 58 ; (read and write assume previous calls to set up the io parameters) 59 ; read read track/sector to preset dma address 60 ; write track/sector from preset dma address 61 ; 62 ; jump vector for individual routines 63 1600 c3b316 jmp boot 64 1603 c3c316 wboote: jmp wboot 65 1606 c36117 jmp const 66 1609 c36417 jmp conin 67 160c c36a17 jmp conout 68 160f c36d17 jmp list 69 1612 c37217 jmp punch 70 1615 c37517 jmp reader 71 1618 c37817 jmp home 72 161b c37d17 jmp seldsk 73 161e c3a717 jmp settrk 74 1621 c3ac17 jmp setsec A-2 75 1624 c3bb17 jmp setdma 76 1627 c3c117 jmp read 77 162a c3ca17 jmp write 78 162d c37017 jmp listst ;list status 79 1630 c3b117 jmp sectran 80 ; 81 maclib diskdef ;load the disk definition library 82 disks 4 ;four disks 83 1633+= dpbase equ $ ;base of disk parameter blocks 84 1633+82160000 dpe0: dw xlt0, 0000h ;translate table 85 1637+00000000 dw 0000h, 0000h ;scratch area 86 163b+6e187316 dw dirbuf, dpb0 ;dir buff, parm block 87 163f+0d19ee18 dw csv0, alv0 ;check, alloc vectors 88 1643+82160000 dpe1: dw xlt1, 0000h ;translate table 89 1647+00000000 dw 0000h, 0000h ;scratch area 90 164b+6e187316 dw dirbuf, dpb1 ;dir buff, parm block 91 164f+3c191d19 dw csv1, alv1 ;check, alloc vectors 92 1653+82160000 dpe2: dw xlt2, 0000h ;translate table 93 1657+00000000 dw 0000h, 0000h ;scratch area 94 165b+6e187316 dw dirbuf, dpb2 ;dir buff, parm block 95 165f+6b194c19 dw csv2, alv2 ;check, alloc vectors 96 1663+82160000 dpe3: dw xlt3, 0000h ;translate table 97 1667+00000000 dw 0000h, 0000h ;scratch area 98 166b+6e187316 dw dirbuf, dpb3 ;check, alloc block 99 166f+9a197b19 dw csv3, alv3 ;dir buff, parm vectors 100 diskdef 0, 1, 26, 6, 1024, 243, 64, 64, offset 101 1673+= dpb0 equ $ ;disk parm block 102 1673+1a00 dw 26 ;sec per track 103 1675+03 db 3 ;block shift 104 1676+07 db 7 ;block mask 105 1677+00 db 0 ;extnt mask 106 1678+f200 dw 242 ;disk size-1 107 167a+3f00 dw 63 ;directory max 108 167c+c0 db 192 ;alloc0 109 167d+00 db 0 ;alloc1 110 167e+1000 dw 16 ;check size 111 1680+0200 dw 2 ;offset 112 1682+= xlt0 equ $ ;translate table 113 1682+01 db 1 114 1683+07 db 7 A-3 115 1684+0d db 13 116 1685+13 db 19 117 1686+19 db 25 118 1687+05 db 5 119 1688+0b db 11 120 1689+11 db 17 121 168a+17 db 23 122 168b+03 db 3 123 168c+09 db 9 124 168d+0f db 15 125 168e+15 db 21 126 168f+02 db 2 127 1690+08 db 8 128 1691+0e db 14 129 1692+14 db 20 130 1693+1a db 26 131 1694+06 db 6 132 1695+0c db 12 133 1696+12 db 18 134 1697+18 db 24 135 1698+04 db 4 136 1699+0a db 10 137 169a+10 db 16 138 169b+16 db 22 139 diskdef 1,0 140 1673+ = dpb1 equ dpb0 ;equivalent parameters 141 001f+ = als1 equ als0 ;same allocation vector size 142 0010+ = css1 equ css0 ;same checksum vector size 143 1682+ = xlt1 equ xlt0 ;same translate table 144 diskdef 2, 0 145 1673+ = dpb2 equ dpb0 ;equivalent parameters 146 001f+ = als2 equ als0 ;same allocation vector size 147 0010+ = css2 equ css0 ;same checksum vector size 148 1682+ = xlt2 equ xlt0 ;same translate table 149 diskdef 3, 0 150 1673+ = dpb3 equ dpb0 ;equivalent parameters 151 001f+ = als3 equ als0 ;same allocation vector size 152 0010+ = css3 equ css0 ;same checksum vector size 153 1682+ = xlt3 equ xlt0 ;same translate table 154 ; endef occurs at end of assembly A-4 155 ; 156 ; end of controller--independent code, the remaining subroutines 157 ; are tailored to the particular operating environment, and must 158 ; be altered for any system which differs from the intel mds. 159 ; 160 ; the following code assumes the mds monitor exists at 0f800h 161 ; and uses the i/o subroutines within the monitor 162 ; 163 ; we also assume the mds system has four disk drives 164 00fd = revrt equ 0fdh ;interrupt revert port 165 00fc = intc equ 0fch ;interrupt mask port 166 00f3 = icon equ 0f3h ;interrupt control port 167 007E = inte equ 0111$1110b ;enable rst 0 (warm boot), rst 7 (monitor) 168 ; 169 ; mds monitor equates 170 f800 = mon80 equ 0f800h ;mds monitor 171 ff0f = rmon80 equ 0ff0fh ;restart mon80 (boot error) 172 f803 = ci equ 0f803h ;console character to reg-a 173 f806 = ri equ 0f806h ;reader in to reg-a 174 f809 = co equ 0f809h ;console char from c to console out 175 f80c = po equ 0f80ch ;punch char from c to punch device 176 f80f = lo equ 0f80fh ;list from c to list device 177 f812 = csts equ 0f812h ;console status 00/ff to register a 178 ; 179 ; disk ports and commands 180 0078 = base equ 78h ;base of disk command io ports 181 0078 = dstat equ base ;disk status (input) 182 0079 = rtype equ base+1 ;result type (input) 183 007b = rbyte equ base+3 ;result byte (input) 184 ; 185 0079 = ilow equ base+1 ;iopb low address (output) 186 007a = ihigh equ base+2 ;iopb high address (output) 187 ; 188 0004 = readf equ 4h ;read function 189 0006 = writf equ 6h ;write function 190 0003 = recal equ 3h ;recalibrate drive 191 0004 = iordy equ 4h ;i/o finished mask 192 000d = cr equ 0dh ;carriage return 193 000a = lf equ 0ah ;line-feed 194 ; A-5 195 signon: ;signon message: xxk cp/m vers y.y 196 169c 0d0a0a db cr, lf, lf 197 if test 198 db '32' ;32k example bios 199 endif 200 if not test 201 169f 3030 db '00' ;memory size filled by relocator 202 endif 203 16a1 6b2043502f db 'k cp/m vers ' 204 16ad 322e32 db ver/10+'0', ',' vers mod 10+'0' 205 16b0 0d0a00 db cr, lf, 0 206 ; 207 boot: ;print signon message and go to ccp 208 ; (note: mds boot initialized iobyte at 0003h) 209 16b3 310001 lxi sp, buff+80h 210 16b6 219c16 lxi h, signon 211 16b9 cdd317 call prmsg ;print message 212 16bc af xra a ;clear accumulator 213 16bd 320400 sta cdisk ;set initially to disk a 214 16c0 c30f17 jmp gocpm ;go to cp/m 215 ; 216 ; 217 wboot:; loader on track 0, sector 1, which will be skipped for warm 218 ; read cp/m from disk--assuming there is a 128 byte cold start 219 ; start 220 ; 221 16c3 318000 lxi sp, buff ;using dma--thus 80 thru ff available for stack 222 ; 223 16c6 0e0a mvi c, retry ;max retries 224 16c8 c5 push b 225 wboot0: ;enter here on error retries 226 16c9 010000 lxi b, cpmb ;set dma address to start of disk system 227 16cc cdbb17 call setdma 228 16cf 0e00 mvi c, 0 ;boot from drive 0 229 16d1 cd7d17 call seldsk 230 16d4 0e00 mvi c, 0 231 16d6 cda717 call settrk ;start with track 0 232 16d9 0e02 mvi c, 2 ;start reading sector 2 233 16db cdac17 call setsec 234 ; A-6 235 ; read sectors, count nsects to zero 236 16de c1 pop b ;10-error count 237 16df 062c mvi b, nsects 238 rdsec: ;read next sector 239 16e1 c5 push b ;save sector count 240 16e2 cdc117 call read 241 16e5 c24917 jnz booterr ;retry if errors occur 242 16e8 2a6c18 lhld iod ;increment dma address 243 16eb 118000 lxi d, 128 ;sector size 244 16ee 19 dad d ;incremented dma address in hl 245 16ef 44 mov b, h 246 16f0 4d mov c, l ;ready for call to set dma 247 16f1 cdbb17 call setdma 248 16f4 3a6b18 lda ios ;sector number just read 249 16f7 fe1a cpi 26 ;read last sector? 250 16f9 da0517 jc rd1 251 ; must be sector 26, zero and go to next track 252 16fc 3a6a18 lda iot ;get track to register a 253 16ff 3c inr a 254 1700 4f mov c, a ;read for call 255 1701 cda717 call settrk 256 1704 af xra a ;clear sector number 257 1705 3c rd1: inr a ;to next sector 258 1706 4f mov c, a ;ready for call 259 1707 cdac17 call setsec 260 170a c1 pop b ;recall sector count 261 170b 05 dcr b ;done? 262 170c c2e116 jnz rdsec 263 ; 264 ; done with the load, reset default buffer address 265 gocpm: ;(enter here from cold start boot) 266 ; enable rst0 and rst7 267 170f f3 di 268 1710 3e12 mvi a, 12h ;initialize command 269 1712 d3fd out revrt 270 1714 af xra a 271 1715 d3fc out intc ;cleared 272 1717 3e7e mvi a, inte ;rst0 and rst7 bits on 273 1719 d3fc out intc 274 171b af xra a A-7 275 171c d3f3 out icon ;interrupt control 276 ; 277 ; set default buffer address to 80h 278 171e 018000 lxi b, buff 279 1721 cdbb17 call setdma 280 ; 281 ; reset monitor entry points 282 1724 3ec3 mvi a, jmp 283 1726 320000 sta 0 284 1729 210316 lxi h, wboote 285 172c 220100 shld 1 ;jump wboot at location 00 286 172f 320500 sta 5 287 1732 210608 lxi h, bdos 288 1735 220600 shld 6 ;jmp bdos at location 5 289 if not test 290 1738 323800 sta 7*8 ;jmp to mon80 (may have changed by ddt) 291 173b 2100f8 lxi h, mon80 292 173e 223900 shld 7*8+1 293 endif 294 ; leave iobyte set 295 ; previously selected disk was b, send parameter to cpm 296 1741 3a0400 lda cdisk ;last logged disk number 297 1744 4f mov c, a ;send to ccp to log it in 298 1745 fb ei 299 1746 c30000 jmp cpmb 300 ; 301 ; error condition occurred, print message and retry 302 booterr: 303 1749 c1 pop b ;recall counts 304 174a 0d dcr c 305 174b ca5217 jz booter0 306 ; try again 307 174e c5 push b 308 174f c3c916 jmp wboot0 309 ; 310 booter0: 311 ; otherwise too many retries 312 1752 215b17 lxi h, bootmsg 313 1755 cdd317 call prmsg 314 1758 c30fff jmp rmon80 ;mds hardware monitor A-8 315 ; 316 bootmsg: 317 175b 3f626f6f74 db '?boot', 0 318 ; 319 ; 320 const: console status to reg-a 321 ; (exactly the same as mds call) 322 1761 c312f8 jmp csts 323 ; 324 conin: ;console character to reg-a 325 1764 cd03f8 call ci 326 1767 e67f ani 7fh ;remove parity bit 327 1769 c9 ret 328 ; 329 conout: ;console character from c to console out 330 176a c309f8 jmp co 331 ; 332 list: ;list device out 333 ; (exactly the same as mds call) 334 176d c30ff8 jmp lo 335 ; 336 listst: 337 ;return list status 338 1770 af xra a 339 1771 c9 ret ;always not ready 340 ; 341 punch: ;punch device out 342 ; (exactly the same as mds call) 343 1772 c30cf8 jmp po 344 ; 345 reader: ;reader character in to reg-a 346 ; (exactly the same as mds call) 347 1775 c306f8 jmp ri 348 ; 349 home: ;move to home position 350 ; treat as track 00 seek 351 1778 0e00 mvi c, 0 352 177a c3a717 jmp settrk 353 ; 354 seldsk: ;select disk given by register c A-9 355 177d 210000 lxi h, 0000h ;return 0000 if error 356 1780 79 mov a, c 357 1781 fe04 cpi ndisks ;too large? 358 1783 d0 rnc ;leave hl = 0000 359 ; 360 1784 e602 ani 10b ;00 00 for drive 0, 1 and 10 10 for drive 2, 3 361 1786 326618 sta dbank ;to select drive bank 362 1789 79 mov a, c ;00, 01, 10, 11 363 178a e601 ani 1b ;mds has 0, 1 at 78, 2, 3 at 88 364 178c b7 ora a ;result 00? 365 178d ca9217 jz setdrive 366 1790 3e30 mvi a, 00110000b ;selects drive 1 in bank 367 setdrive: 368 1792 47 mov b, a ;save the function 369 1793 216818 lxi h, iof ;io function 370 1796 7e mov a, m 371 1797 e6cf ani 11001111b ;mask out disk number 372 1799 b0 ora b ;mask in new disk number 373 179a 77 mov m, a ;save it in iopb 374 179b 69 mov l, c 375 179c 2600 mvi h, 0 ;hl=disk number 376 179e 29 dad h ;*2 377 179f 29 dad h ;*4 378 17a0 29 dad h ;*8 379 17a1 29 dad h ;*16 380 17a2 113316 lxi d, dpbase 381 17a5 19 dad d ;hl=disk header table address 382 17a6 c9 ret 383 ; 384 ; 385 settrk: ;set track address given by c 386 17a7 216a18 lxi h, iot 387 17aa 71 mov m, c 388 17ab c9 ret 389 ; 390 setsec: ;set sector number given by c 391 17ac 216b18 lxi h, ios 392 17af 71 mov m, c 393 17b0 c9 ret 394 sectran: A-10 395 ;translate sector bc using table at de 396 17b1 0600 mvi b, 0 ;double-precision sector number in bc 397 17b3 eb xchg ;translate table address to hl 398 17b4 09 dad b ;translate (sector) address 399 17b5 7e mov a, m ;translated sector number to a 400 17b6 326b18 sta ios 401 17b9 6f mov l, a ;return sector number in l 402 17ba c9 ret 403 ; 404 setdma: ;set dma address given by regs b, c 405 17bb 69 mov l, c 406 17bc 60 mov h, b 407 17bd 226c18 shld iod 408 17c0 c9 ret 409 ; 410 read: ;read next disk record (assuming disk/trk/sec/dma set) 411 17c1 0e04 mvi c, readf ;set to read function 412 17c3 cde017 call setfunc 413 17c6 cdf017 call waitio ;perform read function 414 17c9 c9 ret ;may have error set in reg-a 415 ; 416 ; 417 write: ;disk write function 418 17ca 0e06 mvi c, writf 419 17cc cde017 call setfunc ;set to write function 420 17cf cdf017 call waitio 421 17d2 c9 ret ;may have error set 422 ; 423 ; 424 ; utility subroutines 425 prmsg: ;print message at h, l to 0 426 17d3 7e mov a, m 427 17d4 b7 ora a zero? 428 17d5 c8 rz 429 ; more to print 430 17d6 e5 push h 431 17d7 4f mov c,a 432 17d8 cd6a17 call conout 433 17db e1 pop h 434 17dc 23 inx h A-11 435 17dd c3d317 jmp prmsg 436 ; 437 setfunc: 438 ; set function for next i/o (command in reg-c) 439 17e0 216818 lxi h, iof ;io function address 440 17e3 7e mov a, m ;get it to accumulator for masking 441 17e4 e6f8 ani 11111000b ;remove previous command 442 17e6 b1 ora c ;set to new command 443 17e7 77 mov m, a ;replaced in iopb 444 ; the mds-800 controller requires disk bank bit in sector byte 445 ; mask the bit from the current i/o function 446 17e8 e620 ani 00100000b ;mask the disk select bit 447 17ea 216b18 lxi h, ios ;address the sector select byte 448 17ed b6 ora m ;select proper disk bank 449 17ee 77 mov m, a ;set disk select bit on/off 450 17ef c9 ret 451 ; 452 waitio: 453 17f0 0e0a mvi c, retry ;max retries before perm error 454 rewait: 455 ; start the i/o function and wait for completion 456 17f2 cd3f18 call intype ;in rtype 457 17f5 cd4c18 call inbyte ;clears the controller 458 ; 459 17f8 3a6618 lda dbank ;set bank flags 460 17fb b7 ora a ;zero if drive 0, 1 and nz if 2, 3 461 17fc 3e67 mvi a, iopb and offh ;low address for iopb 462 17fe 0618 mvi b, iopb shr 8 ;high address for iopb 463 1800 c20b18 jnz iodr1 ;drive bank 1? 464 1803 d379 out ilow ;low address to controller 465 1805 78 mov a, b 466 1806 d37a out ihigh ;high address 467 1808 c31018 jmp waito ;to wait for complete 468 ; 469 iodr1: ;drive bank 1 470 180b d389 out ilow+10h ;88 for drive bank 10 471 180d 78 mov a, b 472 180e d38a out ihigh+10h 473 ; 474 1810 cd5918 waito: call instat ;wait for completion A-12 475 1813 e604 ani iordy ;ready? 476 1815 ca1018 jz waito 477 ; 478 ; check io completion ok 479 1818 cd3f18 call intype ;must be io complete (00) unlinked 480 ; 00 unlinked i/o complete, 01 linked i/o complete (not used) 481 ; io disk status changed 11 (not used) 482 181b fe02 cpi 10b ;ready status change? 483 181d ca3218 jz wready 484 ; 485 ; must be 00 in the accumulator 486 1820 b7 ora a 487 1821 c23818 jnz werror ;some other condition, retry 488 ; 489 ; check i/o error bits 490 1824 cd4c18 call inbyte 491 1827 17 ral 492 1828 da3218 jc wready ;unit not ready 493 182b 1f rar 494 182c e6fe ani 11111110b ;any other errors? (deleted data ok) 495 182e c23818 jnz werror 496 ; 497 ; read or write is ok, accumulator contains zero 498 1831 c9 ret 499 ; 500 wready: ;not ready, treat as error for now 501 1832 cd4c18 call inbyte ;clear result byte 502 1835 c33818 jmp trycount 503 ; 504 werror: ;return hardware malfunction (crc, track, seek, etc.) 505 ; the mds controller has returned a bit in each position 506 ; of the accumulator, corresponding to the conditions: 507 ; 0 -deleted data (accepted as ok above) 508 ; 1 -crc error 509 ; 2 -seek error 510 ; 3 -address error (hardware malfunction) 511 ; 4 -data over/under flow (hardware malfunction) 512 ; 5 -write protect (treated as not ready) 513 ; 6 -write error (hardware malfunction) 514 ; j -not ready A-13 515 ; (accumulator bits are numbered 7 6 5 4 3 2 1 0) 516 ; 517 ; it may be useful to filter out the various conditions, 518 ; but we will get a permanent error message if it is not 519 ; recoverable. in any case, the not ready condition is 520 ; treated as a separated condition for later improvement 521 trycount: 522 ; register c contains retry count, decrement 'til zero 523 1838 0d dcr c 524 1839 c2f217 jnz rewait ;for another try 525 ; 526 ; cannot recover from error 527 183c 3e01 mvi a, 1 ;error code 528 183e c9 ret 529 ; 530 ; intype, inbyte, instat read drive bank 00 or 10 531 183f 3a6618 intype: lda dbank 532 1842 b7 ora a 533 1843 c24918 jnz intyp1 ;skip to bank 10 534 1846 db79 in rtype 535 1848 c9 ret 536 1849 db89 intyp1: in rtype+10h ;78 for 0, 1 88 for 2, 3 537 184b c9 ret 538 ; 539 184c 3a6618 inbyte: lda dbank 540 184f b7 ora a 541 1850 c25618 jnz inbyt1 542 1853 db7b in rbyte 543 1855 c9 ret 544 1856 db8b inbyt1: in rbyte+10h 545 1858 c9 ret 546 ; 547 1859 3a6618 instat: lda dbank 548 185c b7 ora a 549 185d c26318 jnz insta1 550 1860 db78 in dstat 551 1862 c9 ret 552 1863 db88 insta1: in dstat+10h 553 1865 c9 ret 554 ; A-14 555 ; 556 ; 557 ; data areas (must be in ram) 558 1866 00 dbank: db 0 ;disk bank 00 if drive 0, 1 559 ; 10 if drive 2, 3 560 iopb: ;io parameter block 561 1867 80 db 80h ;normal i/o operation 562 1868 04 iof: db readf ;io function, initial read 563 1869 01 ion: db 1 ;number of sectors to read 564 186a 02 iot: db offset ;track number 565 186b 01 ios: db 1 ;sector number 566 186c 8000 iod: dw buff ;io address 567 ; 568 ; 569 ; define ram areas for bdos operation 570 endef 571 186e+= begdat equ $ 572 186e+ dirbuf: ds 128 ;directory access buffer 573 18ee+ alv0: ds 31 574 190d+ csv0: ds 16 575 191d+ alv1: ds 31 576 193c+ csv1: ds 16 577 194c+ alv2: ds 31 578 196b+ csv2: ds 16 579 197b+ alv3: ds 31 580 199a+ csv3: ds 16 581 19aa+= enddat equ $ 582 013c+= datsiz equ $-begdat 583 19aa end als1 001f 141# als2 001f 146# als3 001f 151# alv0 18ee 87 573# alv1 191d 91 575# alv2 194c 95 577# alv3 197b 99 579# base 0078 180# 181 182 183 185 186 bdos 0806 29# 287 A-15 begdat 186e 571# 582 bias 0000 19# 22# boot 16b3 63 207# booter0 1752 305 310# booterr 1749 241 302# bootmsg 175b 312 316# buff 0080 34# 209 221 278 566 cdisk 0004 33# 213 296 ci f803 172# 325 co f809 174# 330 conin 1764 66 324# conout 176a 67 329# 432 const 1761 65 320# cpmb 0000 28# 29 30 226 299 cpml 1600 30# 31 cr 000d 192# 196 205 css1 0010 142# css2 0010 147# css3 0010 152# csts f812 177# 322 csv0 190d 87 574# csv1 193c 91 576# csv2 196b 95 578# csv3 199a 99 580# datsiz 013c 582# dbank 1866 361 459 531 539 539 547 558# dirbuf 186e 86 90 94 98 572# dpb0 1673 86 101# 140 145 150 dpb1 1673 90 140# dpb2 1673 94 145# dpb3 1673 98 150# dpbase 1633 83# 380 dpe0 1633 84# dpe1 1643 88# dpe2 1653 92# dpe3 1663 96# dstat 0078 181# 550 552 enddat 19aa 581# false 0000 15# 16 gocpm 170f 214 265# A-16 home 1778 71 349# icon 00fe 166# 275 ihigh 007a 186# 466 472 ilow 0079 185# 464 470 inbyt1 1856 541 544# inbyte 184c 457 490 501 539# insta1 1863 549 552# instat 1859 474 547# intc 00fc 165# 271 273 inte 007e 167# 272 intyp1 1849 533 536# intype 183f 456 479 531# iod 186c 242 407 566# iodr1 180b 463 469# iof 1868 369 439 562# ion 1869 563# iopb 1867 461 462 560# iordy 0004 191# 475 ios 186b 248 391 400 447 565# iot 186a 252 386 564# lf 000a 193# 196 196 205 list 176d 68 332# listst 1770 78 336# lo f80f 176# 334 mon80 f800 170# 291 nsects 002c 31# 237 offset 0002 32# 100 564 patch 1600 25# 27 28 po f80c 175# 343 prmsg 17d3 211 313 425# 435 punch 1772 69 341# rbyte 007b 183# 542 544 rd1 1705 250 257# rdsec 16e1 238# 262 read 17c1 76 240 410# reader 1775 70 345# readf 0004 188# 411 562 recal 0003 190# retry 000a 35# 223 453 revrt 00fd 164# 269 A-17 rewait 17f2 454# 524 ri f806 173# 347 rmon80 ff0f 171# 314 rtype 0079 182# 534 536 sectran 17b1 79 394# seldsk 177d 72 229 354# setdma 17bb 75 227 247 279 404# setdrive 1792 365 367# setfunc 17e0 412 419 437# setsec 17ac 74 233 259 390# settrk 17a7 73 231 255 352 385# signon 169c 195# 210 test 0000 16# 18 21 197 200 289 true ffff 14# 15 trycount 1838 502 521# vers 0016 6# 204 204 waito 1810 467 474# 476 waitio 17f0 413 420 452# wboot 16c3 64 217# wboot0 16c9 225# 308 wboote 1603 64# 284 werror 1838 487 495 504# wready 1832 483 492 500# write 17ca 77 417# writf 0006 189# 418 xlt0 1682 84 112# 143 148 153 xlt1 1682 88 143# xlt2 1682 92 148# xlt3 1682 96 153# A-18 Appendix B A Skeletal CBIOS 1 ; skeletal cbios for first level of cp/m 2.0 alteration 2 ; 3 0014 = msize equ 20 ;cp/m version memory size in kilobytes 4 ; 5 ; "bias" is address offset from 3400h for memory systems 6 ; than 16k (referred to as "b" throughout the text) 7 ; 8 0000 = bias equ (msize-20)*1024 9 3400 = ccp equ 3400h+bias ;base of ccp 10 3c06 = bdos equ ccp+806h ;base of bdos 11 4a00 = bios equ ccp+1600h ;base of bios 12 0004 = cdisk equ 0004h ;current disk number 0=a,..., 15=p 13 0003 = iobyte equ 0003h ;intel i/o byte 14 ; 15 4a00 org bios ;origin of this program 16 002c = nsects equ ($-ccp)/128 ;warm start sector count 17 ; 18 ; jump vector for individual subroutines 19 4a00 c39c4a jmp boot ;cold start 20 4a03 c3a64a wboote: jmp wboot ;warm start 21 4a06 c3114b jmp const ;console status 22 4a09 c3244b jmp conin ;console character in 23 4a0c c3374b jmp conout ;console character out 24 4a0f c3494b jmp list ;list character out 25 4a12 c34d4b jmp punch ;punch character out 26 4a15 c34f4b jmp reader ;reader character out 27 4a18 c3544b jmp home ;move head to home position 28 4a1b c35a4b jmp seldsk ;select disk 29 4a1e c37d4b jmp settrk ;set track number 30 4a21 c3924b jmp setsec ;set sector number 31 4a24 c3ad4b jmp setdma ;set dma address 32 4a27 c3c34b jmp read ;read disk 33 4a2a c3d64b jmp write ;write disk B-1 34 4a2d c34b4b jmp listst ;return list status 35 4a30 c3a74b jmp sectran ;sector translate 36 ; 37 ; fixed data tables for four-drive standard 38 ; ibm-compatible 8" disks 39 ; disk parameter header for disk 00 40 4a33 734a0000 dpbase: dw trans, 0000h 41 4a37 00000000 dw 0000h, 0000h 42 4a3b f04c8d4a dw dirbf, dpblk 43 4a3f ec4d704d dw chk00, all00 44 ; disk parameter header for disk 01 45 4a43 734a0000 dw trans, 0000h 46 4a47 00000000 dw 0000h, 0000h 47 4a4b f04c8d4a dw dirbf, dpblk 48 4a4f fc4d8f4d dw chk01, all01 49 ; disk parameter header for disk 02 50 4a53 734a0000 dw trans, 0000h 51 4a57 00000000 dw 0000h, 0000h 52 4a5b f04c8d4a dw dirbf, dpblk 53 4a5f 0c4eae4d dw chk02, all02 54 ; disk parameter header for disk 03 55 4a63 734a0000 dw trans, 0000h 56 4a67 00000000 dw 0000h, 0000h 57 4a6b f04c8d4a dw dirbf, dpblk 58 4a6f 1c4ecd4d dw chk03, all03 59 ; 60 ; sector translate vector 61 4a73 01070d13 trans: db 1, 7, 13, 19 ;sectors 1, 2, 3, 4 62 4a77 19050b11 db 25, 5, 11, 17 ;sectors 5, 6, 7, 8 63 4a7b 1703090f db 23, 3, 9, 15 ;sectors 9, 10, 11, 12 64 4a7f 1502080e db 21, 2, 8, 14 ;sectors 13, 14, 15, 16 65 4a83 141a060c db 20, 26, 6, 12 ;sectors 17, 18, 19, 20 66 4a87 1218040a db 18, 24, 4, 10 ;sectors 21, 22, 23, 24 67 4a8b 1016 db 16, 22 ;sectors 25, 26 68 ; 69 dpblk: ;disk parameter block, common to all disks 70 4a8d 1a00 dw 26 ;sectors per track 71 4a8f 03 db 3 ;block shift factor 72 4a90 07 db 7 ;block mask 73 4a91 00 db 0 ;null mask B-2 74 4a92 f200 dw 242 ;disk size-1 75 4a94 3f00 dw 63 ;directory max 76 4a96 c0 db 192 ;alloc 0 77 4a97 00 db 0 ;alloc 1 78 4a98 1000 dw 16 ;check size 79 4a9a 0200 dw 2 ;track offset 80 ; 81 ; end of fixed tables 82 ; 83 ; individual subroutines to perform each function 84 boot: ;simplest case is to just perform parameter initialization 85 4a9c af xra a ;zero in the accum 86 4a9d 320300 sta iobyte ;clear the iobyte 87 4aa0 320400 sta cdisk ;select disk zero 88 4aa3 c3ef4a jmp gocpm ;initialize and go to cp/m 89 ; 90 wboot: ;simplest case is to read the disk until all sectors loaded 91 4aa6 318000 lxi sp, 80h ;use space below buffer for stack 92 4aa9 0e00 mvi c, 0 ;select disk 0 93 4aab cd5a4b call seldsk 94 4aae cd544b call home ;go to track 00 95 ; 96 4ab1 062c mvi b, nsects ;b counts # of sectors to load 97 4ab3 0e00 mvi c, 0 ;c has the current track number 98 4ab5 1602 mvi d, 2 ;d has the next sector to read 99 ; note that we begin by reading track 0, sector 2 since sector 1 100 ; contains the cold start loader, which is skipped in a warm start 101 4ab7 210034 lxi h, ccp ;base of cp/m (initial load point) 102 load1: ;load one more sector 103 4aba c5 push b ;save sector count, current track 104 4abb d5 push d ;save next sector to read 105 4abc e5 push h ;save dma address 106 4abd 4a mov c, d ;get sector address to register c 107 4abe cd924b call setsec ;set sector address from register c 108 4ac1 c1 pop b ;recall dma address to b, c 109 4ac2 c5 push b ;replace on stack for later recall 110 4ac3 cdad4b call setdma ;set dma address from b, c 111 ; 112 ; drive set to 0, track set, sector set, dma address set 113 4ac6 cdc34b call read B-3 114 4ac9 fe00 cpi 00h ;any errors? 115 4acb c2a64a jnz wboot ;retry the entire boot if an error occurs 116 ; 117 ; no error, move to next sector 118 4ace e1 pop h ;recall dma address 119 4acf 118000 lxi d, 128 ;dma=dma+128 120 4ad2 19 dad d ;new dma address is in h, l 121 4ad3 d1 pop d ;recall sector address 122 4ad4 c1 pop b ;recall number of sectors remaining, and current trk 123 4ad5 05 dcr b ;sectors=sectors-1 124 4ad6 caef4a jz gocpm ;transfer to cp/m if all have been loaded 125 ; 126 ; more sectors remain to load, check for track change 127 4ad9 14 inr d 128 4ada 7a mov a,d ;sector=27?, if so, change tracks 129 4adb fe1b cpi 27 130 4add daba4a jc load1 ;carry generated if sector<27 131 ; 132 ; end of current track, go to next track 133 4ae0 1601 mvi d, 1 ;begin with first sector of next track 134 4ae2 0c inr c ;track=track+1 135 ; 136 ; save register state, and change tracks 137 4ae3 c5 push b 138 4ae4 d5 push d 139 4ae5 e5 push h 140 4ae6 cd7d4b call settrk ;track address set from register c 141 4ae9 e1 pop h 142 4aea d1 pop d 143 4aeb c1 pop b 144 4aec c3ba4a jmp load1 ;for another sector 145 ; 146 ; end of load operation, set parameters and go to cp/m 147 gocpm: 148 4aef 3ec3 mvi a, 0c3h ;c3 is a jmp instruction 149 4af1 320000 sta 0 ;for jmp to wboot 150 4af4 21034a lxi h, wboote ;wboot entry point 151 4af7 220100 shld 1 ;set address field for jmp at 0 152 ; 153 4afa 320500 sta 5 ;for jmp to bdos B-4 154 4afd 21063c lxi h, bdos ;bdos entry point 155 4b00 220600 shld 6 ;address field of jump at 5 to bdos 156 ; 157 4b03 018000 lxi b, 80h ;default dma address is 80h 158 4b06 cdad4b call setdma 159 ; 160 4b09 fb ei ;enable the interrupt system 161 4b0a 3a0400 lda cdisk ;get current disk number 162 4b0d 4f mov c, a ;send to the ccp 163 4b0e c30034 jmp ccp ;go to cp/m for further processing 164 ; 165 ; 166 ; simple i/o handlers (must be filled in by user) 167 ; in each case, the entry point is provided, with space reserved 168 ; to insert your own code 169 ; 170 const: ;console status, return 0ffh if character ready, 00h if not 171 4b11 ds 10h ;space for status subroutine 172 4b21 3e00 mvi a, 00h 173 4b23 c9 ret 174 ; 175 conin: ;console character into register a 176 4b24 ds 10h ;space for input routine 177 4b34 e67f ani 7fh ;strip parity bit 178 4b36 c9 ret 179 ; 180 conout: ;console character output from register c 181 4b37 79 mov a, c ;get to accumulator 182 4b38 ds 10h ;space for output routine 183 4b48 c9 ret 184 ; 185 list: ;list character from register c 186 4b49 79 mov a, c ;character to register a 187 4b4a c9 ret ;null subroutine 188 ; 189 listst: ;return list status (0 if not ready, 1 if ready) 190 4b4b af xra a ;0 is always ok to return 191 4b4c c9 ret 192 ; 193 punch: ;punch character from register c B-5 194 4b4d 79 mov a, c ;character to register a 195 4b4e c9 ret ;null subroutine 196 ; 197 ; 198 reader: ;reader character into register a from reader device 199 4b4f 3e1a mvi a, 1ah ;enter end of file for now (replace later) 200 4b51 e67f ani 7fh ;remember to strip parity bit 201 4b53 c9 ret 202 ; 203 ; 204 ; i/o drivers for the disk follow 205 ; for now, we will simply store the parameters away for use 206 ; in the read and write subroutines 207 ; 208 home: ;move to the track 00 position of current drive 209 ; translate this call into a settrk call with parameter 00 210 4b54 0e00 mvi c, 0 ;select track 0 211 4b56 cd7d4b call settrk 212 4b59 c9 ret ;we will move to 00 on first read/write 213 ; 214 seldsk: ;select disk given by register c 215 4b51 210000 lxi h, 0000h ;error return code 216 4b5d 79 mov a, c 217 4b5e 32ef4c sta diskno 218 4b61 fe04 cpi 4 ;must be between 0 and 3 219 4b63 d0 rnc ;no carry if 4, 5,... 220 ; disk number is in the proper range 221 4b64 ds 10 ;space for disk select 222 ; compute proper disk parameter header address 223 4b6e 3aef4c lda diskno 224 4b71 6f mov l, a ;l=disk number 0, 1, 2, 3 225 4b72 2600 mvi h, 0 ;high order zero 226 4b74 29 dad h ;*2 227 4b75 29 dad h ;*4 228 4b76 29 dad h ;*8 229 4b77 29 dad h ;*16 (size of each header) 230 4b78 11334a lxi d, dpbase 231 4b7b 19 dad 0 ;hl=.dpbase (diskno*16) 232 4b7c c9 ret 233 ; B-6 234 settrk: ;set track given by register c 235 4b7d 79 mov a, c 236 4b7e 32e94c sta track 237 4b81 ds 10h ;space for track select 238 4b91 c9 ret 239 ; 240 setsec: ;set sector given by register c 241 4b92 79 mov a, c 242 4b93 32eb4c sta sector 243 4b96 ds 10h ;space for sector select 244 4ba6 c9 ret 245 ; 246 sectran: 247 ;translate the sector given by bc using the 248 ;translate table given by de 249 4ba7 eb xchg ;hl=.trans 250 4ba8 09 dad b ;hl=.trans (sector) 251 4ba9 6e mov l, m ;l=trans (sector) 252 4baa 2600 mvi h, 0 ;hl=trans (sector) 253 4bac c9 ret ;with value in hl 254 ; 255 setdma: ;set dma address given by registers b and c 256 4bad 69 mov l, c ;low order address 257 4bae 60 mov h, b ;high order address 258 4baf 22ed4c shld dmaad ;save the address 259 4bb2 ds 10h ;space for setting the dma address 260 4bc2 c9 ret 261 ; 262 read: ;perform read operation (usually this is similar to write 263 ; so we will allow space to set up read command, then use 264 ; common code in write) 265 4bc3 ds 10h ;set up read command 266 4bd3 c3e64b jmp waitio ;to perform the actual i/o 267 ; 268 write: ;perform a write operation 269 4bd6 ds 10h ;set up write command 270 ; 271 waitio: ;enter here from read and write to perform the actual i/o 272 ; operation. return a 00h in register a if the operation completes 273 ; properly, and 01h if an error occurs during the read or write B-7 274 ; 275 ; in this case, we have saved the disk number in 'diskno' (0, 1) 276 ; the track number in 'track' (0-76) 277 ; the sector number in 'sector' (1-26) 278 ; the dma address in 'dmaad' (0-65535) 279 4be6 ds 256 ;space reserved for i/o drivers 280 4ce6 3e01 mvi a, 1 ;error condition 281 4ce8 c9 ret ;replaced when filled-in 282 ; 283 ; the remainder of the cbios is reserved uninitialized 284 ; data area, and does not need to be a part of the 285 ; system memory image (the space must be available, 286 ; however, between "begdat" and "enddat"). 287 ; 288 4ce9 track: ds 2 ;two bytes for expansion 289 4ceb sector: ds 2 ;two bytes for expansion 290 4ced dmaad: ds 2 ;direct memory address 291 4cef diskno: ds 1 ;disk number 0-15 292 ; 293 ; scratch ram area for bdos use 294 4cf0= begdat equ $ ;beginning of data area 295 4cf0 dirfb: ds 128 ;scratch directory area 296 4d70 all00: ds 31 ;allocation vector 0 297 4d8f all01: ds 31 ;allocation vector 1 298 4dae all02: ds 31 ;allocation vector 2 299 4dcd all03: ds 31 ;allocation vector 3 300 4dec chk00: ds 16 ;check vector 0 301 4dfc chk01: ds 16 ;check vector 1 302 4e0c chk02: ds 16 ;check vector 2 303 4e1c chk03: ds 16 ;check vector 3 304 ; 305 4e2c enddat equ $ ;end of data area 306 013c= datsiz equ $-begdat; ;size of data area 307 4e2c end all00 4d70 43 296# all01 4d8f 48 297# all02 4dae 53 298# all03 4dcd 58 299# bdos 3c06 10# 154 B-8 begdat 4cf0 294# 306 bias 0000 8# 9 bios 4a00 11# 15 boot 4a9c 19 84# ccp 3400 9# 10 11 16 101 163 cdisk 0004 12# 87 161 chk00 4dec 43 300# chk01 4dfc 48 301# chk02 4e0c 53 302# chk03 4e1c 58 303# conin 4b24 22 175# conout 4b37 23 180# const 4b11 21 170# datsiz 013c 306# dirbf 4cf0 42 47 52 57 295# diskno 4cef 217 223 291# dmaad 4ced 258 290# dpbase 4a33 40# 230 dpblk 4a8d 42 47 52 57 69# enddat 4e2c 305# gocpm 4aef 88 124 147# home 4b54 27 94 208# iobyte 0003 13# 86 list 4b49 24 185# listst 4b4b 34 189# load1 4aba 102# 130 144 msize 0014 3# 8 nsects 002c 16# 96 punch 4b4d 25 193# read 4bc3 32 113 262# reader 4b4f 26 198# sector 4ceb 242 289# sectran 4ba7 35 246# seldsk 4b5a 28 93 214# setdma 4bad 31 110 158 255# setsec 4b92 30 107 240# settrk 4b7d 29 140 211 234# track 4ce9 236 288# trans 4a73 40 45 50 55 61# waitio 4be6 266 271# B-9 wboot 4aa6 20 90# 115 wboote 4a03 20# 150 write 4bd6 33 268# B-10 Appendix C A Skeletal GETSYS/PUTSYS Program ; combined getsys and putsys programs from ; Sec 6.4 ; Start the programs at the base of the TPA 0100 org 0100h 0014 = msize equ 20 ;size of cp/m in Kbytes ;"bias" is the amount to add to addresses for > 20k ; (referred to as "b" throughout the text) 0000 = bias equ (msize-20)*1024 3400 = ccp equ 3400h+bias 3c00 = bdos equ ccp+0800h 4a00 = bios equ ccp+1600h ; getsys programs tracks 0 and 1 to memory at ; 3880h + bias ; register usage ; a (scratch register) ; b track count (0...76) ; c sector count (1...26) ; d,e (scratch register pair) ; h,l load address ; sp set to track address gstart: ;start of getsys 0100 318033 lxi sp,ccp-0080h ;convenient place 0103 218033 lxi h,ccp-0080h ;set initial load 0106 0600 mvi b 0 ;start with track rd$trk: ;read next track 0108 0e01 mvi c,1 ;each track start rd$sec: C-1 010a cd0003 call read$sec ;get the next sector 010d 118000 lxi d,128 ;offset by one sector 0110 19 dad d ; (hl=hl+128) 0111 0c inr c ;next sector 0112 79 mov a,c ;fetch sector number 0113 felb cpi 27 ;and see if last 0115 da0a01 jc rdsec ;<, do one more ;arrive here at end of track, move to next track 0118 04 inr b ;track = track+1 0119 78 mov a,b ;check for last 011a fe02 cpi 2 ;track = 2 ? 011c da0801 jc rd$trk ;<, do another ;arrive here at end of load, halt for lack of anything ;better 011f fb ei 0120 76 hlt ; putsys program, places memory image ; starting at ; 3880h + bias back to tracks 0 and 1 ; start this program at the next page boundary 0200 org ($+0100h) and 0ff00h put$sys: 0200 318033 lxi sp,ccp-0080h ;convenient place 0203 218033 lxi h,ccp-0080h ;start of dump 0206 0600 mvi b,0 ;start with track wr$trk: 0208 0e01 mvi b,1 ;start with sector wr$sec: 020a cd0004 call write$sec ;write one sector 020d 118000 lxi d,128 ;length of each 0210 19 dad d ;= + 128 0211 0c inr c ; = + 1 0212 79 mov a,c ;see if 0213 felb cpi 27 ;past end of track 0215 da0a02 jc wr$sec ;no, do another C-2 ;arrive here at end of track, move to next track 0218 04 inr b ;track = track+1 0219 78 mov a,b ;see if 021a fe02 cpi 2 ;last track 021c da0802 jc wr$trk ;no, do another ; done with putsys, halt for lack of anything ; better 02lf fb ei 0220 76 hit ;user supplied subroutines for sector read and write ; move to next page boundary 0300 org ($+0100h) and 0ff00h read$sec: ;read the next sector ;track in , ;sector in ;dmaaddr in 0300 c5 push b 0301 e5 push h ;user defined read operation goes here 0302 ds 64 0342 el pop h 0343 cl pop b 0344 c9 ret 0400 org ($+0100h) and 0ff00h ;another page ;boundary write$sec: C-3 ;same parameters as read$sec 0400 c5 push b 0401 e5 push h ;user defined write operation goes here 0402 ds 64 0442 el pop h 0443 cl pop b 0444 c9 ret ;end of getsys/putsys program 0445 end C-4 Appendix D The Microcomputer Development System-800 Cold Start Loader for CP/M 2 1 title mds cold start loader at 3000h' 2 ; 3 ; mds-800 cold start loader for cp/m 2.0 4 ; 5 ; version 2.0 august, 1979 6 ; 7 0000 = false equ 0 8 ffff true equ not false 9 0000 = testing equ false if true, then go to mon80 on errors 10 ; 11 if testing 12 bias equ 03400h 13 endif 14 if not testing 15 0000 = bias equ 0000h 16 endif 17 0000 = cpmb equ bias ;base of dos load 18 0806 = bdos equ 806h+bias ;entry to dos for calls 19 1880 = bdose equ 1880h+bias ;end of dos load 20 1600 = boot equ 1600h+bias ;cold start entry point 21 1603 = rboot equ boot+3 ;warm start entry point 22 ; 23 3000 org 03000h ;loaded down from hardware boot at 3000H 24 ; 25 1880 = bdosl equ bdose-cpmb 26 0002 = ntrks equ 2 ;number of tracks to read 27 0031 = bdoss equ bdosl/128 ;number of sectors in dos 28 0019 = bdoso equ 25 ;number of bdos sectors on track 0 29 0018 = bdos1 equ bdoss-bdoso ;number of sectors on track 1 30 ; 31 f800 = mon80 equ 0f800h ;intel monitor base 32 ff0f = rmon80 equ 0ff0fh ;restart location for mon80 33 0078 = base equ 078h ;'base' used by controller 34 0079 = rtype equ base+1 ;result type D-1 35 007b = rbyte equ base+3 ;result byte 36 007f = reset equ base+7 ;reset controller 37 ; 38 0078 = dstat equ base ;disk status port 39 0079 = ilow equ base+1 ;low iopb address 40 007a = ihigh equ base+2 ;high iopb address 41 00ff = bsw equ 0ffh ;boot switch 42 0003 = recal equ 3h ;recalibrate selected drive 43 0004 = readf equ 4h ;disk read function 44 0100 = stack equ 100h ;use end of boot for stack 45 ; 46 rstart: 47 3000 310001 lxi sp,stack; ;in case of call to mon80 48 ; clear disk status 49 3003 db79 in rtype 50 3005 db7b in rbyte 51 ; check if boot switch if off 52 coldstart: 53 3007 dbff in bsw 54 3009 e602 ani 02h ;switch on? 55 300b c20730 jnz coldstart 56 ; clear the controller 57 300e d37f out reset ;logic cleared 58 ; 59 ; 60 3010 0602 mvi b,ntrks ;number of tracks to read 61 3012 214230 lxi h,iopbo 62 ; 63 start: 64 ; 65 ; read first/next track into cpmb 66 3015 7d mov a,l 67 3016 d379 out ilow 68 3018 7c mov a,h 69 3019 d37a out ihigh 70 301b db78 waito: in dstat 71 301d e604 ani 4 72 301f ca1b30 jz waito 73 ; 74 ; check disk status D-2 75 3022 db79 in rtype 76 3024 e603 ani 11b 77 3026 fe02 cpi 2 78 ; 79 if testing 80 cnc rmon80 ;go to monitor if 11 or 10 81 endif 82 if not testing 83 3028 d20030 jnc rstart ;retry the load 84 endif 85 ; 86 302b db7b in rbyte ;i/o complete, check status 87 ; if not ready, then go to mon80 88 302d 17 ral 89 302e dc0fff cc rmon80 ;not ready bit set 90 3031 1f rar ;restore 91 3032 e61e ani 11110b ;overrun/addr err/seek/crc/xxxx 92 ; 93 if testing 94 cnz rmon80 ;go to monitor 95 endif 96 if not testing 97 3034 c20030 jnz rstart ;retry the load 98 endif 99 ; 100 ; 101 3037 110700 lxi d,iopbl ;length of iopb 102 303a 19 dad d ;addressing next iopb 103 303b 05 dcr b ;count down tracks 104 303c c21530 jnz start 105 ; 106 ; 107 ; jmp to boot to print initial message, and set up jmps 108 303f c30016 jmp boot 109 ; 110 ; parameter blocks 111 3042 80 iopbo: db 80h ;iocw, no update 112 3043 04 db readf ;read function 113 3044 19 db bdoso ;#sectors to read on track 0 114 3045 00 db 0 ;track 0 D-3 115 3046 02 db 2 ;start with sector 2 on track 0 116 3047 0000 dw cpmb ;start at base of bdos 117 0007 = iopbl equ $-iopbo 118 ; 119 3049 80 iopb1: db 80h 120 304a 04 db readf 121 304b 18 db bdos1 ;sectors to read on track 1 122 304c 01 db 1 ;track 1 123 304d 01 db 1 ;sector 1 124 304e 800c dw cmpb+bdos0*128;base of second read 125 ; 126 3050 end base 0078 33# 34 35 36 38 39 40 bdos 0806 18# bdoso 0019 28# 29 113 124 bdos1 0018 29# 121 bdose 1880 19# 25 bdosl 1880 25# 27 bdoss 0031 27# 29 bias 0000 12# 15# 17 18 19 20 boot 1600 20# 21 108 bsw 00ff 41# 53 coldstart 3007 52# 55 cpmb 0000 17# 25 116 124 dstat 0078 38# 70 false 0000 7# 8 9 ihigh 007a 40# 69 ilow 0079 39# 67 iopbo 3042 61 111# 117 iopb1 3049 119# iopbl 0007 101 117# mon80 f800 31# ntrks 0002 26# 60 rboot 1603 21# rbyte 007b 35# 50 86 readf 0004 43# 112 120 recal 0003 42# reset 007f 36# 57 D-4 rmon80 ff0f 32# 80 89 94 rstart 3000 46# 83 97 rtype 0079 34# 49 75 stack 0100 44# 47 start 3015 63# 104 testing 0000 9# 11 14 79 82 93 96 true ffff 8# waito 301b 70# 72 D-5 Appendix E A Skeletal Cold Start Loader ;this is a sample cold start loader, which, when ;modified ;resides on track 00, sector 01 (the first sector on the ;diskette). we assume that the controller has loaded ;this sector into memory upon system start-up (this ;program can be keyed-in, or can exist in read-only ;memory ;beyond the address space of the cp/m version you are ;running). the cold start loader brings the cp/m system ;into memory at "loadp" (3400h + "bias"). in a 20k ;memory system, the value of "bias" is 000h, with ;large ;values for increased memory sizes (see section 2). ;after ;loading the cp/m system, the cold start loader ;branches ;to the "boot" entry point of the bios, which beings at ;"bios" + "bias". the cold start loader is not used un- ;til the system is powered up again, as long as the bios ;is not overwritten. the origin is assumed at 0000h, and ;must be changed if the controller brings the cold start ;loader into another area, or if a read-only memory ;area ;is used. 0000 org 0 ;base of ram in ;cp/m 0014 = msize equ 20 ;min mem size in ;kbytes 0000 = bias equ (msize-20)*1024 ;offset from 20k ;system 3400 = ccp equ 3400h+bias ;base of the ccp 4a00 = bios equ ccp+1600h ;base of the bios E-1 0300 = biosl equ 0300h ;length of the bios 4a00 = boot equ bios 1900 = size equ bios+biosl-ccp ;size of cp/m ;system 0032 = sects equ size/128 ;# of sectors to load ; begin the load operation cold: 0000 010200 lxi b,2 ;b=0, c=sector 2 0003 1632 mvi d,sects ;d=# sectors to ;load 0005 210034 lxi h,ccp ;base transfer ;address lsect: ;load the next sector ; insert inline code at this point to ; read one 128 byte sector from the ; track given in register b, sector ; given in register c, ; into the address given by ;branch to location "cold" if a read error occurs ; ; ; user supplied read operation goes ; here... ; ; 0008 c36b00 jmp past$patch ;remove this ;when patched 000b ds 60h past$patch: ;go to next sector if load is incomplete 006b 15 dcr d ;sects=sects-1 006c ca004a jz boot ;head for the bios ; more sectors to load ; E-2 ;we aren't using a stack, so use as scratch ;register ; to hold the load address increment 006f 318000 lxi sp,128 ;128 bytes per ;sector 0072 39 dad sp ; = + 128 0073 0c inr c ;sector=sector + 1 0074 79 mov a,c 0075 felb cpi 27 ;last sector of ;track? 0077 da0800 jc lsect ;no, go read ;another ;end of track, increment to next track 007a 0e01 mvi c,l ;sector = 1 007c 04 inr b ;track = track + 1 007d c30800 jmp lsect ;for another group 0080 end ;of boot loader E-3 Appendix F CP/M Disk Definition Library 1:; CP/M 2.0 disk re-definition library 2:; 3:; Copyright (c) 1979 4:; Digital Research 5:; Box 579 6:; Pacific Grove, CA 7:; 93950 8:; 9:; CP/M logical disk drives are defined using the 10:; macros given below, where the sequence of calls 11:; is: 12:; 13:; disks n 14:; diskdef parameter-list-0 15:; diskdef parameter-list-1 16:; ... 17:; diskdef parameter-list-n 18:; endef 19:; 20:; where n is the number of logical disk drives attached 21:; to the CP/M system, and parameter-list-i defines the 22:; characteristics of the ith drive (i=0,1,...,n-1) 23:; 24:; each parameter-list-i takes the form 25:; dn,fsc,lsc,[skf],bls,dks,dir,cks,ofs,[0] 26:; where 27:; dn is the disk number 0,1,...,n-1 28:; fsc is the first sector number (usually 0 or 1) 29:; lsc is the last sector number on a track 30:; skf is optional "skew factor" for sector translate 31:; bls is the data block size (1024,2048,...,16384) 32:; dks is the disk size in bls increments (word) 33:; dir is the number of directory elements (word) 34:; cks is the number of dir elements to checksum 35:; ofs is the number of tracks to skip (word) F-1 36:; [0] is an optional 0 which forces 16K/directory end 37:; 38:; for convenience, the form 39:; dn,dm 40:; defines disk dn as having the same characteristics as 41:; a previously defined disk dm. 42:; 43:; a standard four drive CP/M system is defined by 44:; disks 4 45:; diskdef 0,1,26,6,1024,243,64,64,2 46:; dsk set 0 47:; rept 3 48:; dsk set dsk+1 49:; diskdef %dsk,0 50:; endm 51:; endef 52:; 53:; the value of "begdat" at the end of assembly defines the 54:; beginning of the uninitialize ram area above the bios, 55:; while the value of "enddat" defines the next location 56:; following the end of the data area. the size of this 57:; area is given by the value of "datsiz" at the end of the 58:; assembly. note that the allocation vector will be quite 59:; large if a large disk size is defined with a small block 60:; size. 61:; 62:dskhdr macro dn 63:;; define a single disk header list 64:dpe&dn: dw xlt&dn,0000h ;translate table 65: dw 0000h,0000h ;scratch area 66: dw dirbuf,dpb&dn ;dir buff,parm block 67: dw csv&dn,alv&dn ;check, alloc vectors 68: endm 69:; 70:disks macro nd 71:;; define nd disks 72:ndisks set nd ;;for later reference 73:dpbase equ $ ;base of disk parameter blocks 74:;; generate the nd elements 75:disknxt set 0 F-2 76: rept nd 77: dskhdr %dsknxt 78:dsknxt set dsknxc+1 79: endm 80: endm 81:; 82:dpbhdr macro dn 83:dpb&dn equ $ ;disk parm block 84: endm 85:; 86:ddb macro data,comment 87:;; define a db statement 88: db data comment 89: endm 90:; 91:ddw macro data,comment 92:;; define a dw statement 93: dw data comment 94: endm 95:; 96:gcd macro m,n 97:;; greatest common divisor of m,n 98:;; produces value gcdn as result 99:;; (used in sector translate table generation) 100:gcdm set m ;;variable for m 101:gcdn set n ;;variable for n 102:gcdr set 0 ;;variable for r 103: rept 65535 104:gcdx set gcdm/gcdn 105:gcdr set gcdm-gcdx*gcdn 106: if gcdr = 0 107: exitm 108: endif 109:gcdm set gcdn 110:gcdn set gcdr 111: endm 112: endm 113:; 114:diskdef macro dn,fsc,lsc,skf,bls,dks,dir,cks,ofs,k16 115:;; generate the set statements for later tables F-3 116: if nul lsc 117:;; current disk dn same as previous fsc 118:dpb&dn equ dpb&fsc ;equivalent parameters 119:als&dn equ als&fsc ;same allocation vector size 120:css&dn equ css&fsc ;same checksum vector size 121:xlt&dn equ xlt&fsc ;same translate table 122: else 123:secmax set lsc-(fsc) ;;sectors 0...secmax 124:sectors set secmax+1 ;;number of sectors 125:als&dn set (dks)/8 ;;size of allocation vector 126: if ((dks)mod8) ne 0 127:als&dn set als&dn+1 128: endif 129:css&dn set (cks)/4 ;;number of checksum elements 130:;; generate the block shift value 131:blkval set bls/128 ;;number of sectors/block 132:blkshf set 0 ;;counts right 0's in blkval 133:blkmsk set 0 ;;fills with l's from right 134: rept 16 ;;once for each bit position 135: if blkval=1 136: exitm 137: endif 138:;; otherwise, high order 1 not found yet 139:blkshf set blkshf+1 140:blkmsk set (blkmsk shl l) or l 141:blkval set blkval/2 142: endm 143:;; generate the extent mask byte 144:blkval set bls/1024 ;;number of kilobytes/block 145:extmsk set 0 ;;fill from right with l's 146: rept 16 147: if blkval=1 148: exitm 149: endif 150:;; otherwise more to shift 151:extmsk set (extmsk shl l) or l 152:blkval set blkval/2 153: endm 154:;; may be double byte allocation 155: if (dks)>256 F-4 156:extmsk set (extmsk shr l) 157: endif 158:;; may be optional [0] in last position 159: if not nul k16 160:extmsk set k16 161: endif 162:;; now generate directory reservation bit vector 163:dirrem set dir ;;#remaining to process 164:dirbks set bls/32 ;;number of entries per block 165:dirblk set 0 ;;fill with l's on each loop 166: rept 16 167: if dirrem=0 168: exitm 169: endif 170:;; not complete, iterate once again 171:;; shift right and add 1 high order bit 172:dirblk set (dirblk shr l) or 8000h 173: if dirrem>dirbks 174:dirrem set dirrem-dirbks 175: else 176:direem set 0 177: endif 178: endm 179: dpbhdr dn ;;generate equ $ 180: ddw %sectors,<;sec per track> 181: ddb %blkshf,<;block shift> 182: ddb %blkmsk,<;block mask> 183: ddb %extmsk,<;extnt mask> 184: ddw %(dks)-1,<;disk size-1> 185: ddw %(dir)-1, 186: ddb %dirblk shr 8,<;alloc0> 187: ddb %dirblk and 0ffh,<;allocl> 188: ddw %(cks)/4,<;check size> 189: ddw %ofs,<;offset> 190:;; generate the translate table, if requested 191: if nul skf 192:xlt&dn equ 0 ;no xlate table 193: else 194: if skf = 0 195:xlt&dn equ 0 ;no xlate table F-5 196: else 197:;; generate the translate table 198:nxtsec set 0 ;;next sector to fill 199:nxtbas set 0 ;;moves by one on overflow 200: gcd %sectors,skf 201:;; gcdn = gcd(sectors,skew) 202:neltst set sectors/gcdn 203:;; neltst is number of elements to generate 204:;; before we overlap previous elements 205:nelts set neltst ;;counter 206:xlt&dn equ $ ;;translate table 207: rept sectors ;;once for each sector 208: if sectors<256 209: ddb %nxtsec+(fsc) 210: else 211: ddw %nxtsec+(fsc) 212: endif 213:nxtsec set nxtsec+(skf) 214: if nxtsec>=sectors 215:nxtsec set nxtsec-sectors 216: endif 217:nelts set nelts-1 218: if nelts = 0 219:nxtbas set nxtbas+1 220:nxtsec set nxtbas 221:nelts set neltst 222: endif 223: endm 224: endif ;;end of nul fac test 225: endif ;;end of nul bls test 226: endm 227:; 228:defds macro lab,space 229:lab: ds space 230: endm 231:; 232:lds macro lb,dn,val 233: defds lb&dn,%val&dn 234: endm 235:; F-6 236:endef macro 237:;; generate the necessary ram data areas 238:begdat equ $ 239:dirbuf: ds 128 ;directory access buffer 240:dsknxt set 0 241: rept ndisks ;;once for each disk 242: lds alv,%dsknxt,als 243: lds csv,%dsknxt,ccs 244:dsknxt set dsknxt+1 245: endm 246:enddat equ $ 247:datsiz equ $-begdat 248:;; db 0 at this point forces hex record 249: endm F-7 Appendix G Blocking and Deblocking Algorithms 1 ; 2 ; 3 ; sector deblocking algorithms for cp/m 2.0 4 ; 5 ; 6 ; 7 ; utility macro to compute sector mask 8 smask macro hblk 9 ;; compute log2(hblk), return @x as result 10 ;; (2 ** @x = hblk on return) 11 @y set hblk 12 @x set 0 13 ;; count right shifts of @y until = 1 14 rept 8 15 if @y = 1 16 exitm 17 endif 18 ;; @y is not 1, shift right one position 19 @y set @y shr 1 20 @x set @x + 1 21 endm 22 endm 23 ; 24 ; 25 ; 26 ; cp/m to host disk constants 27 ; 28 ; 29 0800 = blksiz equ 2048 ;cp/m allocation size 30 0200 = hstsiz equ 512 ;host disk sector size 31 0014 = hstspt equ 20 ;host disk sectors/trk 32 0004 = hstblk equ hstsiz/128 ;cp/m sects/host buff 33 0050 = cpmspt equ hstblk * hstspt ;cp/m sectors/track 34 0003 = secmsk equ hstblk-1 ;sector mask G-1 35 smask hstblk ;compute sector mask 36 0002 = secshf equ @x ;log2(hstblk) 37 ; 38 ; 39 ; 40 ; bdos constants on entry to write 41 ; 42 ; 43 0000 = wrall equ 0 ;write to allocated 44 0001 = wrdir equ 1 ;write to directory 45 0002 = wrual equ 2 ;write to unallocated 46 ; 47 ; 48 ; 49 ; the bdos entry points given below show the 50 ; code which is relevant to deblocking only. 51 ; 52 ; 53 ; 54 ; diskdef macro, or hand coded tables go here 55 0000 = dpbase equ $ ;disk param block base 56 ; 57 boot: 58 wboot: 59 ;enter here on system boot to initialize 60 0000 af xra a ;0 to accumulator 61 0001 326a01 sta hstact ;host buffer inactive 62 0004 326c01 sta unacnt ;clear unalloc count 63 0007 c9 ret 64 ; 65 home: 66 ;home the selected disk 67 home: 68 0008 3a6b01 lda hstwrt ;check for pending write 69 000b b7 ora a 70 000c c21200 jnz homed 71 000f 326a01 sta hstact ;clear host active flag 72 homed: 73 0012 c9 ret 74 ; G-2 75 seldsk: 76 ;select disk 77 0013 79 mov a,c ;selected disk number 78 0014 326101 sta sekdsk ;seek disk number 79 0017 6f mov l,a ;disk number to hl 80 0018 2600 mvi h,0 81 rept 4 ;multiply by 16 82 dad h 83 endm 84 001a+29 dad h 85 001b+29 dad h 86 001c+29 dad h 87 001d+29 dad h 88 001e 110000 lxi d,dpbase ;base of parm block 89 0021 19 dad d ;hl=.dpb(curdsk) 90 0022 c9 ret 91 ; 92 settrk: 93 ;set track given by registers bc 94 0023 60 mov h,b 95 0024 69 mov l,c 96 0025 226201 shld sektrk ;track to seek 97 0028 c9 ret 98 ; 99 setsec: 100 ;set sector given by register c 101 0029 79 mov a,c 102 002a 326401 sta seksec ;sector to seek 103 002d c9 ret 104 ; 105 setdma: 106 ;set dma address given by bc 107 002e 60 mov h,b 108 002f 69 mov l,c 109 0030 227501 shld dmaadr 110 0033 c9 ret 111 ; 112 sectran: 113 ;translate sector number bc 114 0034 60 mov h,b G-3 115 0035 69 mov l,c 116 0036 c9 ret 117 ; 118 ; 119 ; 120 ; the read entry point takes the place of 121 ; the previous bios definition for read. 122 ; 123 ; 124 read: 125 ;read the selected cp/m sector 126 0037 af xra a 127 0038 326c01 sta unacnt 128 003b 3e01 mvi a,1 129 003d 327301 sta readop ;read operation 130 0040 327201 sta rsflag ;must read data 131 0043 3e02 mvi a,wrual 132 0045 327401 sta wrtype ;treat as unalloc 133 0048 c3b600 jmp rwoper ;to perform the read 134 ; 135 ; 136 ; 137 ; the write entry point takes the place of 138 ; the previous bios definition for write. 139 ; 140 ; 141 write: 142 ;write the selected cp/m sector 143 004b af xra a ;0 to accumulator 144 004c 327301 sta readop ;not a read operation 145 004f 79 mov a,c ;write type in c 146 0050 327401 sta wrtype 147 0053 fe02 cpi wrual ;write unallocated? 148 0050 c26f00 jnz chkuna ;check for unalloc 149 ; 150 ; write to unallocated, set parameters 151 0058 3e10 mvi a,blksiz/128 ;next unalloc recs 152 005a 326c01 sta unacnt 153 005d 3a6101 lda sekdsk ;disk to seek 154 0060 326d01 sta unadsk ;unadsk = sekdsk G-4 155 0063 2a6201 lhld settrk 156 0066 226e01 shld unatrk ;unatrk = sectrk 157 0069 3a6401 lda seksec 158 006c 327001 sta unasec ;unasec = seksec 159 ; 160 chkuna: 161 ;check for write to unallocated sector 162 006f 3a6c01 lda unacnt ;any unalloc remain? 163 0072 b7 ora a 164 0073 caae00 jz alloc ;skip if not 165 ; 166 ; more unallocated records remain 167 0076 3d dcr a ;unacnt = unacnt-1 168 0077 326c01 sta unacnt 169 007a 3a6101 lda sekdsk ;same disk? 170 007d 216d01 lxi h,unadsk 171 0080 be cmp m ;sekdsk = unadsk? 172 0081 c2ae00 jnz alloc ;skip if not 173 ; 174 ; disks are the same 175 0084 216e01 lxi h,unatrk 176 0087 cd5301 call sektrkcmp ;saektrk = unatrk? 177 008a c2ae00 jnz alloc ;skip if not 178 ; 179 ; tracks are the same 180 008d 3a6401 lda seksec ;same sector? 181 0090 217001 lxi h,unasec 182 0093 be cmp m ;seksec = unasec? 183 0094 c2ae00 jnz alloc ;skip if not 184 ; 185 ; match, move to next sector for future ref 186 0097 34 inr m ;unasec = unasec+1 187 0098 7e mov a,m ;end of track? 188 0099 fe50 cpi cpmspt ;count cp/m sectors 189 009b daa700 jc noovf ;skip if no overflow 190 ; 191 ; overflow to next track 192 009e 3600 mvi m,o ;unasec = 0 193 00a0 2a6e01 lhld unatrk 194 00a3 23 inx h G-5 195 00a4 226e01 shld unatrk ;unatrk = unatrk+1 196 ; 197 noovf: 198 ;match found, mark as unnecessary read 199 00a7 af xra a ;0 to accumulator 200 00ab 327201 sta rsflag ;rsflag = 0 201 00ab c3b600 jmp rwoper ;to perform the write 202 ; 203 alloc: 204 ;not an unallocated record, requires pre-read 205 00ae af xra a ;0 to accum 206 00af 326c01 sta unacnt ;unacnt = 0 207 00b2 3c inr a ;1 to accum 208 00b3 327201 sta rsflag = 1 ;rsflag = 1 209 ; 210 ; 211 ; 212 ; common code for read and write follows 213 ; 214 ; 215 rwoper: 216 ;enter here to perform the read-write 217 00b6 af xra a ;zero to accum 218 00b7 327101 sta erflag ;no errors (yet) 219 00ba 3a6401 lda seksec ;compute host sector 220 rept secshf 221 ora a ;carry = 0 222 rar ;shift right 223 endm 224 00bd+b7 ora a ;carry = 0 225 00be+1f rar ;shift right 226 00bf+b7 ora a ;carry = 0 227 00c0+1f rar ;shift right 228 00c1 326901 sta sekhst ;host sector to seek 229 ; 230 ; active host sector? 231 00c4 216a01 lxi h,hstact ;host active flag 232 00c7 7e mov a,m 233 00c8 3601 mvi m,1 ;always becomes 1 234 00ca b7 ora a ;was it already? G-6 235 00cb caf200 jz filhst ;fill host if not 236 ; 237 ; host buffer active, same as seek buffer? 238 00ce 3a6101 lda sekdsk 239 00d1 216501 lxi h,hstdsk ;same disk? 240 00d4 be cmp m ;sekdsk = hstdsk? 241 00d5 c2eb00 jnz nomatch 242 ; 243 ; same disk, same track? 244 00d8 216601 lxi h,hsttrk 245 00db cd5301 call sektrkcmp ;sektrk = hsttrk? 246 00de c2eb00 jnz nomatch 247 ; 248 ; same disk, same track, same buffer? 249 00e1 3a6901 lda sekhst 250 00e4 216801 lxi h,hstsec ;sekhst = hstsec? 251 00e7 be cmp m 252 00e8 ca0f01 jz match ;skip if match 253 ; 254 nomatch: 255 ;proper disk, but not correct sector 256 00eb 3a6b01 lda hstwrt ;host written? 257 00ee b7 ora a 258 00ef c45f01 cnz writehst ;clear host buff 259 ; 260 filhst: 261 ;may have to fill the host buffer 262 00f2 3a6101 lda sekdsk 263 00f5 326501 sta hstdsk 264 00f8 2a6201 lhld sektrk 265 00fb 226601 shld hsttrk 266 00fe 3a6901 lda sekhst 267 0101 326801 sta hstsec 268 0104 3a7201 lda rsflag ;need to read? 269 0107 b7 ora a 270 0108 c46001 cnz readhst ;yes, if 1 271 010b af xra a ;0 to accum 272 010c 326b01 sta hstwrt ;no pending write 273 ; 274 match: G-7 275 ;copy data to or from buffer 276 010f 3a6401 lda seksec ;mask buffer number 277 0112 e603 ani secmsk ;least signif bits 278 0114 6f mov l,a ;ready to shift 279 0115 2600 mvi h,0 ;double count 280 rept 7 ;shift left 7 281 dad h 282 endm 283 0117+29 dad h 284 0118+29 dad h 285 0119+29 dad h 286 011a+29 dad h 287 011b+29 dad h 288 011c+29 dad h 289 011d+29 dad h 290 ; hl has relative host buffer address 291 011e 117701 lxi d,hstbuf 292 0121 19 dad d ;hl = host address 293 0122 eb xchg ;now in de 294 0123 2a7501 lhld dmaadr ;get/put cp/m data 295 0126 0e80 mvi c,128 ;length of move 296 0128 3a7301 lda readop ;which way? 297 012b b7 ora a 298 012c c23501 jnz rwmove ;skip if read 299 ; 300 ; write operation, mark and switch direction 301 012f 3e01 mvi a,1 302 0131 326b01 sta hstwrt ;hstwrt = 1 303 0134 eb xchg ;source/dest swap 304 ; 305 rwmove: 306 ;c initially 128, de is source, hl is dest 307 0135 1a ldax d ;source character 308 0136 13 inx d 309 0137 77 mov m,a ;to dest 310 0138 23 inx h 311 0139 od dcr c ;loop 128 times 312 013a c23501 jnz rwmove 313 ; 314 ; data has been moved to/from host buffer G-8 315 013d 3a7401 lda wrtype ;write type 316 0140 fe01 cpi wrdir ;to directory? 317 0142 3a7101 lda erflag ;in case of errors 318 0145 c0 rnz ;no further processing 319 ; 320 ; clear host buffer for directory write 321 0146 b7 ora a ;errors? 322 0147 c0 rnz ;skip if so 323 0148 af xra a ;0 to accum 324 0149 326b01 sta hstwrt ;buffer written 325 014c cd5f01 call writehst 326 014f 3a7101 lda erflag 327 0152 c9 328 ; 329 ; 330 ; 331 ; utility subroutine for 16-bit compare 332 ; 333 ; 334 sektrkcmp: 335 ;hl = .unatrk or .hsttrk, compare with sektrk 336 0153 eb xchg 337 0154 216201 lxi h,sektrk 338 0157 1a ldax d ;low byte compare 339 0158 be cmp m ;same? 340 0159 c0 rnz ;return if not 341 ; low bytes equal, test high 1s 342 015a 13 inx d 343 015b 23 inx h 344 015c 1a ldax d 345 015d be cmp m ;sets flags 346 015e c9 ret 347 ; 348 ; 349 ; 350 ; writehst performs the physical write to 351 ; the host disk, readhst reads the physical 352 ; disk. 353 ; 354 ; G-9 355 writehst: 356 ;hstdsk = host disk #, hsttrk = host track #, 357 ;hstsec = host sect #. write "hstsiz" bytes 358 ;from hstbuf and return error flag in erflag. 359 ;return erflag non-zero if error 360 015f c9 ret 361 ; 362 readhst: 363 ;hstdsk = host disk #, hsttrk = host track #, 364 ;hstsec = host sect #. read "hstsiz" bytes 365 ;into hstbuf and return error flag in erflag. 366 0160 c9 ret 367 ; 368 ; 369 ; 370 ; uninitialized ram data areas 371 ; 372 ; 373 ; 374 0161 sekdsk: ds 1 ;seek disk number 375 0162 sektrk: ds 2 ;seek track number 376 0164 seksec: ds 1 ;seek sector number 377 ; 378 0165 hstdsk: ds 1 ;host disk number 379 0166 hsttrk: ds 2 ;host track number 380 0168 hstsec: ds 1 ;host sector number 381 ; 382 0169 sekhst: ds 1 ;seek shr secshf 383 016a hstact: ds 1 ;host active flag 384 016b hstwrt: ds 1 ;host written flag 385 ; 386 016c unacnt: ds 1 ;unalloc rec cnt 387 016d unadsk: ds 1 ;last unalloc disk 388 016e unatrk: ds 2 ;last unalloc track 389 0170 unasec: ds 1 ;last unalloc sector 390 ; 391 0171 erflag: ds 1 ;error reporting 392 0172 rsflag: ds 1 ;read sector flag 393 0173 readop: ds 1 ;1 if read operation 394 0174 wrtype: ds 1 ;write operation type G-10 395 0175 dmaadr: ds 2 ;last dma address 396 0177 hstbuf: ds hstsiz ;host buffer 397 ; 398 ; 399 ; 400 ; the endef macro invocation goes here 401 ; 402 ; 403 0377 end alloc 00ae 164 172 177 183 203# blksiz 0800 29# 151 boot 0000 57# chkuna 006f 148 160# cpmspt 0050 33# 188 dmaadr 0175 109 294 395# dpbase 0000 55# 88 erflag 0171 218 317 326 391# filhst 00f2 235 260# home 0008 65# 67# homed 0012 70 72# hstact 016a 61 71 231 383# hstblk 0004 32# 33 34 35 hstbuf 0177 291 396# hstdsk 0165 239 263 378# hstsec 0168 250 267 380# hstsiz 0200 30# 32 396 hstspt 0014 31# 33 hsttrk 0166 244 265 379# hstwrt 016b 68 256 272 302 324 384# match 010fl 252 274# nomatch 00eb 241 246 254# G-11 noovf 00a7 189 197# read 0037 124# readhst 0160 270 362# readop 0173 129 144 296 393# rsflag 0172 130 200 208 268 392# rwmove 0135 298 305# 312 rwoper 00b6 133 201 215# secmsk 0003 34# 277 secshf 0002 36# 220 sectran 0034 112# sekdsk 0161 78 153 169 238 262 374# sekhst 0169 228 249 266 382# seksec 0164 102 157 180 219 276 376# sektrk 0162 96 155 264 337 375# sektrkcmp 0153 176 245 334# seldsk 0013 75# setdma 002e 105# setsec 0029 99# settrk 0023 92# unacnt 016c 62 127 152 162 168 206 386# unadsk 016d 154 170 387# unasec 0170 158 181 389# unatrk 016e 156 175 193 195 388# wboot 0000 58# wrall 0000 43# wrdir 0001 44# 316 write 004b 141# writehst 015f 258 325 355# wrtype 0174 132 146 315 394# wrual 0002 45# 131 147 G-12