home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / sigmv062.ark / DTST.Z80 < prev    next >
Text File  |  1984-04-29  |  23KB  |  1,079 lines

  1.     title    'Z-80 Floppy Disk Test'
  2. ; Floppy Disk Test for Z-80 CP/M Systems
  3. ;
  4. ; version 1.0  16 December 1980
  5. ;
  6. ; The purchaser may freely create any number
  7. ; of copies of this program on magnetic media
  8. ; as necessary to support his computer system(s).
  9. ; Further resale of this program is prohibited.
  10. ;
  11. ; Copyright (c) 1980 by
  12. ; Ray Duncan
  13. ; Laboratory Microsystems
  14. ; 4147 Beethoven Street
  15. ; Los Angeles, CA 90066
  16. ;
  17.     org    100h
  18. ;
  19. cpm    equ    5    ;references to
  20. wboot    equ    0     ;operating system
  21. ;
  22. ;            references to ASCII char
  23. cr    equ    0dh
  24. lf    equ    0ah
  25. ff    equ    0ch
  26. tab    equ    09h
  27. ;
  28. ;            parameters for disk
  29. ;            (supplied as single
  30. ;            density, soft sectored)
  31. $drvf    equ    1    ;first drive to allow
  32.             ;testing (0=A,1=B,etc)
  33. $drvl    equ    3    ;last drive to allow
  34.             ;testing
  35. $trkf    equ    0    ;first track
  36. $trkl    equ    76    ;last track
  37. $secf    equ    1    ;first sector
  38. $secl    equ    26    ;last sector
  39. $bps    equ    128    ;bytes per sector
  40. $bpt    equ    $bps*$secl ;bytes per track
  41. ;
  42.             ;number of digits to
  43.             ;accept in track and
  44.             ;sector assignments
  45. $dig    equ    2    ;(should be set larger
  46.             ; for devices having 
  47.             ; track or sector
  48.             ; numbers >99 )
  49. ;
  50. ;            program identification
  51. $ver    equ    1    ;version
  52. $rev    equ    0    ;revision
  53. ;
  54.     jp    dtst    ;enter from CP/M
  55.     form
  56. ; global variables for use by all routines
  57. ;
  58. pass    dw    0    ;current pass number
  59. errors    dw    0    ;error count for pass
  60. ;
  61.             ;the following variables
  62.             ;are used by RDBUF and
  63.             ;WTBUF to address the
  64.             ;disk, and by PERR to
  65.             ;display failing disk
  66.             ;addresses ---
  67. drv    db    0    ;drive to test
  68. trk    dw    0    ;current track
  69. sec    dw    0    ;current sector
  70. buffer    dw    0    ;current memory address
  71. iolen    dw    0    ;bytes last transferred
  72. ;
  73.             ;the following variables
  74.             ;define the area to be
  75.             ;tested on the selected
  76.             ;disk drive ---
  77. trkf    dw    0    ;first track to test
  78. trkl    dw    0    ;last track to test
  79. secf    dw    0    ;first sector to test
  80. secl    dw    0    ;last sector to test
  81. ;
  82.             ;the following variables
  83.             ;define the test mode ---
  84.             ;
  85. bypass    db    0    ;0=do not bypass error
  86.             ;itemization, 1=bypass
  87.             ;error itemization,print
  88.             ;total errors per pass
  89.             ;only.
  90.             ;
  91. skew    db    0    ;0=no sector skew
  92.             ;1=use sector skew for
  93.             ;  increased test speed
  94.             ;
  95. list    db    0    ;0=print errors on
  96.             ;terminal, 1=print errors
  97.             ;on list device.
  98.             ;
  99. lockio    db    0    ;0=no lock
  100.             ;1=lock on read
  101.             ;2=lock on write
  102.             ;
  103. restor    db    0    ;0=do not restore original
  104.             ;data, 1=restore original
  105.             ;data on diskette
  106.             ;
  107. lockpt    db    0    ;0=use variable test
  108.             ;data pattern, 1=lock on
  109.             ;user supplied data pattern
  110.             ;
  111. pattrn    db    0    ;contains user supplied
  112.             ;8 bit data pattern
  113.             ;
  114. passl    dw    0    ;last pass to do on this
  115.             ;test run
  116.             ;
  117. digits    db    $dig    ;maximum number of digits
  118.             ;to be accepted during
  119.             ;decimal or hexadecimal
  120.             ;numeric input.
  121.             ;
  122. xtran    dw    sectrb    ;address of sector
  123.             ;translation table
  124.     form
  125. ;
  126. ; disk test --- main control
  127. ;
  128. dtst    equ    $    ;entry from CP/M
  129.     ld    de,dtsta;print program title
  130.     ld    c,9
  131.     call    cpm
  132.     ld    hl,(cpm+1)
  133.     ld    de,buffend
  134.     or    a,a    ;make sure enough user
  135.     sbc    hl,de    ;memory to execute test
  136.     jr    nc,dtst01
  137.     ld    de,dtsts;not enough memory,
  138.     ld    c,9    ;print warning and exit.
  139.     call    cpm
  140.     jp    wboot
  141. dtst01    ld    c,12    ;check CP/M version
  142.     call    cpm
  143.     ld    a,l    ;make sure 2.x
  144.     and    0f0h
  145.     cp    20h
  146.     jr    z,dtst02
  147.     ld    de,dtstz;not CP/M 2.x, print
  148.     ld    c,9    ;error message and exit
  149.     call    cpm
  150.     jp    wboot
  151. dtst02    xor    a,a    ;initialize variables
  152.     ld    (bypass),a
  153.     ld    (skew),a
  154.     ld    (list),a
  155.     ld    (lockio),a
  156.     ld    (restor),a
  157.     ld    (lockpt),a
  158.     ld    (pass),a
  159.     ld    (pass+1),a
  160.     ld    (errors),a
  161.     ld    (errors+1),a
  162.             ;now set up test
  163.             ;configuration
  164.     ld    de,dtstb
  165.     call    getyn    ;itemize errors?
  166.     cp    'y'
  167.     jr    z,dtst03;yes
  168.     ld    a,1    ;no
  169.     ld    (bypass),a
  170.     jr    dtst04    ;skip query for output
  171.             ;device, since errors
  172.             ;will not be listed
  173. dtst03    ld    de,dtstc;audit errors on console
  174.     call    getl    ;or line printer?
  175.     cp    'c'
  176.     jr    z,dtst04;c=use console 
  177.     cp    'p'
  178.     call    nz,query
  179.     jr    nz,dtst03;no match,try again
  180.     ld    a,1    ;p=use line printer
  181.     ld    (list),a
  182. dtst04    ld    de,dtstd;lock on read or write?
  183.     call    getl
  184.     cp    'n'    ;n=no locks
  185.     jr    z,dtst06
  186.     cp    'r'    ;r=lock on read
  187.     jr    nz,dtst05
  188.     ld    a,1
  189.     ld    (lockio),a
  190.     jr    dtst12    ;bypass querys about
  191.             ;restore mode and
  192.             ;data pattern: since
  193.             ;we are locked in read
  194.             ;mode, they are
  195.             ;irrelevant.
  196.             ;
  197. dtst05    cp    'w'    ;w=lock on write
  198.     call    nz,query
  199.     jr    nz,dtst04 ;no match,try again
  200.     ld    a,2
  201.     ld    (lockio),a
  202.     jr    dtst08    ;bypass restore question,
  203.             ;since we are locked in
  204.             ;write mode.
  205.             ;
  206. dtst06    ld    de,dtste;restore user data?
  207.     call    getyn
  208.     cp    'y'    ;y=restore
  209.     jr    nz,dtst08 
  210.     ld    a,1    ;n=do not restore
  211.     ld    (restor),a
  212. dtst08    ld    de,dtstf;lock on data pattern?
  213.     call    getyn
  214.     cp    'n'
  215.     jr    z,dtst12;n=use variable pattern
  216.     ld    a,1    ;y=lock on pattern
  217.     ld    (lockpt),a ;supplied by operator
  218.     ld    de,dtstg;accept data pattern
  219.     call    geth    ;from keyboard
  220.     ld    (pattrn),a
  221. dtst12    ld    de,dtsth;select drive to be
  222.     call    getl    ;used for test
  223.     sub    'a'    ;convert to logical #
  224.     cp    $drvf    ;make sure its legal
  225.     call    c,query
  226.     jr    c,dtst12 ;too small,try again
  227.     cp    $drvl+1
  228.     call    nc,query
  229.     jr    nc,dtst12 ;too large,try again
  230.     ld    (drv),a    ;save drive assignment
  231.     add    'A'    ;also format for output
  232.     ld    (dtsti1),a
  233.     ld    de,dtsti;confirm selected drive?
  234.     call    getyn
  235.     cp    'n'
  236.     jr    z,dtst12;not confirmed,try again
  237.             ;
  238.             ;initialize track
  239.             ;limits
  240.     ld    hl,$trkf
  241.     ld    (trkf),hl
  242.     ld    hl,$trkl
  243.     ld    (trkl),hl
  244. dtst15    ld    de,dtstj ;test all tracks?
  245.     call    getyn
  246.     cp    'y'    ;y=use all of them
  247.     jr    z,dtst20;n=user wants to specify
  248.             ;  range of tracks
  249. dtst17    ld    de,dtstk;enter first track
  250.     call    getn    ;to test
  251.     ld    (trkf),hl ;save it
  252.     ld    de,dtstl;enter last track
  253.     call    getn    ;to test
  254.     ld    (trkl),hl ;save it
  255.     ld    de,(trkf);make sure first
  256.     or    a,a    ;track<=last track
  257.     sbc    hl,de
  258.     call    c,query    ;wrong,start over
  259.     jr    c,dtst17
  260. dtst20            ;initialize sector
  261.             ;limits
  262.     ld    hl,$secf
  263.     ld    (secf),hl
  264.     ld    hl,$secl
  265.     ld    (secl),hl
  266. dtst22    ld    de,dtstm;use all sectors
  267.     call    getyn    ;of each track?
  268.     cp    'y'
  269.     jr    z,dtst26;y=use all sectors
  270.             ;n=user wants to specify
  271.             ;range of sectors
  272. dtst24    ld    de,dtstn;enter first sector
  273.     call    getn    ;to test.
  274.     ld    (secf),hl ;save it.
  275.     ld    de,dtsto;enter last sector
  276.     call    getn    ;to test.
  277.     ld    (secl),hl ;save it.
  278.     ld    de,(secf);make sure first
  279.     or    a,a    ;sector<=last sector
  280.     sbc    hl,de
  281.     call    c,query
  282.     jr    c,dtst24;error,start over
  283.             ;
  284.             ;all variables set up
  285.             ;now --- how many
  286. dtst26    ld    de,dtstp;test passes should be
  287.     call    getn    ;made?
  288.     ld    (passl),hl ;save # of passes
  289.             ;
  290.             ;print advisory message
  291.     ld    de,dtstt;as test begins
  292.     ld    c,9
  293.     call    cpm
  294.     ld    de,dtstu;remind user whether he
  295.     ld    a,(restor) ;is using restore
  296.     or    a,a    ;mode
  297.     jr    z,dtst32
  298.     ld    de,dtstv
  299. dtst32    ld    c,9
  300.     call    cpm
  301.             ;
  302. dtst40            ;begin a pass
  303.     ld    hl,(trkf)
  304.     ld    (trk),hl;initialize current track
  305.             ;
  306. dtst42            ;process next track
  307.     ld    c,6    ;check for interruption
  308.     ld    e,0ffh
  309.     call    cpm    ;from console
  310.     or    a,a
  311.     jp    nz,dtst94 ;break detected,quit
  312.     ld    a,(restor)
  313.     or    a,a    ;is this restore mode?
  314.     jr    z,dtst45;no,jump
  315.     ld    hl,buff3;yes, save current
  316.     ld    de,merr1;disk contents
  317.     call    rdbuf
  318. dtst45    ld    a,(lockio)
  319.     cp    a,1    ;is this lock on read?
  320.     jr    z,dtst47;yes,jump
  321.     ld    hl,buff1;set up test pattern
  322.     ld    de,$bpt    
  323.     call    bufpat
  324.     ld    hl,buff1;write test pattern
  325.     ld    de,merr2
  326.     call    wtbuf
  327. dtst47    ld    a,(lockio)
  328.     cp    a,2    ;is this lock on write?
  329.     jr    z,dtst70;yes,jump
  330.     ld    hl,buff2;read back test pattern
  331.             ;(or just read existing
  332.             ; data if locked on read)
  333.     ld    de,merr3
  334.     call    rdbuf
  335. dtst50    ld    a,(lockio)
  336.     or    a,a    ;is this lock on
  337.             ;read or write?
  338.     jr    nz,dtst70 ;yes,jump
  339.             ;no, compare test data
  340.     ld    hl,buff1;written to data read
  341.     ld    de,buff2;back from disk. If
  342.     ld    bc,merr4;difference found,
  343.     call    bufcmp    ;print error message
  344. dtst70    ld    a,(restor)
  345.     or    a,a    ;using restore mode?
  346.     jr    z,dtst80;no,jump
  347.             ;yes,write back user's
  348.             ;data
  349.     ld    hl,buff3
  350.     ld    de,merr6
  351.     call    wtbuf
  352.     ld    hl,buff1;verify that
  353.     ld    de,merr7;it was rewritten ok
  354.     call    rdbuf
  355.     ld    hl,buff1
  356.     ld    de,buff3
  357.     ld    bc,merr5;check restored data
  358.     call    bufcmp
  359.             ;if difference found,
  360.             ;print 'data cannot
  361.             ;be restored'
  362.             ;
  363. dtst80            ;advance current track
  364.     ld    de,(trk)
  365.     inc    de
  366.     ld    (trk),de
  367.     ld    hl,(trkl)
  368.     or    a,a    ;done with all tracks?
  369.     sbc    hl,de
  370.     jp    nc,dtst42 ;no,process another
  371.             ;
  372. dtst90            ;end of pass
  373.     ld    bc,(pass)
  374.     inc    bc    ;count passes
  375.     ld    (pass),bc
  376.     ld    hl,dtstr1
  377.     call    conv    ;convert pass #
  378.     ld    bc,(errors)
  379.     ld    hl,dtstr2
  380.     call    conv    ;convert error count
  381.     ld    de,dtstr;print pass and errors
  382.     ld    c,9    ;on console
  383.     call    cpm
  384.     ld    a,(list);also using printer?
  385.     or    a,a
  386.     jr    z,dtst92;no,jump
  387.             ;yes,also send pass
  388.             ;and error count to
  389.             ;list device
  390.     ld    hl,dtstr
  391.     call    perr9
  392. dtst92            ;reset error count
  393.     xor    a,a
  394.     ld    (errors),a
  395.     ld    (errors+1),a
  396.     ld    hl,(pass)
  397.     ld    de,(passl)
  398.     or    a,a    ;are enough passes done?
  399.     sbc    hl,de
  400.     jp    c,dtst40;not yet,loop
  401. dtst94            ;done with all passes
  402.     ld    de,dtstw;ask whether to exit
  403.     call    getl    ;or to continue test
  404.     cp    'c'    ;c=continue
  405.     jp    z,dtst
  406.     cp    'e'    ;e=exit
  407.     jr    nz,dtst94;if no match,try again
  408.     ld    de,dtstx;print goodbye
  409.     ld    c,9
  410.     call    cpm    ;and return control
  411.     jp    wboot    ;to CP/M
  412.             ;
  413.     form
  414. ;
  415. ; routines to read and write up to one track
  416. ;
  417. rdbuf            ;read current track from
  418.             ;secf to secl
  419.             ;
  420.             ;call hl=buffer base addr
  421.             ;     de=error msg addr
  422.     ld    (rdbufa),de ;save message address
  423.     ld    (buffer),hl ;save buffer address
  424.     ld    hl,0    ;initialize transfer byte
  425.     ld    (iolen),hl ;count
  426.     call    seldsk    ;select disk
  427.     ld    hl,(secf)
  428.     ld    (sec),hl;initialize current sector
  429. rdbuf1    call    setio    ;set up track,sector,memory
  430.     call    read    ;now request transfer
  431.     or    a,a    ;was i/o successful?
  432.     jr    z,rdbuf2;no error,jump
  433.     ld    de,(rdbufa)
  434.     call    perr    ;i/o error, audit it
  435. rdbuf2    call    rwadv      ;advance sector address
  436.     jr    nc,rdbuf1;not done,read another
  437.     ret        ;back to caller
  438. rdbufa    dw    0    ;address of error message
  439. ;
  440. wtbuf            ;write current track
  441.             ;from secf to secl
  442.             ;
  443.             ;call de=error msg addr
  444.             ;     hl=buffer base addr
  445.             ;
  446.     ld    (wtbufa),de ;save message addr
  447.     ld    (buffer),hl ;save memory addr
  448.     ld    hl,0    ;initialize transfer
  449.     ld    (iolen),hl ;byte count
  450.     call    seldsk    ;select disk drive
  451.     ld    hl,(secf)
  452.     ld    (sec),hl;initialize current sector
  453. wtbuf1    call    setio    ;set track,sector,memory
  454.     call    write    ;request disk write
  455.     or    a,a    ;any i/o errors?
  456.     jr    z,wtbuf2;no,jump
  457.     ld    de,(wtbufa)
  458.     call    perr    ;error, audit it
  459. wtbuf2    call    rwadv      ;advance sector address
  460.     jr    nc,wtbuf1;not done,write another
  461.     ret        ;back to caller
  462. wtbufa    equ    rdbufa    ;save address of error
  463.             ;message
  464.             ;
  465. rwadv            ;advance sector and 
  466.             ;memory addresses
  467.             ;
  468.     ld    de,$bps    ; de <- bytes per sector
  469.     ld    hl,(buffer)
  470.     add    hl,de    ;update buffer address
  471.     ld    (buffer),hl
  472.     ld    hl,(iolen)
  473.     add    hl,de    ;count bytes transferred
  474.     ld    (iolen),hl
  475.     ld    de,(sec)
  476.     inc    de    ;advance current sector
  477.     ld    (sec),de
  478.     ld    hl,(secl)
  479.     or    a,a    ;done with all sectors?
  480.     sbc    hl,de    ;exit with carry set if
  481.             ;done
  482.     ret
  483.     form
  484. ;
  485. ; set up buffer with test pattern
  486. ;
  487. bufpat            ;call hl=address of base
  488.             ;        of buffer
  489.             ;     de=byte length of
  490.             ;        area to set up
  491.     ld    a,(lockpt)
  492.     or    a,a    ;are we locked on user
  493.             ;specified data pattern?
  494.     jr    nz,bufpa2;yes,jump
  495. bufpa1    ld    a,r    ;read refresh register
  496.     xor    a,h
  497.     add    a,l
  498.             ;make data a function of
  499.             ;memory address
  500.     ld    (hl),a    ;and store it
  501.     inc    hl    ;advance buffer address
  502.     dec    de    ;count bytes stored
  503.     ld    a,d    ;done yet?
  504.     or    a,e
  505.     jr    nz,bufpa1 ;no,loop
  506.     ret
  507.             ;user specified pattern
  508. bufpa2    ld    a,(pattrn)
  509.     ld    (hl),a     ;store one byte
  510.     inc    hl    ;advance buffer address
  511.     dec    de    ;count bytes stored
  512.     ld    a,d    ;done yet?
  513.     or    a,e
  514.     jr    nz,bufpa2 ;not done,loop
  515.     ret        ;exit
  516.             ;
  517.     form
  518. ;
  519. ;
  520. ; compare specified buffer and print error
  521. ; message if difference found
  522. ;
  523. bufcmp            ;compare buffers
  524.             ;
  525.             ;call bc=address of
  526.             ;        error message
  527.             ;     de=address 1st buffer
  528.             ;     hl=address 2nd buffer
  529.             ;
  530.     ld    (bufcma),bc ;save msg address
  531.     ld    (bufcmb),hl ;save base of buffer
  532.     ld    bc,(iolen)  ;length to compare
  533. bufcm1    ld    a,(de)    ;fetch byte from 1st buffer
  534.     cp    a,(hl)    ;compare it to 2nd buffer
  535.     jr    nz,bufcm3 ;difference found,jump
  536. bufcm2    inc    hl    ;advance buffer addresses
  537.     inc    de
  538.     dec    bc    ;count bytes
  539.     ld    a,b    ;done yet?
  540.     or    a,c
  541.     jr    nz,bufcm1 ;no,loop
  542.     ret        ;back to caller
  543.             ;
  544. bufcm3            ;difference found, print
  545.             ;error audit trail
  546.     push    bc    ;first save registers
  547.     push    de
  548.     push    hl
  549.     ld    de,(bufcmb)
  550.     or    a,a
  551.     sbc    hl,de    ;find a buffer offset
  552.     push    hl    ;now divide by bytes per
  553.     pop    bc    ;sector to find relative
  554.     ld    de,$bps    ;sector number
  555.     call    div
  556.     ld    hl,(secf)
  557.     add    hl,bc    ;add relative sector to
  558.             ;first sector to find
  559.             ;actual address for use
  560.             ;by PERR
  561.     ld    (sec),hl
  562.     ld    de,(bufcma)
  563.     call    perr    ;now audit error
  564.     pop    hl    ;restore registers
  565.     pop    de
  566.     pop    bc
  567. bufcm4            ;advance memory address
  568.             ;out of this sector where
  569.             ;an error was found.
  570.     inc    hl    ;bump buffer addresses
  571.     inc    de
  572.     dec    bc    ;done with all data area?
  573.     ld    a,b
  574.     or    a,c
  575.     ret    z    ;yes,exit compare routine
  576.     ld    a,l    ;check if on new sector  
  577.     and    $bps-1    ;boundary
  578.     jr    z,bufcm1;found it, go compare
  579.             ;more data
  580.     jr    bufcm4    ;keep advancing until
  581.             ;sector boundary.
  582.             ;
  583. bufcma    dw    0    ;address of error message
  584. bufcmb    dw    0    ;base buffer address
  585.     form
  586. perr            ;error printing routine,
  587.             ;prints pass,drive,track,
  588.             ;sector, and message
  589.             ;specified by caller on
  590.             ;console or list device.
  591.             ;
  592.             ; call with de=address
  593.             ;   of message giving
  594.             ;   type of error
  595.             ;
  596.     ld    a,(bypass)
  597.     or    a,a    ;is error itemization
  598.             ;bypass flag set?
  599.     jr    nz,perr2;yes,skip printing
  600.             ;and go count errors
  601.     ld    (perra),de ;save message addr.
  602.     ld    bc,(pass)
  603.     inc    bc
  604.     ld    hl,perrc;convert current pass
  605.     call    conv
  606.     ld    a,(drv) ;form drive name
  607.     add    'A'
  608.     ld    (perrd),a
  609.     ld    bc,(trk);convert current track
  610.     ld    hl,perre
  611.     call    conv
  612.     ld    bc,(sec);convert current sector
  613.     ld    a,(skew);is skew in effect?
  614.     or    a,a
  615.     jr    z,perr0    ;no
  616.     call    sectran    ;yes, translate sector
  617. perr0    ld    hl,perrf
  618.     call    conv
  619.     ld    a,(list);should output be on
  620.     or    a,a    ;console or printer?
  621.     jr    nz,perr3;jump,use printer
  622.             ;fall thru,use console
  623.     ld    hl,(errors)
  624.     ld    a,h    ;is this first error?
  625.     or    a,l
  626.     jr    nz,perr1;no,jump
  627.     ld    de,dtstq;print title for errors
  628.     ld    c,9
  629.     call    cpm
  630. perr1    ld    de,perrb;print disk address
  631.     ld    c,9
  632.     call    cpm
  633.     ld    de,(perra)
  634.     ld    c,9    ;print error type
  635.     call    cpm
  636.             ;
  637. perr2            ;count errors
  638.     ld    hl,(errors)
  639.     inc    hl
  640.     ld    (errors),hl
  641.     ret        ;back to caller
  642.             ;
  643. perr3            ;errors to printer
  644.     ld    hl,(errors)
  645.     ld    a,h    ;is this 1st error to
  646.     or    a,l    ;be printed this pass?
  647.     jr    nz,perr4;no,jump
  648.     ld    hl,dtstq;yes,print title
  649.     call    perr9
  650. perr4    ld    hl,perrb;print disk address
  651.     call    perr9
  652.     ld    hl,(perra)
  653.     call    perr9    ;print error type
  654.     jr    perr2    ;go count errors
  655.             ;
  656. perr9            ;send a string 
  657.             ;terminated by '$'
  658.             ;to list device
  659.     ld    a,(hl)    ;fetch next char
  660.     cp    a,'$'    ;is it terminator?
  661.     ret    z    ;yes,exit
  662.     push    hl    ;save string addr.
  663.     ld    e,a    ;send this character
  664.     ld    c,5
  665.     call    cpm
  666.     pop    hl    ;restore string addr
  667.     inc    hl    ;and increment it
  668.     jr    perr9    ;check next char.
  669.             ;
  670. perra    dw    0    ;addr of message
  671.             ;describing error type
  672. perrb    db    cr,lf
  673. perrc    db    'nnnn    ' ;pass #
  674. perrd    db    'n     '   ;drive
  675. perre    db    'nnnn   '  ;track
  676. perrf    db    'nnnn   $' ;sector
  677. ;
  678.     form
  679. ;
  680. ;
  681. ; disk interface to CP/M BIOS
  682. ;
  683. seldsk    ld    a,(drv)    ;select disk drive
  684.     ld    c,a
  685.     ld    de,24
  686.             ;this routine links
  687.             ;to the desired routine
  688.             ;through the standard
  689.             ;CP/M BIOS jump table
  690. jpbios    ld    hl,(wboot+1)
  691.     add    hl,de
  692.     jp    (hl)
  693. ;
  694. settrk    ld    bc,(trk);select track
  695.     ld    de,27
  696.     jr    jpbios
  697. ;
  698. setsec    ld    bc,(sec);select sector
  699.     ld    de,30
  700.     ld    a,(skew);use sector skew?
  701.     or    a,a
  702.     jr    z,jpbios;no
  703.     call    sectran ;translate sector addr.
  704.     jr    jpbios
  705. ;
  706. setdma    ld    bc,(buffer) ;set memory addr.
  707.     ld    de,33
  708.     jr    jpbios
  709. ;
  710. setio    call    settrk    ;set up track,sector,
  711.     call    setsec    ;and memory address
  712.     call    setdma    ;for subsequent read
  713.     ret        ;or write
  714. ;
  715. read            ;read one disk sector
  716.     ld    de,36
  717.     jr    jpbios
  718. ;
  719. write            ;write one disk sector
  720.     ld    de,39
  721.     jr    jpbios
  722. ;
  723. sectran            ;translate logical to
  724.             ;physical sector number
  725.             ;
  726.             ;call bc=logical sector
  727.             ;return bc=physical sector
  728.     push    hl
  729.     ld    hl,sectrb-1
  730.     add    hl,bc
  731.     ld    c,(hl)
  732.     pop    hl
  733.     ret
  734. sectrb    db    1,4,7,10,13    ;table built
  735.     db    16,19,22,25,2    ;with skew
  736.     db    5,8,11,14,17,20    ;factor =3
  737.     db    23,26,3,6,9,12
  738.     db    15,18,21,24
  739.     form
  740. ;
  741. ; messages for test initialization and
  742. ; error printing
  743. ;
  744. dtsta    db    cr,lf,lf
  745.     db    'Z-80 Floppy Disk '
  746.     db    'Test version '
  747.     db    $ver+'0','.'
  748.     db    $rev+'0',cr,lf
  749.     db    '(c) 1980 Laboratory '
  750.     db    'Microsystems',cr,lf,'$'
  751. dtstb    db    cr,lf,'Itemize '
  752.     db    'errors?    $'
  753. dtstc    db    cr,lf,'Use '
  754.     db    'console or printer'
  755.     db    '? (C/P) $'
  756. dtstd    db    cr,lf,'Lock on read '
  757.     db    'or write? (N/R/W) $'
  758. dtste    db    cr,lf,'Restore '
  759.     db    'original data? $'
  760. dtstf    db    cr,lf,'Lock on '
  761.     db    'data pattern? $'
  762. dtstg    db    cr,lf,'Enter data '
  763.     db    'pattern, hex 00-FF$'
  764. dtsth    db    cr,lf,'Drive '
  765.     db    'to be tested '
  766.     db    '(',$drvf+'A','-'
  767.     db    $drvl+'A',') $'
  768. dtsti    db    cr,lf,'Confirm: test drive '
  769. dtsti1    db    'X ? $'
  770. dtstj    db    cr,lf,'Test all '
  771.     db    'tracks?    $'
  772. dtstk    db    cr,lf,'First '
  773.     db    'track to test      $'
  774. dtstl    db    cr,lf,'Last '
  775.     db    'track to test      $'
  776. dtstm    db    cr,lf,'Test all '
  777.     db    'sectors?    $'
  778. dtstn    db    cr,lf,'First '
  779.     db    'sector to test    $'
  780. dtsto    db    cr,lf,'Last '
  781.     db    'sector to test     $'
  782. dtstp    db    cr,lf,'How many '
  783.     db    'test passes?    $'
  784. dtstq    db    cr,lf,lf,'Pass  '
  785.     db    'Drive  Track  '
  786.     db    'Sector  Error-type'
  787.     db    cr,lf,'$'
  788. dtstr    db    cr,lf,lf,'Pass '
  789. dtstr1    db    'nnnn complete, '
  790. dtstr2    db    'nnnn errors.'
  791.     db    cr,lf,'$'
  792. dtsts    db    cr,lf,'Not enough '
  793.     db    'memory to execute.'
  794.     db    cr,lf,'$'
  795. dtstt    db    cr,lf,lf,'Beginning '
  796.     db    'disk test - push '
  797.     db    'any key to abort '
  798.     db    'program.',cr,lf,'$'
  799. dtstu    db    'Warning: user '
  800.     db    'data will not be '
  801.     db    'restored.',cr,lf,'$'
  802. dtstv    db    'User data will be '
  803.     db    'restored.',cr,lf,'$'
  804. dtstw    db    cr,lf,'Continue or '
  805.     db    'exit test? (C/E)$'
  806. dtstx    db    cr,lf,lf
  807.     db    'Goodbye.',cr,lf,'$'
  808. dtsty    db    cr,lf,'Use sector '
  809.     db    'skew?  $'
  810. dtstz    db    cr,lf,'Need CP/M 2.x '
  811.     db    'to execute.',cr,lf,'$'
  812. ;
  813. ;
  814. merr1    db    'read error - original data$'
  815. merr2    db    'write error - test pattern$'
  816. merr3    db    'read error - test pattern$'
  817. merr4    db    'compare error - test pattern$'
  818. merr5    db    'original data cannot '
  819.     db    'be restored$'
  820. merr6    db    'write error - restore phase$'
  821. merr7    db    'read error - restore phase$'
  822. ;
  823.     form
  824. ;
  825. ;
  826. ; utility and console input routines
  827. ;
  828. getyn            ;get y or n response
  829.             ;from operator.
  830.             ;
  831.             ;call de=address of cue
  832.             ;return acc=y or n
  833.     push    de    ;save cue address
  834.     ld    c,9    ;print cue message
  835.     call    cpm
  836.     ld    de,getyna
  837.     ld    c,9    ;print possible answers
  838.     call    cpm
  839.     call    getchar    ;get a character
  840.             ;from console
  841.     or    a,20h    ;fold to lower case
  842.     pop    de    ;restore cue address
  843.             ;in case needed again
  844.     cp    'y'    ;make sure response
  845.             ;is ok
  846.     ret    z    ;exit if y
  847.     cp    'n'
  848.     ret    z    ;exit if n
  849.     push    de
  850.     call    query    ;print question mark if
  851.     pop    de    ;not y or n, try again
  852.     jr    getyn    ;
  853. getyna    db    '(Y/N) ',tab,'> $'
  854. ;
  855. ;
  856. getl            ;get any letter response
  857.             ;from operator.
  858.             ;
  859.             ;call de=address of cue
  860.             ;return acc=ASCII char.
  861.     ld    c,9    ;print cue message
  862.     call    cpm
  863.     ld    de,getla;tab and print 
  864.     ld    c,9    ;cue mark
  865.     call    cpm
  866.     call    getchar    ;read console
  867.     or    a,20h    ;fold to lower case
  868.     ret
  869. getla    db    tab,'> $'
  870. ;
  871. ;
  872. getn            ;get a decimal number 
  873.             ;from the console.
  874.             ;
  875.             ;call de=address of cue
  876.             ;return hl=number
  877.     push    de    ;save cue message address
  878.             ;in case needed later
  879.     ld    c,9
  880.     call    cpm    ;print cue message
  881.     ld    de,getna;print tab and cue mark
  882.     ld    c,9
  883.     call    cpm
  884.     ld    hl,0    ;initialize forming
  885.             ;answer
  886.     ld    a,(digits)
  887.     ld    b,a    ;total characters allowed
  888.             ;to be input
  889. getn1    push    hl    ;save answer
  890.     push    bc    ;save char. count
  891.     call    getchar    ;read console
  892.     pop    bc    ;restore char. count
  893.     pop    hl    ;restore forming answer
  894.     cp    cr    ;is this return?
  895.     jr    z,getn9    ;yes,exit with answer
  896.     cp    '0'    ;is this legal char.?
  897.     jr    c,getn3    ;no, jump
  898.     cp    '9'+1    ;is this legal char.?
  899.     jr    nc,getn3;no,jump
  900.     and    0fh    ;isolate bottom 4 bits
  901.             ;previous data * 10
  902.     push    hl
  903.     pop    de
  904.     add    hl,hl    ;(*2)
  905.     add    hl,hl    ;(*4)
  906.     add    hl,de    ;(*5)
  907.     add    hl,hl    ;(*10)
  908.     ld    e,a    ;now add in this digit
  909.     ld    d,0
  910.     add    hl,de
  911.     djnz    getn1    ;count characters accepted
  912.     jr    getn9    ;enough accepted,exit
  913. getn3            ;illegal character detected.
  914.     call    query    ;print question mark and
  915.     pop    de    ;restart input
  916.     jr    getn
  917. getn9            ;input complete,clean
  918.             ;stack and exit with
  919.             ;answer in (hl)
  920.     pop    de
  921.     ret
  922. getna    db    tab,'> $'
  923. getnb    db    '?$'
  924. ;
  925. ;
  926. geth            ;get $dig hex digits
  927.             ;from keyboard
  928.             ;
  929.             ;call de=addr of cue
  930.             ;return acc=lower 8 bits
  931.             ;     of entered number,
  932.             ;     hl=entire 16 bit no.
  933.             ;
  934.     push    de    ;save cue address
  935.             ;in case needed again
  936.     ld    c,9
  937.     call    cpm    ;print cue message
  938.     ld    de,getha;print tab and cue mark
  939.     ld    c,9
  940.     call    cpm
  941.     ld    hl,0    ;initialize forming
  942.             ;answer
  943.     ld    a,(digits)
  944.     ld    b,a    ;max digits to accept
  945. geth1    push    bc    ;save registers
  946.     push    hl
  947.     call    getchar    ;read console
  948.     pop    hl
  949.     pop    bc    ;restore registers
  950.     cp    cr    ;if carriage return exit
  951.     jr    z,geth25
  952.     cp    '0'    ;make sure its legal
  953.     jr    c,geth3 ;no,jump
  954.     cp    '9'+1    ;if alpha fold to
  955.     jr    c,geth15;lower case
  956.     or    20h
  957. geth15    cp    'f'+1    ;make sure its legal
  958.     jr    nc,geth3;no,jump
  959.     cp    'a'    ;check if alpha
  960.     jr    c,geth2 ;jump if 0-9
  961.     add    9    ;add correction
  962. geth2    and    0fh
  963.     add    hl,hl    ;previous data *16
  964.     add    hl,hl    ;(left shift 4 bits)
  965.     add    hl,hl
  966.     add    hl,hl
  967.     add    a,l    ;add this char. to
  968.     ld    l,a    ;forming result
  969.     djnz    geth1    ;keep reading console
  970. geth25    pop    de    ;clean up stack
  971.     ld    a,l    ;put lower 8 bits
  972.             ;of answer in acc.
  973.             ;(in case exit by
  974.             ; carriage return)
  975.     ret
  976. geth3    call    query   ;print question mark
  977.     pop    de    ;then restart input
  978.     jr    geth
  979. getha    db    tab,'> $'
  980. ;
  981. ;
  982. query    push    af    ;save flags
  983.     ld    c,9    ;print question mark
  984.     ld    de,querya
  985.     call    cpm
  986.     pop    af    ;restore flags
  987.     ret
  988. querya    db    ' ?$'
  989. ;
  990. ;
  991. getchar            ;get 1 character from
  992.             ;console via raw input
  993.             ;mode.  do not echo a
  994.             ;carriage return.
  995.     ld    e,0ffh
  996.     ld    c,6
  997.     call    cpm    ;read console
  998.     or    a,a    ;anything there?
  999.     jr    z,getchar ;no,try again
  1000.     cp    cr    ;is it a carriage return?
  1001.     ret    z    ;yes
  1002.     push    af    ;no,echo it
  1003.     ld    e,a
  1004.     ld    c,6
  1005.     call    cpm
  1006.     pop    af    ;restore acc. and exit
  1007.     ret
  1008. ;
  1009. ;
  1010. conv            ;convert binary to
  1011.             ;decimal ascii
  1012.             ;
  1013.             ;call bc=binary data, in
  1014.             ;        range 0000-9999.
  1015.             ;     hl=first byte addr
  1016.             ;     to store output
  1017.             ;
  1018.     ld    de,1000
  1019.     call    div
  1020.     call    conv9    ;thousands digit
  1021.     ld    de,100
  1022.     call    div
  1023.     call    conv9    ;hundreds digit
  1024.     ld    de,10
  1025.     call    div
  1026.     call    conv9    ;tens digit
  1027.     call    conv9    ;units
  1028.     ret        ;back to caller
  1029. conv9    ld    a,c    ;turn quotient into
  1030.     add    '0'    ;ASCII character
  1031.     ld    (hl),a    ;and store it 
  1032.     inc    hl    ;bump output pointer
  1033.     push    de    ;bc <- remainder
  1034.     pop    bc
  1035.     ret
  1036. ;
  1037. ;
  1038. div            ;single precision divide
  1039.             ;call bc=numerator
  1040.             ;     de=divisor
  1041.             ;return bc=quotient
  1042.             ;     de=remainder
  1043.     push    hl
  1044.     ld    hl,0
  1045.     or    a,a
  1046.     sbc    hl,de
  1047.     ex    de,hl
  1048.     ld    hl,0
  1049.     ld    a,17
  1050. div0    push    hl
  1051.     add    hl,de
  1052.     jr    nc,div1
  1053.     ex    (sp),hl
  1054. div1    pop    hl
  1055.     push    af
  1056.     rl    c
  1057.     rl    b
  1058.     rl    l
  1059.     rl    h
  1060.     pop    af
  1061.     dec    a
  1062.     jr    nz,div0
  1063.     or    a,a
  1064.     rr    h
  1065.     rr    l
  1066.     ex    de,hl
  1067.     pop    hl
  1068.     ret
  1069. ;
  1070. ;
  1071. buff1    equ    1000h    ;disk buffers
  1072. buff2    equ    $bpt*2+buff1
  1073. buff3    equ    $bpt*2+buff2
  1074. buffend    equ    $bpt*2+buff3
  1075. ;
  1076. ;
  1077.     end    100h
  1078.