You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3010 lines
125 KiB

XS 9 N0
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 ;<hl>=<hl> + 128
0211 0c inr c ; <c>=<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 <b>,
;sector in <c>
;dmaaddr in <hl>
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 <hl>
;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 <sp> as scratch
;register
; to hold the load address increment
006f 318000 lxi sp,128 ;128 bytes per
;sector
0072 39 dad sp ;<hl> = <hl> +
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,<directory max>
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