home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / MBUG / MBUG097.ARC / FL512.MAC < prev    next >
Text File  |  1979-12-31  |  12KB  |  535 lines

  1.     .Z80
  2.  
  3. ; DOUBLE DENSITY disk package for 512k BIOS
  4.  
  5. MILLISEC    equ    122        ;3.375 Mhz only
  6. ; This should be the value to set the number of retries.
  7. RTCNT    equ    25    ;50        ;retry count (or 25)
  8. DS_RETRY    equ    4        ;# times to try read addr.
  9. CMND    equ    044H        ;WD1793/97 FDC
  10. STATUS    equ    cmnd
  11. TRACK    equ    cmnd+1
  12. SECTOR    equ    cmnd+2
  13. DATA    equ    cmnd+3
  14. DRQ    equ    048H
  15. DRIVES    equ    drq
  16. DDEN_SEL    equ    3        ;bits on the (drives) port
  17. SIDE_SEL    equ    2
  18. TTD    equ    3        ;30 Ms for restore only
  19. TRKPD    equ    40        ;40 cylinders
  20.  
  21. INT_CMND    equ    0D0H        ;force interrupt
  22. RA_CMND    equ    0C0H        ;read address command
  23. SEEK_CMND    equ    01cH        ;seek, hld, verify
  24. STPIN_CMND    equ    058H        ;stpin, update, hld, no verify
  25.  
  26. ; the read and write commmands assume disks formatted with
  27. ; the side byte zero on both sides - this allows both
  28. ; 1/2793 and 1/2797 controller chips to be used
  29. RD_CMND    equ    088H            ;read 1 sector, no HLD wait
  30. WR_CMND    equ    0A8H            ;write 1 sector, no HLD wait
  31. ;
  32. ; assuming c=drq, this macro will wait for the DRQ
  33. ; flag from the FDC
  34.     idrqwait    macro
  35.     zdrqwait    defl    $
  36.     in    a,(c)
  37.     jp    p,zdrqwait
  38.     endm
  39. ;
  40.     odrqwait    macro
  41.     zdrqwait    defl    $
  42.     in    d,(c)
  43.     jp    p,zdrqwait
  44.     endm
  45. ;
  46. ; select drive (A), and set (sec_length) and (dden_byte)
  47. ; according to what type of disk is in the drive
  48. ; also correct track register
  49. ; return Z if O.K., NZ if drive won't select (no disk
  50. ; or no drive if unused drive_sels are connected to IP)
  51. SEL_FLOPPY:
  52.     push    bc
  53.     ld    (disk),a
  54.     ld    c,a            ;what is desired
  55.     ld    a,(dden_byte)
  56.     or    c
  57.     out    (drives),a        ;select drive,density
  58. ;
  59. ; don't bother checking whether there is a disk in the drive,
  60. ; because if we return an error, we would have to bomb the
  61. ; program anyway
  62.     call    d_int            ;force type I status
  63.     call    dense_sense        ;fix track, density, size
  64.     jr    z,fzz_aam
  65.     call    d_restore        ;in case off track, restore
  66.     call    dense_sense        ;and try again
  67. fzz_aam:
  68.     pop    bc
  69.     ret
  70.  
  71.  
  72. ; sense the density and sector length of the currently
  73. ; selected disk by retrying up to ds_retry times until a correct
  74. ; read is obtained (update track register if it is ok)
  75. DENSE_SENSE:    
  76.     push    bc
  77.     ld    b,ds_retry        ;ds_retry goes to get it right
  78. fz_a    defl    $
  79.     call    try_ra        ;read address, return Z/NZ
  80.     jr    z,fz_aaav
  81.     push    hl
  82.     ld    hl,dden_byte
  83.     ld    a,1 shl dden_sel
  84.     xor    (hl)        ;invert dden bit (swap modes)
  85.     ld    (hl),a
  86.     ld    a,(disk)
  87.     or    (hl)
  88.     out    (drives),a    ;tell controller
  89.     pop    hl
  90.     or    -1        ;set nz=error
  91.     djnz    fz_a
  92. fz_aaav:
  93.     pop    bc
  94.     ret
  95.  
  96.  
  97. ; try_ra tries to do a READ ADDRESS command and
  98. ; if successful, updates the sector length bytes and
  99. ; track register (in case of misseek)
  100. TRY_RA:
  101.     push    bc
  102.     push    de
  103. fz_a    defl    $
  104.     di            ;disable RS232 interrupts
  105.     out    (vwait_off),a    ;kill colour board
  106.     ld    a,ra_cmnd
  107.     call    cmnd_delay    ;give command, load head if necc.
  108.     ld    c,drq
  109.     idrqwait
  110.     in    a,(data)    ;get possible track number
  111.     ld    d,a
  112.     ld    b,3        ;read through side,sector,length
  113. fz_b    defl    $
  114.     idrqwait
  115.     in    a,(data)
  116.     djnz    fz_b
  117. fz_baaa:
  118.     ld    e,a        ;get poss. sector length byte
  119.     call    wbsy        ;wait till unbusy, get status
  120.     ei
  121.     and    098H
  122.     jr    nz,ra_ex    ;bad read, so exit early
  123.     ld    a,d        ;track number read from disk
  124.     out    (track),a    ;correct track register
  125.     cp    3        ;if >= track 3, continue
  126.     jr    nc,fz_aaaw
  127. ; step in a track to determine type correctly for foreign formats
  128.     ld    a,stpin_cmnd
  129.     call    cm_wrdy
  130.     jr    fz_a
  131. fz_aaaw:
  132. ; no problems, so update track, sec_length, and # pair of bytes
  133.     ld    a,e
  134.     ld    (sec_length),a        ;sector length 0=128, 2=512
  135. ; this does not work for 1024 byte sectors ..
  136.     ld    a,1 shl 5
  137. fz_a    defl    $
  138.     rla
  139.     dec    e
  140.     jp    p,fz_a
  141. fz_aaax:
  142.     ld    (num_pairs),a
  143.     cp    a
  144. ; .. Z flag is true
  145. RA_EX:    
  146.     pop    de
  147.     pop    bc
  148.     ret
  149.  
  150.  
  151. ; setup for read or write ...
  152. ; given d=track with b7=1 for side 1, e=sector,
  153. ; try to seek to correct position, if O.K., return
  154. ; Z, otherwise return NZ if seek error
  155. ; also return b=# pairs of bytes to read, c=drq
  156. SETUP:    
  157.     out    (vwait_off),a    ;disable screen waiting each line
  158.     push    de
  159.     ld    a,(disk)
  160.     ld    e,a
  161.     ld    a,(dden_byte)
  162.     or    e
  163.     ld    e,a        ;e = disk | dden_byte
  164.  
  165.     bit    7,d
  166.     jr    z,side0
  167.     res    7,d        ;and for physical track number
  168.     set    side_sel,e    ;set for side 1
  169. SIDE0:    
  170.     ld    a,e
  171.     out    (drives),a    ;set drive, side, density
  172. ;
  173.     in    a,(track)
  174.     cp    d        ;already there?
  175.     jr    z,fzz_aan
  176.     ld    a,d
  177.     out    (data),a    ;desired track
  178.     ld    a,seek_cmnd    ;seek with verify and hld at 6ms
  179.     call    cm_wrdy        ;and return status in a
  180.     ld    b,10
  181.     call    dely1        ;10 Ms head settle time
  182.     in    a,(status)
  183.     and    018H        ;did verify fail?
  184. fzz_aan:
  185. ; get # pairs of bytes to read or write in B
  186.     ld    a,(num_pairs)    ;quickest way to get it
  187.     ld    b,a
  188. ;
  189.     ld    c,drq        ;for ED70 loop
  190.     pop    de
  191.     ld    a,e        ;required sector
  192.     out    (sector),a
  193.     ret
  194. ;
  195. ;
  196. ; Read 'host' sector
  197. ; given ...
  198. ; drive number in 'drive'
  199. ; sector length in (sec_length)
  200. ; d=track, e=sector
  201. ; hl=data transfer address
  202. ;
  203. ; returns ..
  204. ; data at (hl) for 128*2^(sec_length) bytes
  205. ; hl=hl+128*2^(sec_length)
  206. ; a=0 (and Z) if no errors, else returns 1 (and NZ)
  207. ;
  208. RD_FLOPPY:    
  209.     push    bc
  210.     ld    b,rtcnt
  211. fz_a    defl    $
  212.     push    hl        ;save transfer address
  213.     push    bc        ;save error count-down
  214.     call    setup        ;seek, set sector, b=# pairs, c=drq
  215.     jr    nz,fzz_aao
  216.     di
  217.     ld    a,rd_cmnd    ;read, no wait cmnd
  218.     call    cmnd_delay    ;give command, wait for status valid
  219. fz_b    defl    $
  220.     idrqwait
  221.     in    a,(data)
  222.     ld    (hl),a
  223.     inc    hl
  224.     idrqwait
  225.     in    a,(data)
  226.     ld    (hl),a
  227.     inc    hl
  228.     djnz    fz_b
  229. fz_baab:
  230.     ei
  231.     call    wbsy        ;wait for unbusy, get status
  232.     and    09CH        ;relevant bits only
  233.     jr    nz,fzz_aao
  234.     pop    bc        ;pop off error count
  235.     pop    bc        ;pop off transfer address
  236.     pop    bc
  237.     ret            ;successful read exit
  238. fzz_aao:
  239.     pop    bc        ;reget error count in b
  240.     pop    hl        ;reget transfer address
  241.  
  242.     call    erchk        ;do dense_sense and restore sometimes
  243.     djnz    fz_a
  244. fz_aaay:
  245.     pop    bc
  246.     xor    a
  247.     inc    a
  248.     ret            ;unrecoverable error
  249. ;
  250. ;
  251. ; Write 'host' sector
  252. ; given ...
  253. ; drive number in 'drive'
  254. ; sector length in (sec_length)
  255. ; d=track, e=sector
  256. ; hl=data transfer address
  257. ;
  258. ; returns ..
  259. ; hl=hl+128*2^(sec_length)
  260. ; a=0 (and Z) if no errors, else returns 1 (and NZ)
  261. ;
  262. ; Write a sector
  263. WR_FLOPPY:    
  264.     push    bc
  265.     ld    b,rtcnt
  266. fz_a    defl    $
  267.     push    hl        ;save transfer address
  268.     push    bc        ;save error count-down
  269.     call    setup        ;seek, set sector, b=# pairs, c=drq
  270.     jr    nz,fzz_aap
  271.     di
  272.     push    de        ;save de since we must "in ?,(c)"
  273.     ld    a,wr_cmnd    ;write, no wait cmnd
  274.     call    cmnd_delay    ;give command, wait for status valid
  275. fz_b    defl    $
  276.     ld    a,(hl)
  277.     odrqwait
  278.     out    (data),a
  279.     inc    hl
  280.     ld    a,(hl)
  281.     odrqwait
  282.     out    (data),a
  283.     inc    hl
  284.     djnz    fz_b
  285. fz_baac:
  286.     ei
  287.     pop    de
  288.     call    wbsy        ;wait for unbusy, get status
  289.     and    0FDH        ;relevant bits only
  290.     jr    nz,fzz_aap
  291.     pop    bc        ;pop off error count
  292.     pop    bc        ;pop off transfer address
  293.     pop    bc
  294.     ret            ;successful write exit
  295. fzz_aap:
  296.     pop    bc        ;reget error count in b
  297.     pop    hl        ;reget transfer address
  298.     call    erchk        ;do dense_sense and restore sometimes
  299.  
  300.     djnz    fz_a
  301. fz_aaaz:
  302.     pop    bc
  303.     xor    a
  304.     inc    a
  305.     ret                ;unrecoverable error
  306. ;
  307. ; an error has occured, so
  308. ; home the head after every 8 retrys (b is counter)
  309. ; also STATUS is type I after this subroutine
  310. ; also update error count
  311. ERCHK:    
  312.     push    af
  313.     call    try_ra        ;try to read address, fix track reg ..
  314.     ld    a,7
  315.     and    b        ;restore every 8 retrys
  316.     call    z,d_restore    ;do a restore
  317.     call    d_int        ;force type I status (not read status)
  318. ; keep a count of total errors, stopping at 255
  319.     ld    a,(total_errs)
  320.     inc    a
  321.     jr    z,fzz_aaq
  322.     ld    (total_errs),a
  323. fzz_aaq:
  324.     pop    af
  325.     ret
  326. ;
  327. CMND_DELAY:    
  328.     out    (cmnd),a
  329. ; greater than 60uS delay at 2.25Mhz
  330. D_DELAY:    
  331.     ld    a,16
  332. fz_a    defl    $
  333.     dec    a
  334.     jr    nz,fz_a
  335. fz_aaba:
  336.     ret
  337. ;
  338. ; interrupt the FDC
  339. D_INT:    
  340.     ld    a,int_cmnd
  341.     jr    cm_wrdy
  342. ; restore to track zero
  343. D_RESTORE:    
  344.     ld    a,8+ttd        ;restore (slowly always)
  345. CM_WRDY:    
  346.     out    (cmnd),a
  347. DWRDY:    
  348.     call    d_delay
  349. WBSY:    
  350.     in    a,(status)
  351.     bit    0,a            ;check busy flag
  352.     jr    nz,wbsy        ;wait till not busy
  353.     ret
  354. ;
  355. ; delay for b milliseconds
  356. DELY1:    
  357.     push    hl
  358. DLY1LP:    
  359.     ld    hl,millisec
  360. DLY:    
  361.     dec    hl
  362.     ld    a,h
  363.     or    l
  364.     jr    nz,dly
  365.     djnz    dly1lp
  366.     pop    hl
  367.     ret
  368. ;
  369. ;
  370. ; a routine which loads consecutive sectors into memory for
  371. ; a specified number of bytes
  372. ;
  373. ; Requires no. bytes to load in BC
  374. ; destination of load in HL
  375. ; D=starting track no 0-79
  376. ; E=starting sector no 1-?
  377. ;  returns Z if OK, NZ if a bad read occured
  378. ;
  379. ;OFFLOAD:    
  380. ;    push    ix
  381. ;    push    iy
  382. ;;
  383. ;    push    hl
  384. ;    pop    ix
  385. ;    add    ix,bc
  386. ;    call    get_tab        ;address of sectors per track in iy
  387. ;    ld    b,5            ;number of retries
  388. ;fz_a    defl    $
  389. ;    push    bc        ;save #retries left
  390. ;    push    de        ;save initial track/sector
  391. ;    push    hl        ;save initial address
  392. ;fz_b    defl    $
  393. ;    call    setup        ;seek and set init. sector reg.
  394. ;    jr    nz,fz_baad
  395. ;    di            ;kill RS232 ints
  396. ;    ld    a,rd_cmnd+010H    ;multiple sec read
  397. ;    call    cmnd_delay        ;ensure head loaded (& motor)
  398. ;fz_c    defl    $
  399. ;    ld    a,(num_pairs)
  400. ;    ld    b,a
  401. ;    ld    c,drq        ;port with drq bit 7
  402. ;fz_d    defl    $
  403. ;    idrqwait
  404. ;    in    a,(data)
  405. ;    ld    (hl),a
  406. ;    inc    hl
  407. ;    idrqwait
  408. ;    in    a,(data)
  409. ;    ld    (hl),a
  410. ;    inc    hl
  411. ;    djnz    fz_d
  412. ;fz_daaa:
  413. ;    push    ix
  414. ;    pop    bc
  415. ;    push    hl
  416. ;    and    a        ;clear carry
  417. ;    sbc    hl,bc
  418. ;    pop    hl
  419. ;    jr    nc,qr_exit    ;don't need any more sectors
  420. ;;
  421. ;    ld    a,e
  422. ;    inc    e
  423. ;    cp    (iy+0)    ;number of sectors per track
  424. ;    jr    nz,fz_c
  425. ;fz_caaa:
  426. ;    ld    b,3
  427. ;    call    dely1            ;wait for busy status valid
  428. ;    in    a,(status)
  429. ;    cpl    
  430. ;    bit    0,a
  431. ;    jr    nz,fz_baad
  432. ;;
  433. ;    call    d_int            ;kill track read
  434. ;    ld    e,1
  435. ;    inc    d            ;next track
  436. ;    jr    fz_b
  437. ;fz_baad:
  438. ;    pop    hl            ;start address
  439. ;    pop    de            ;starting track, sector
  440. ;    pop    bc            ;number of retries
  441. ;    djnz    fz_a
  442. ;fz_aabb:
  443. ;QR_PX:    
  444. ;    ei
  445. ;    pop    iy
  446. ;    pop    ix
  447. ;    ret    nz            ;if stopped for error
  448. ;    call    d_int            ;kill multi-sector read
  449. ;    and    09CH            ;relevant bits only
  450. ;    ret
  451. ;QR_EXIT:    
  452. ;    pop    hl
  453. ;    pop    de
  454. ;    pop    bc
  455. ;    xor    a            ;set z flag -> check status reg.
  456. ;    jr    qr_px
  457. ;;
  458. ;
  459. ; a routine which stores consecutive sectors onto disk for
  460. ; a specified number of bytes (taken up to next sector length)
  461. ;
  462. ; Requires no. bytes to save in BC
  463. ; source of load in HL
  464. ; D=starting track no 0-79
  465. ; E=starting sector no 1-?
  466. ;  returns Z if OK, NZ if a bad write occured
  467. ;blockwrite
  468. ;    push    iy
  469. ;    push    hl
  470. ;    add    hl,bc
  471. ;    ld    b,h        ;bc=byte after last byte to read
  472. ;    ld    c,l
  473. ;    call    get_tab    ;get address of sectors per track
  474. ;    pop    hl
  475. ;    {
  476. ;        call    wr_floppy
  477. ;        #if    nz,brk    ;bad sector read
  478. ;        ld    a,e
  479. ;        inc    e
  480. ;        cp    (iy+0)    ;overflow off track?
  481. ;        #if    c,nxt
  482. ;        inc    d        ;next track
  483. ;        ld    e,1        ;first sector
  484. ;    #mark
  485. ;        push    hl
  486. ;        and    a        ;clear carry
  487. ;        sbc    hl,bc
  488. ;        pop    hl
  489. ;        #if    c,cont
  490. ;        cp    a        ;set Z flag
  491. ;    }
  492. ;    pop    iy
  493. ;    ret
  494. ;
  495. ;
  496. ; return iy pointing to byte containing the number
  497. ; of sectors per track for a disk formatted in the
  498. ; current format
  499. GET_TAB:    
  500.     push    hl
  501.     ld    hl,dden_byte
  502.     ld    a,(sec_length)    ;0=128, 1=256, 2=512
  503.     rlca            ;*2
  504.     bit    dden_sel,(hl)    ;is it single density?
  505.     pop    hl
  506.     jr    z,fzz_aar
  507.     dec    a        ;double density
  508. fzz_aar:
  509.     ld    iy,max_sects    ;default to 18 if too big or small
  510.     ret    m        ;and NZ if 128 byte DD !
  511.     bit    2,a        ;too big if 512 SD, or 1024 SD&DD
  512.     ret    nz
  513.     push    de
  514.     ld    d,0
  515.     ld    e,a
  516.     add    iy,de
  517.     pop    de
  518.     ret
  519. ;
  520. ;
  521. ; a table of the maximum number of sectors per
  522. ; track for the 4 supported formats
  523. MAX_SECTS:    
  524.     defb    18        ;SD 128 bytes    (old sd format)
  525.     defb    18        ;DD 256 bytes    (mos)
  526.     defb    10        ;SD 256 bytes    (osborne)
  527.     defb    10        ;DD 512 bytes    (main DD format)
  528.  
  529.  
  530. DISK:    defb    0    ;currently selected disk
  531. SEC_LENGTH:    defb    2    ;0=128, 1=256, 2=512
  532. NUM_PAIRS:    defb    1    ;# pairs of byte to xfer
  533. TOTAL_ERROR:    defb    0    ;total r/w errors so far
  534. DDEN_BYTE:    defb    08H    ;=08H if double density selected
  535.