.pl 51
.nf
.bp 1
.ft                                                       G-%
                                     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
 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                ;
 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
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
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
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?
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:
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
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                ;
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
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#
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
