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 / ENTERPRS / CPM / UTILS / A / BIOS2RSX.LZH / BIOS2RSX.ASM next >
Assembly Source File  |  1991-01-16  |  12KB  |  540 lines

  1. ;
  2.     title    'CP/M 2.2 BIOS RSX'
  3. ;
  4. ;    18Jan84        By Mike Griswold
  5. ;
  6. ;    This RSX will provide CP/M 2.2 compatible BIOS support
  7. ;    for CP/M 3.x.  Primarily it performs logical sector
  8. ;    blocking and deblocking needed for some programs.
  9. ;    All actual I/O is done by the CP/M 3.0 BIOS.
  10. ;
  11. ; Typed in from the Dr. Dobb's Journal article in the July 84
  12. ;  issue.                    mabry
  13. ;
  14. ; Modified 9 July 1984 to run on an 8085 rather than just a Z80 !
  15. ;  Also added trap for BDOS call 12 (version number) and returns
  16. ;  the indication that the calling program is running under
  17. ;  version 2.2 of CP/M.  This is necessary for programs that
  18. ;  are written to trap a CP/M Plus environment but not able to
  19. ;  handle the physical sector I/O of a CP/M Plus BIOS.
  20. ;                        mabry
  21. ;
  22.     cseg
  23. ;
  24. ;    This equate is the only hardware dependent value.
  25. ;    It should be set to the largest sector size that
  26. ;    will be used.
  27. ;
  28. max$sector$size:    equ    256
  29.  
  30. cr    equ    0dh
  31. lf    equ    0ah
  32. ;
  33. ;
  34. ;    RSX prefix structure
  35. ;
  36.     db    0,0,0,0,0,0
  37. entry:    jmp    boot
  38. next:    db    jmp        ; jump
  39.     dw    0        ; next module in line
  40. prev:    dw    0        ; previous module
  41. remove:    db    0ffh        ; remove flag
  42. nonbmk:    db    0
  43.     db    'BIOS2.21'
  44.     db    0,0,0
  45. ;
  46. ;    The CP/M 3.0 BIOS jump table is copied here
  47. ;    to allow easy access to 1st routines.  The disk
  48. ;    I/O routines are potentially in banked memory
  49. ;    so they cannot be called directly.
  50. ;
  51. xwboot:    jmp    0        ; warm boot
  52. xconst:    jmp    0
  53. xconin:    jmp    0
  54. xconout:jmp    0
  55. xlist:    jmp    0
  56. xauxout:jmp    0
  57. xauxin:    jmp    0
  58.     jmp    0
  59.     jmp    0
  60.     jmp    0
  61.     jmp    0
  62.     jmp    0
  63.     jmp    0
  64.     jmp    0
  65. xlistst:jmp    0
  66. ;
  67. ;    Signon message
  68. ;
  69. signon:    db    cr,lf,'BIOS ver 2.21 ACTIVE',cr,lf,0
  70. ;
  71. ;    Cold boot
  72. ;
  73. boot:    push    psw        ; a BDOS call is in progress, save cpu state
  74.     push    h        ;  so save cpu state
  75.     push    d
  76.     push    b
  77.     lda    first        ; is this the first time through ?
  78.     ora    a
  79.     jz    boot10        ; jump if no
  80.     xra    a        ; reset first time through flag
  81.     sta    first
  82.     call    init        ; initialize BIOS variables
  83.     lhld    1        ; save the CP/M 3.0 BIOS jump
  84.     shld    old$addr    ;  at location 0
  85.     lxi    d,xwboot    ; set up to move jump table
  86.     lxi    b,15*3        ; byte count
  87.  
  88. ;    ldir
  89. boot05:
  90.     mov    a,m
  91.     stax    d
  92.     inx    h
  93.     inx    d
  94.     dcr    c        ; This is cheating, but 15*3 < 256
  95.     jnz    boot05
  96.  
  97.     lxi    h,wbt        ; substitute new jump address
  98.     shld    1
  99.     lxi    h,signon    ; sound off
  100.     call    prmsg
  101. ;
  102. ; We check to see if CP/M version number is requested via BDOS
  103. ;  function 12.  If so, return 2.2.
  104. ;
  105. boot10:
  106.     mov    a,c        ; BDOS function number
  107.     cpi    12        ; version call ?
  108.     jnz    boot15        ; if no, then continue
  109.     pop    b
  110.     pop    d
  111.     pop    h
  112.     pop    psw
  113.     lxi    h,0022h        ; flag CP/M and version 2.2
  114.     ret
  115. boot15:
  116.     pop    b        ; restore BDOS call state
  117.     pop    d
  118.     pop    h
  119.     pop    psw
  120.     jmp    next        ; carry on
  121. ;
  122. ;    Warm boot
  123. ;
  124. wboot:    lhld    old$addr
  125.     shld    1        ; restore normal BIOS address
  126.     jmp    0        ; jump to CP/M 3.0 warm boot
  127. ;
  128. ;    Initialize BIOS internal variables for cold boot
  129. ;
  130. init:    xra    a
  131.     sta    hstwrt        ; host buffer written
  132.     sta    hstact        ; host buffer inactive
  133.     lxi    h,80h
  134.     shld    dmaadr
  135.     ret
  136. ;
  137. ;    Routine to call banked BIOS routines via BDOS
  138. ;    function 50.  All disk I.O calls are made through
  139. ;    here.
  140. ;
  141. xbios:    sta    biospb        ; set BIOS function
  142.     mvi    c,50        ; direct BIOS call function
  143.     lxi    d,biospb    ; BIOS parameter block
  144.     jmp    next        ; jump to BDOS
  145. ;
  146. biospb:    db    0        ; BIOS function
  147. areg:    db    0        ; A register
  148. bcreg:    dw    0        ; BC register
  149. dereg:    dw    0        ; DE register
  150. hlreg:    dw    0        ; HL register
  151. ;
  152. ;    Home disk.
  153. ;
  154. home:    lda    hstwrt        ; check if pending write
  155.     ora    a
  156.     cnz    writehst    ; dump buffer to disk
  157.     xra    a
  158.     sta    hstwrt        ; buffer written
  159.     sta    hstact        ; buffer inactive
  160.     sta    unacnt        ; zero alloc count
  161.     sta    sektrk        ; zero track count
  162.     sta    sektrk+1
  163.     ret
  164. ;
  165. ;    Set track.
  166. ;
  167. settrk:;sbcd    sektrk
  168.     mov    l,c        ; track number to HL
  169.     mov    h,b
  170.     shld    sektrk
  171.     ret
  172. ;
  173. ;    Align jump table on next page boundary.  This is needed
  174. ;    for programs that cheat when getting the addresses of
  175. ;    BIOS jump table entries.
  176. ;
  177.     ds    16
  178. ;
  179. ;    BIOS Jump Table
  180. ;
  181. cbt:    jmp    wboot        ; cold boot entry
  182. wbt:    jmp    wboot        ; warm boot entry
  183.     jmp    xconst        ; console status
  184.     jmp    xconin        ; console input
  185.     jmp    xconout        ; console output
  186.     jmp    xlist        ; list output
  187.     jmp    xauxout        ; aux device output
  188.     jmp    xauxin        ; aux device input
  189.     jmp    home        ; home disk head
  190.     jmp    seldsk        ; select drive
  191.     jmp    settrk        ; select track
  192.     jmp    setsec        ; select sector
  193.     jmp    setdma        ; set dma address
  194.     jmp    read        ; read a sector
  195.     jmp    write        ; write a sector
  196.     jmp    xlistst        ; list status
  197.     jmp    sectran        ; sector translation
  198. ;
  199. ;    Select disk.  Create a fake DPH for programs
  200. ;    that might use it.
  201. ;
  202. seldsk:    mov    a,c        ; requested drive number
  203.     sta    sekdsk
  204.     sta    bcreg        ; set C reg in BIOSPB
  205.     mvi    a,9        ; BIOS function number
  206.     call    xbios        ; CP/M 3.0 select
  207.     mov    a,h
  208.     ora    l        ; check for HL=0
  209.     rz            ; select error
  210.     mov    e,m        ; get address of xlat table
  211.     inx    h
  212.     mov    d,m
  213.     xchg
  214.     shld    xlat        ; save xlat address
  215.     lxi    h,11        ; offset to dpb address
  216.     dad    d
  217.     mov    e,m        ; fetch address of dpb
  218.     inx    h
  219.     mov    d,m
  220.     xchg
  221.     shld    dpb        ; address of dpb
  222.     mov    a,m        ; cpm sectors per track
  223.     sta    spt
  224.     inx    h
  225.     inx    h        ; point to block shift mask
  226.     inx    h
  227.     mov    a,m
  228.     sta    bsm        ; save block shift mask
  229.     lxi    d,12        ; offset to psh
  230.     dad    d
  231.     mov    a,m
  232.     sta    psh        ; save physical shift factor
  233.     lxi    h,dph        ; return DPH address
  234.     ret
  235. ;
  236. ;    This fake DPH holds the adresses of the actual
  237. ;    DPB.  The CP/M 3.0 DPH is *not* understood
  238. ;    by CP/M 2.2 programs.
  239. ;
  240. dph:    equ    $
  241.     dw    0        ; no translation
  242.     ds    6        ; scratch words
  243.     ds    2        ; directory buffer
  244. dpb:    ds    2        ; DPB
  245.     ds    2        ; CSV
  246.     ds    2        ; ALV
  247. ;
  248. ;    Set dma.
  249. ;
  250. setdma:;sbcd    dmaadr
  251.     mov    l,c        ; dma number to HL
  252.     mov    h,b
  253.     shld    dmaadr
  254.     ret
  255. ;
  256. ;    Translate sectors.  Sectors are not translated yet.
  257. ;    Wait until we know the physical sector number.
  258. ;    This works fine as long as the program trusts
  259. ;    the BIOS to do the translation.  Some programs
  260. ;    access the XLAT table directly to do their own
  261. ;    translation.  These programs will get the wrong
  262. ;    idea about the disk skew but it should cause no
  263. ;    harm.
  264. ;
  265. sectran:mov    l,c        ; return sector in HL
  266.     mov    h,b
  267.     ret
  268. ;
  269. ;    Set sector number.
  270. ;
  271. setsec:    mov    a,c
  272.     sta    seksec
  273.     ret
  274. ;
  275. ;    Read the selected CP/M sector.
  276. ;
  277. read:    mvi    a,1
  278.     sta    readop        ; read operation
  279.     inr    a        ; a=2 (wrual)
  280.     sta    wrtype        ; treat as unalloc
  281.     jmp    alloc        ; perform read
  282. ;
  283. ;    Write the selected CP/M sector.
  284. ;
  285. write:    xra    a
  286.     sta    readop        ; not a read operation
  287.     mov    a,c
  288.     sta    wrtype        ; save write type
  289.     cpi    2        ; unalloc block?
  290.     jnz    chkuna
  291. ;
  292. ;    Write to first sector of unallocated block.
  293. ;
  294.     lda    bsm        ; get block shift mask
  295.     inr    a        ; adjust value
  296.     sta    unacnt        ; unalloc record count
  297.     lda    sekdsk        ; set up values for
  298.     sta    unadsk        ;  writing to an unallocated
  299.     lda    sektrk        ;  block
  300.     sta    unatrk
  301.     lda    seksec
  302.     sta    unasec
  303. ;
  304. chkuna:    lda    unacnt        ; any unalloc sectors
  305.     ora    a        ;  in this block?
  306.     jz    alloc        ; skip if not
  307.     dcr    a        ; unacnt = unacnt - 1
  308.     sta    unacnt
  309.     lda    sekdsk
  310.     lxi    h,unadsk
  311.     cmp    m        ; sekdsk = unadsk ?
  312.     jnz    alloc        ; skip if not
  313.     lda    sektrk
  314.     lxi    h,unatrk
  315.     cmp    m        ; sektrk = unatrk ?
  316.     jnz    alloc        ; skip if not
  317.     lda    seksec
  318.     lxi    h,unasec
  319.     cmp    m        ; seksec = unasec ?
  320.     jnz    alloc        ; skip if not
  321.     inr    m        ; move to next sector
  322.     mov    a,m
  323.     lxi    h,spt        ; addr of spt
  324.     cmp    m        ; sector > spt ?
  325.     jc    noovf        ; skip if no overflow
  326.     lhld    unatrk
  327.     inx    h
  328.     shld    unatrk        ; bump rack
  329.     xra    a
  330.     sta    unasec        ; reset sector count
  331. noovf:    xra    a
  332.     sta    rsflag        ; don't pre-read
  333.     jmp    rwoper        ; perform write
  334. ;
  335. alloc:    xra    a        ; requires pre-read
  336.     sta    unacnt
  337.     inr    a
  338.     sta    rsflag        ; force pre-read
  339. ;
  340. rwoper:    xra    a
  341.     sta    erflag        ; no errors yet
  342.     lda    psh        ; get physical shift factor
  343.     ora    a        ; set flags
  344.     mov    b,a
  345.     lda    seksec        ; logical sector
  346.     lxi    h,hstbuf    ; addr of buffer
  347.     lxi    d,128
  348.     jz    noblk        ; no blocking
  349.     xchg            ; shuffle registers
  350. shift:    xchg
  351.     rrc
  352.     jnc    sh1
  353.     dad    d        ; bump buffer address
  354. sh1:    xchg
  355.     dad    h        ; double offset
  356.     ani    07fh        ; zero high bit
  357.  
  358. ;    djnz    shift
  359.     dcr    b
  360.     jnz    shift
  361.  
  362.     xchg            ; HL=buffer addr
  363. noblk:    sta    sekhst
  364.     shld    sekbuf
  365.     lxi    h,hstact    ; buffer active flag
  366.     mov    a,m
  367.     mvi    m,1        ; set buffer active
  368.     ora    a        ; was it already?
  369.     jz    filhst        ; fill buffer if not
  370.     lda    sekdsk
  371.     lxi    h,hstdsk    ; same disk ?
  372.     cmp    m
  373.     jnz    nomatch
  374.     lda    sektrk
  375.     lxi    h,hsttrk    ; same track ?
  376.     cmp    m
  377.     jnz    nomatch
  378.     lda    sekhst        ; same buffer ?
  379.     lxi    h,hstsec
  380.     cmp    m
  381.     jz    match
  382. ;
  383. nomatch:
  384.     lda    hstwrt        ; buffer changed?
  385.     ora    a
  386.     cnz    writehst    ; clear buffer
  387.  
  388. filhst:    lda    sekdsk
  389.     sta    hstdsk
  390.     lhld    sektrk
  391.     shld    hsttrk
  392.     lda    sekhst
  393.     sta    hstsec
  394.     lda    rsflag        ; need to read  ?
  395.     ora    a
  396.     cnz    readhst        ; yes
  397.     xra    a
  398.     sta    hstwrt        ; no pending write
  399. ;
  400. match:    lhld    dmaadr
  401.     xchg
  402.     lhld    sekbuf
  403.     lda    readop        ; which way to move ?
  404.     ora    a
  405.     jnz    rwmove        ; skip if read
  406.     mvi    a,1
  407.     sta    hstwrt        ; mark buffer changed
  408.     xchg            ; hl=dma  de=buffer
  409. ;
  410. rwmove:    lxi    b,128        ; byte count
  411.  
  412. ;    ldir            ; block move
  413. rwmv05:
  414.     mov    a,m
  415.     stax    d
  416.     inx    h
  417.     inx    d
  418.     dcr    c        ; This is cheating, but 128 < 256
  419.     jnz    rwmv05
  420.  
  421.     lda    wrtype        ; write type
  422.     cpi    1        ; to directory ?
  423.     jnz    exit        ; done
  424.     lda    erflag        ; check for errors
  425.     ora    a
  426.     jnz    exit        ; don't write dir if so
  427.     xra    a
  428.     sta    hstwrt        ; show buffer written
  429.     call    writehst    ; write buffer
  430. exit:    lda    erflag
  431.     ret
  432. ;
  433. ;    Disk read.  Call CP/M 3.0 BIOS to fill the buffer
  434. ;    with one physical sector.
  435. ;
  436. readhst:
  437.     call    rw$init        ; init CP/M 3.0 BIOS
  438.     mvi    a,13        ; read function number
  439.     call    xbios        ; read sector
  440.     sta    erflag
  441.     ret
  442. ;
  443. ;    Disk write.  Call CP/M 3.0 BIOS to write one
  444. ;    physical sector from buffer.
  445. ;
  446. writehst:
  447.     call    rw$init        ; init CP/M 3.0 BIOS
  448.     mvi    a,14        ; write function number
  449.     call    xbios        ; write sector
  450.     sta    erflag
  451.     ret
  452. ;
  453. ;    Translate sector.  Set CP/M 3.0 track, sector,
  454. ;    DMA buffer and DMA bank.
  455. ;
  456. rw$init:
  457.     lda    hstsec        ; physical sector number
  458.     mov    l,a
  459.     mvi    h,0
  460.     shld    bcreg        ; sector number in BC
  461.     lhld    xlat        ; address of xlat table
  462.     shld    dereg        ; xlat address in DE
  463.     mvi    a,16        ; sectrn function number
  464.     call    xbios        ; get skewed sector number
  465.     mov    a,l
  466.     sta    actsec        ; actual sector
  467.     shld    bcreg        ; sector number in BC
  468.     mvi    a,11        ; setsec function number
  469.     call    xbios        ; set CP/M 3.0 sector
  470.     lhld    hsttrk        ; physical track number
  471.     shld    bcreg        ; track number in BC
  472.     mvi    a,10        ; settrk function number
  473.     call    xbios
  474.     lxi    h,hstbuf    ; sector buffer
  475.     shld    bcreg        ; buffer address in BC
  476.     mvi    a,12        ; setdma function number
  477.     call    xbios
  478.     mvi    a,1        ; DMA bank number
  479.     sta    areg        ; bank number in A
  480.     mvi    a,28        ; setbnk function number
  481.     call    xbios        ; set DMA bank
  482.     ret
  483. ;
  484. ;    Print message at HL until null.
  485. ;
  486. prmsg:    mov    a,m
  487.     ora    a
  488.     rz
  489.     mov    c,m
  490.     push    h
  491.     call    xconout
  492.     pop    h
  493.     inx    h
  494.     jmp    prmsg
  495. ;
  496. ;    disk i/o buffer
  497. ;
  498. hstbuf:    ds    max$sector$size
  499. ;
  500. ;    variable storage area
  501. ;
  502. sekdsk:    ds    1        ; logical disk number
  503. sektrk:    ds    2        ; logical track number
  504. seksec:    ds    1        ; logical sector number
  505. ;
  506. hstdsk:    ds    1        ; physical disk number
  507. hsttrk:    ds    2        ; physical track number
  508. hstsec:    ds    1        ; physical sector number
  509. ;
  510. actsec:    ds    1        ; skewed physical sector
  511. sekhst:    ds    1        ; temp physical sector
  512. hstact:    ds    1        ; buffer ative flag
  513. hstwrt:    ds    1        ; buffer changed flag
  514. ;
  515. unacnt:    ds    1        ; unallocated sector cunt
  516. unadsk:    ds    1        ; unalloc disk number
  517. unatrk:    ds    2        ; unalloc track number
  518. unasec:    ds    1        ; unalloc sector number
  519. sekbuf:    ds    2        ; logical sector address in buffer
  520. ;
  521. spt:    ds    1        ; cpm sectors per track
  522. xlat:    ds    2        ; xlat address
  523. bsm:    ds    1        ; block shift mask
  524. psh:    ds    1        ; physical shift factor
  525. ;
  526. erflag:    ds    1        ; error reporting
  527. rsflag:    ds    1        ; force sector read
  528. readop:    ds    1        ; 1 if read operation
  529. rwflag:    ds    1        ; physical read flag
  530. wrtype:    ds    1        ; write operation type
  531. dmaadr:    ds    2        ; last dma address
  532. oldaddr:ds    2        ; address of old BIOS
  533. ;
  534. first:    db    0ffh        ; first time through flag, set on load
  535.  
  536.     end
  537.  
  538.  
  539.  
  540.