home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol040 / isis-cpm.asm < prev    next >
Assembly Source File  |  1984-04-29  |  25KB  |  968 lines

  1. ;===============================================================
  2. ;
  3. ;    Prom Based CP/M and ISIS 4.0 Bios, August 9, 1981
  4. ;
  5. ;                        Version 1.0
  6. ;
  7. ;       (For Tarbell Disk Controller and Dynabyte Video)
  8. ;
  9. ;===============================================================
  10. ;
  11. ; This module contains the input/output routines used by ISIS II
  12. ; and a CP/M cold boot loader.
  13. ;
  14. true    equ    -1        ; define value of true
  15. false    equ    not true    ; define value of false
  16. debug    equ    false        ; set true if setup assembly for 
  17.                 ; ram based debug at 32 memory size
  18. ;
  19. stprat    equ    2        ; rate 1=6ms, 2=10ms, 3=20ms
  20. hlab    equ    8        ; 8 for hd ld at beg of seek
  21. ;
  22. ; define disk controller base addresses for operations
  23. ;
  24. disk    equ    0f8h        ; disk base address
  25. dcom    equ    disk        ; disk command port
  26. dstat    equ    disk        ; disk status port
  27. track    equ    disk+1        ; disk track port
  28. sectp    equ    disk+2        ; disk sector port
  29. ddata    equ    disk+3        ; disk data port
  30. wait    equ    disk+4        ; disk wait port
  31. dcont    equ    disk+4        ; disk control port
  32. ;
  33. ; define console and printer interface parameter equates
  34. ;
  35. cstat    equ    00h        ; console status port
  36. cdata    equ    01h        ; console data port
  37. lstat    equ    42h        ; list status port
  38. ldata    equ    43h        ; list data port
  39. ckbr    equ    00000001b    ; keyboard ready bit
  40. cptr    equ    10000000b    ; crt out ready bit
  41. lptr    equ    00000001b    ; printer output ready bit
  42. ;
  43. ; define stack top location
  44. ;
  45. stack    equ    100h    ; top of stack
  46. ;
  47. ; define ASCII character codes that are referenced
  48. ;
  49. cr    equ    0dh        ; ASCII cariage return
  50. lf    equ    0ah        ; ASCII linefeed
  51. ;
  52. ; define ISIS and CP/M storage locations and constants
  53. ;
  54. iobyte    equ    0003h        ; INTEL iobyte
  55. initio    equ    0006h        ; initial I/O config
  56. memtop    equ    0004h        ; location ISIS stores the top of ram
  57. ;
  58.     if    debug
  59. monitor    equ    08800h        ; monitor start
  60. memsiz    equ    32        ; ram memory size in decimal kilo bytes
  61.     endif            ; debug
  62. ;
  63.     if    not debug
  64. monitor    equ    0f800h        ; monitor start
  65. memsiz    equ    62        ; ram memory size in decimal kilo bytes
  66.     endif            ; not debug
  67. ;
  68. memmax    equ    ((memsiz*1024)/256)-1    ; memory map area
  69. date    equ    0715h        ; date
  70. verh    equ    10h        ; version 1.0
  71. ;
  72.     org    0ffffh
  73. ;
  74.     db    0        ; set version number of monitor
  75. ;
  76. ; start of CP/M and ISIS boot load point routine
  77. ;
  78.     org    monitor        ; origin of this program
  79. ;
  80.     jmp    start0        ; reset entry point
  81.     jmp    conin        ; console input
  82.     jmp    reader        ; reader input
  83.     jmp    conout        ; console output
  84.     jmp    punch        ; punch output
  85.     jmp    list        ; list output
  86.     jmp    const        ; console input status
  87.     jmp    iochk        ; I/O system status
  88.     jmp    ioset        ; set I/O configuration
  89.     jmp    memchk        ; compute size of memory
  90.     jmp    dummy        ; define user I/O entry points
  91.     jmp    dummy
  92.     dw    date        ; date stamp for monitor rom
  93.     jmp    dummy        ; upp input
  94.     jmp    dummy        ; upp output
  95.     jmp    dummy        ; upp status
  96.     db    verh        ; version stamp for monitor rom
  97.     db    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0    ; dummy copyright
  98.     jmp    dummy        ; ioccom entry point
  99.     jmp    dummy        ; ioc output
  100.     jmp    stat78        ; disk controller 1 status
  101.     jmp    stat88        ; disk controller 2 status
  102.     jmp    cmmd78        ; disk controller 1
  103.     jmp    cmmd88        ; disk controller 2
  104.     jmp    rtyp78        ; disk controller 1 result type
  105.     jmp    rtyp88        ; disk controller 2 result type
  106.     jmp    rbyt78        ; disk controller 1 result byte
  107.     jmp    rbyt88        ; disk controller 2 result byte
  108. ;
  109. ; disk command to controller that should be at 88h
  110. ; hl points to address of I/O parameter block
  111. ;
  112. cmmd88:    mvi    a,2        ; mark this is for controller 2
  113.     jmp    cmmdent        ; go do common I/O command
  114. ;
  115. ;
  116. ; disk command to controller that should be at 78h
  117. ; hl points to address of I/O parameter block
  118. ;
  119. cmmd78:    xra    a        ; mark this is for controller 1
  120. cmmdent:shld    iopb        ; save pointer to iopb
  121.     lxi    h,0        ; make hl 0 for dad
  122.     dad    sp
  123.     shld    ostack        ; save old stack pointer
  124.     lxi    sp,newstk    ; set up new stack
  125.     push    d        ; save d and e
  126.     push    b        ; save b and c
  127.     mov    c,a        ; drive select bit 1
  128.     lxi    h,iodone    ; make return address
  129.     push    h        ; put it on stack
  130. ;
  131. ; copy iopb into scratch area
  132. ;
  133.     lxi    d,ioblk        ; point to ioblk destination
  134.     lhld    iopb        ; point to source
  135.     mvi    b,7        ; number of bytes to move
  136. ibkmov:    mov    a,m        ; get a byte
  137.     stax    d        ; store a byte
  138.     inx    h        ; bump pointers
  139.     inx    d
  140.     dcr    b        ; decrement count
  141.     jnz    ibkmov        ; loop if not done
  142. ;
  143. ; select disk drive specified in iopb
  144. ;
  145.     lda    dskins        ; get disk instruction
  146.     rrc
  147.     rrc
  148.     rrc
  149.     rrc            ; drive select bits to 1 and 2
  150.     ani    1        ; select bit 0
  151.     ora    c        ; select bit 1
  152.     call    seldsk        ; select drive
  153. ;
  154. ; test if selected drive is ready, error if not ready
  155. ;
  156.     in    dstat        ; read status
  157.     rlc            ; look at drive ready bit
  158.     jc    rdyerr        ; error if not ready
  159. ;
  160. ; execute disk instruction from iopb
  161. ;
  162.     lda    dskins        ; get disk instruction
  163.     ani    7        ; look at opcode only
  164.     cpi    4
  165.     jz    iread        ; goto INTEL read
  166.     cpi    6
  167.     jz    iwrite        ; goto INTEL write
  168.     cpi    7
  169.     jz    iwrite        ; do deleted write like normal write
  170.     cpi    5
  171.     jz    iverf        ; goto INTEL verify
  172.     cpi    1
  173.     jz    seek        ; goto INTEL seek
  174.     cpi    2
  175.     jz    ifrmat        ; INTEL format
  176.     cpi    3
  177.     jz    home        ; do INTEL home
  178.     xra    a        ; nop, ret result byte=0
  179.     ret
  180. ;
  181. ; disk I/O complete restore regs and restore sp and return
  182. ; disk controller simulator exit point
  183. ;
  184. iodone:    sta    resbyt        ; save disk status
  185.     pop    b        ; restore regs
  186.     pop    d
  187.     lhld    ostack
  188.     sphl            ; restore stack
  189.     lhld    iopb
  190.     ret            ; return to ISIS
  191. ;
  192. ; user entry point to check the status of the I/O byte
  193. ;
  194. iochk:    lda    iobyte        ; get status byte
  195.     ret
  196. ;
  197. ; user entry point to change the I/O byte to a new value
  198. ;
  199. ioset:    mov    a,c        ; put new value into the memory
  200.     sta    iobyte
  201.     ret
  202. ;
  203. ; user entry point to get the value of the top of available memory
  204. ;
  205. memchk:    lda    memtop+1    ; msbyt of top address of memory
  206.     dcr    a        ; change one page less to permit
  207.                 ; monitor to use 256 bytes of ram
  208.     mov    b,a        ; msbyt in b reg
  209.     mvi    a,0c0h        ; ab points to base of user stack
  210.     ret            ; in 2'nd from top page of ram
  211. ;
  212. ; dummy I/O routine
  213. ;
  214. dummy:    xra    a
  215.     ret            ; dummy routine
  216. ;
  217. ; routine to simulate getting ready status of the single density
  218. ; INTEL disk controller hardware
  219. ;
  220. stat78:    equ    $
  221. ;
  222. stat88:    mvi    a,0bh        ; show always ready
  223.     ret
  224. ;
  225. ; routine to imitate return of result type byte from the disk 
  226. ; controller hardware
  227. ;
  228. rtyp78:    equ    $
  229. ;
  230. rtyp88:    xra    a
  231.     ret
  232. ;
  233. ; routine to imitate reading of the result byte from the disk
  234. ; controller hardware code was made by the disk operation
  235. ; command routines and stored at resbyt in the top page of ram
  236. ;
  237. rbyt78:    equ    $
  238. ;
  239. rbyt88:    lda    resbyt        ; get result byte
  240.     ret
  241. ;
  242. ; here to setup start of command inquiry loop to boot either
  243. ; a CP/M system disk of up to 62k size or to load an ISIS 40
  244. ; system disk that has been patched for disk I/O through this 
  245. ; prom based i/c-bios software
  246. ;
  247. start0:    lxi    sp,stack    ; set stack pointer
  248. ;
  249. ; put jump to monitor at zero
  250. ;
  251.     mvi    a,0c3h        ; put jump to monitor at 0
  252.     sta    0000h
  253.     lxi    h,monitor
  254.     shld    0001h
  255.     mvi    a,01h        ; console is crt
  256.     sta    iobyte
  257.     sta    initio
  258. ;
  259. ; calculate top of memory and store at "memtop" for the ISIS 
  260. ; system operation
  261. ;
  262.     lxi    h,03f00h    ; start point for test
  263. pag:    inr    h        ; set to next page
  264.     jz    fnd        ; stop if at end
  265.     mov    a,m        ; get memory byte
  266.     cma            ; complement it
  267.     mov    m,a        ; put comp in memory
  268.     cmp    m        ; did it go in ok
  269.     cma            ; invert back
  270.     mov    m,a        ; restore original
  271.     jz    pag        ; loop to next 256 bytes if it changed
  272. fnd:    dcx    h        ; back up a page
  273.     mov    a,h
  274.     cpi    memmax        ; less than f700h
  275.     jc    x11        ; if yes then use this value
  276. ;
  277. fnd1:    mvi    h,memmax    ; otherwise set memtop to 0f7ffh
  278. ;
  279. x11:    shld    memtop        ; set ISIS memory top address
  280. ;
  281. ; command check loop for monitor operation select
  282. ;
  283. iboot:    lxi    h,stmsg        ; point to start msg
  284.     call    pmsg        ; print message
  285. iboot1:    call    conin        ; wait for response
  286.     push    psw        ; echo operator response
  287.     mov    c,a
  288.     call    conout
  289.     pop    psw
  290.     ani    05fh        ; convert input to upper case
  291.     cpi    'C'        ; check if CP/M boot
  292.     jz    cpmboot
  293.     cpi    'I'        ; or if ISIS boot
  294.     jnz    iboot        ; if neither then prompt again
  295. ;
  296. ; print ISIS prompt message and then load disk on input of a "cr"
  297. ;
  298. isisboot:
  299. ;
  300.     lxi    h,isisms    ; print ISIS load message
  301.     call    pmsg
  302.     call    conin        ; get ready status
  303.     cpi    cr        ; see if a cr
  304.     jnz    iboot        ; start all over if not ISIS boot
  305.     lxi    h,crlf        ; print carriage return linefeed
  306.     call    pmsg
  307. ;
  308. ; force interrupt
  309. ;
  310.     mvi    a,0d0h        ; force interrupt command
  311.     out    dcom
  312.     in    dstat        ; clear interrupt
  313. ;
  314. ; setup scratch area
  315. ;
  316.     lxi    h,0ffffh
  317.     shld    trtab        ; preset track table
  318.     shld    trtab+2
  319.     mvi    a,4        ; set up initial out of range disk
  320.     sta    diskno
  321.     xra    a
  322.     call    seldsk        ; select drive 0
  323. ;
  324. ; boot in ISISt0 to location 3000 and execute
  325. ;
  326.     lxi    h,bootpb    ; point to boot parameter block
  327.     call    cmmd78        ; read in disk
  328.     ora    a
  329.     jz    3000h        ; if no errors goto ISIS
  330.     lxi    h,bmsg
  331.     call     pmsg        ; print boot error message
  332.     jmp    iboot        ; if error then go try for another command
  333. ;
  334. ; iopb for booting ISISt0 in to 3000h
  335. ;
  336. bootpb:    db    80h        ; iocw, no update bit set
  337.     db    04h        ; I/O instruction, read disk 0
  338.     db    26        ; read 26 sectors
  339.     db    0        ; track 0
  340.     db    1        ; sector 1
  341.     dw    3000h        ; load address
  342. ;
  343. ; print CP/M prompt message and then load disk on input of a "cr"
  344. ;
  345. cpmboot:lxi    h,cpmms        ; print CP/M load message
  346.     call    pmsg
  347.     call    conin        ; get ready status
  348.     cpi    cr        ; see if a cr
  349.     jnz    iboot        ; start all over if not CP/M boot
  350.     lxi    h,crlf        ; print carriage return linefeed
  351.     call    pmsg
  352. ;
  353. ; force interrupt
  354. ;
  355.     mvi    a,0d0h        ; force interrupt command
  356.     out    dcom
  357.     in    dstat        ; clear interrupt
  358. ;
  359. ; setup scratch area
  360. ;
  361.     lxi    h,0ffffh
  362.     shld    trtab        ; preset track table
  363.     shld    trtab+2
  364.     mvi    a,4        ; set up initial out of range disk
  365.     sta    diskno
  366.     xra    a
  367.     call    seldsk        ; select drive 0
  368. ;
  369. ; boot normal CP/M track zero sector 1 into ram at zero and
  370. ; jump to it to get in rest of CP/M
  371. ;
  372.     lxi    h,cpmpb        ; point to boot parameter block
  373.     call    cmmd78        ; read in disk
  374.     ora    a
  375.     jz    0000h        ; if no errors goto CP/M loader
  376.     lxi    h,bmsg
  377.     call     pmsg        ; print boot error message
  378.     jmp    iboot        ; if error then go try for another command
  379. ;
  380. ; iopb for booting CP/M track 0 sector 1 into 0000h
  381. ;
  382. cpmpb:    db    80h        ; iocw, no update bit set
  383.     db    04h        ; I/O instruction, read disk 0
  384.     db    01        ; read one sector
  385.     db    0        ; track 0
  386.     db    1        ; sector 1
  387.     dw    0000h        ; load address
  388. ;
  389. ; hardware interface I/O routines for ISIS bios software
  390. ;
  391. ; check console input status
  392. ;
  393. const:    in    cstat        ; read console status
  394.     ani    ckbr
  395.     mvi    a,0        ; set a=0
  396.     rnz            ; return if not ready with a=0
  397.     cma
  398.     ret
  399. ;
  400. ; read a character from console
  401. ;
  402. conin:    in    cstat        ; read console status
  403.     ani    ckbr        ; if not ready
  404.     jnz    conin        ; keep waiting
  405.     in    cdata        ; read a character
  406.     ani    7fh        ; make most sig bit=0
  407.     ret
  408. ;
  409. ; write a character to the console device
  410. ;
  411. conout:    in    cstat        ; read console status
  412.     ani    cptr        ; if not ready,
  413.     jnz    conout        ; keep waiting
  414.     mov    a,c        ; get character
  415.     out    cdata        ; print it
  416.     ret
  417. ;
  418. ; write a character to the list device
  419. ;
  420. list:    in    lstat        ; read list port status
  421.     ani    lptr        ; if not ready,
  422.     jz    list        ; then keep waiting
  423.     mov    a,c        ; get character
  424.     out    ldata        ; print it
  425.     ret
  426. ;
  427. ; select disk number according to register a
  428. ;
  429. seldsk:    lxi    h,diskno    ; get addr of old disk no
  430.     cmp    m        ; new=old?
  431.     mov    c,a        ; c=new drive
  432.     jz    seld1
  433. ;
  434. ; if changing to a new drive perform a seek to the same track
  435. ; this is an undocumented procedure which unloads the head
  436. ;
  437.     in    track        ; get the present track
  438.     out    ddata        ; put in 1771 data reg
  439.     mvi    a,10h        ; seek command
  440.     out    dcom        ; seek same track
  441.     in    wait
  442. ;
  443. ; get old track number from 1771 and put into table
  444. ;
  445.     mov    e,m        ; e=old disk no
  446.     mvi    d,0        ; clear d for dad
  447.     lxi    h,trtab        ; point to table
  448.     dad    d        ; index into table
  449.     in    track        ; read 1771 track reg
  450.     mov    m,a        ; put into table
  451. ;
  452. ; get new drive track number from table and put in 1771
  453. ;
  454.     mov    e,c        ; e=new disk no
  455.     mvi    d,0        ; clear d for dad
  456.     lxi    h,trtab        ; point to table
  457.     dad    d        ; index into table
  458.     mov    a,m        ; get new track number
  459.     out    track        ; update 1771 track reg
  460. ;
  461. ; update diskno and select new drive
  462. ;
  463. seld1:    mov    a,c        ; update old disk number
  464.     sta    diskno
  465.     cma
  466.     add    a        ; put bits 1 and 2 at 4 and 5
  467.     add    a
  468.     add    a
  469.     add    a
  470.     ori    2
  471.     sta    latch        ; update latch
  472.     out    dcont        ; select drive
  473. ;
  474. ; if table entry for this drive is ff then this drive is not logged
  475. ; and we must do a recalibrate before returning from seldsk
  476. ;
  477.     mov    a,m        ; get track from table
  478.     inr    a        ; if 0ffh then recalibrate
  479.     rnz
  480. ;
  481. ; move disk to track zero
  482. ;
  483. home:    mvi    a,stprat+hlab    ; restore command
  484.     out    dcom        ; to controller
  485.     in    wait        ; wait for restore complete
  486.     in    dstat        ; read status
  487.     ani    91h        ; look at these bits
  488.     rz            ; return good
  489.     mvi    a,00000100b    ; seek error
  490.     ret            ; return bad
  491. ;
  492. ; seek track specified in iopb
  493. ;
  494. seek:    lda    itrack        ; get track # from iopb
  495.     cpi    77        ; more than 77 ?
  496.     jnc    adrerr        ; error if more
  497.     mov    b,a        ; b=destination track
  498.     in    track        ; a= present track no
  499.     mov    c,a        ; c= present track also
  500.     cmp    b        ; dest=present ??
  501.     rz            ; return if same
  502. ;
  503. ; this routine is to allow time for the drive
  504. ; tunnel erase to terminate before moving the
  505. ; head the delay is approx 700 micro-sec @
  506. ; 4 mhz cpu time, and  double this for 2 mhz cpu's
  507. ;
  508.     push    psw
  509.     mvi    a,208        ; delay count
  510. busy1:    dcr    a        ; count=count-1
  511.     jnz    busy1        ; loop til count=0
  512.     pop    psw
  513.     mov    a,b        ; a=destination track
  514.     out    ddata        ; track to data register
  515. busy:    in    dstat        ; read disk status
  516.     rrc            ; look at bit 0
  517.     jc    busy        ; wait till not busy
  518.     mvi    a,10h+stprat+hlab ; get step rate and head load
  519.     out    dcom        ; do seek
  520.     in    wait        ; wait for seek done
  521.     in    dstat        ; read controller status
  522.     ani    91h        ; look at these bits
  523.     rz            ; return good
  524.     mvi    a,00000100b    ; seek error
  525.     ret            ; return bad
  526. ;
  527. ; hdld-get head-load bit if required
  528. ;
  529. hdld:    in    dstat        ; read 1771 status
  530.     ani    20h        ; look at hl bit
  531.     jz    hdldy        ; load if not loaded
  532.     xra    a        ; otherwise, a=0
  533.     ret            ; return from hdld
  534. hdldy:    mvi    a,4        ; set bit to load head
  535.     ret            ; return from hdld
  536. ;
  537. ; write sector or sectors specified in iopb
  538. ;
  539. iwrite:    call    seek        ; check params and seek track
  540.     rnz            ; return if seek error
  541.     mvi    c,20h        ; set (c) to write code
  542.     jmp    ddio        ; go do common I/O
  543. ;
  544. ; verify sector or sectors specified in iopb
  545. ;
  546. iverf:    call    seek        ; check parms and perform seek
  547.     rnz            ; return if seek error
  548.     mvi    c,080h        ; set verify function bit
  549.     jmp    ddio        ; go do common I/O
  550. ;
  551. ; read sector or sectors specified in iopb
  552. ;
  553. iread:    call    seek        ; check params and seek track
  554.     rnz            ; return if seek error
  555.     mvi    c,0        ; set read function code and 
  556.                 ; fall through to common I/O
  557. ;
  558. ; do disk common operations
  559. ;
  560. ddio:    lhld    dmaadd        ; get dma address in h and l
  561.     mvi    a,0d0h
  562.     out    dcom        ; force interupt
  563.     lda    sect        ; get iopb sector
  564.     ani    1fh        ; strip select bit
  565.     cpi    27        ; more than 26 ?
  566.     jnc    adrerr        ; error if more
  567.     out    sectp        ; sector to 1771
  568.     call    hdld        ; head loaded ?
  569.     adi    88h
  570.     push    b        ; save function byte in (c)
  571.     push    psw        ; strip possible verify bit off (c)
  572.     mov    a,c
  573.     ani    07fh
  574.     mov    c,a
  575.     pop    psw
  576.     ora    c        ; read/write
  577.     out    dcom        ; command to 1771
  578.     pop    b
  579.     mov    a,c        ; get read/write
  580.     cpi    020h        ; check for write
  581.     jz    wloop        ; if 020h then write
  582.     cpi    080h        ; check for verify
  583.     jz    vloop        ; if 080h then verify
  584.                 ; must be read if not write/verify
  585. ;
  586. ; read loop            ; else read
  587. ;
  588. rloop:    in    wait        ; wait for drq or intrq
  589.     ora    a        ; set flags
  590.     jp    rdone        ; if p then was intrq, done
  591.     in    ddata        ; otherwise drq, get byte
  592. poke:    mov    m,a        ; put into memory
  593.     inx    h        ; bump memory pointer
  594.     jmp    rloop        ; continue reading
  595. ;
  596. ; read exit
  597. ;
  598. rdone:    in     dstat        ; get status
  599.     ani    9dh        ; look at these error bits
  600.     jnz    dskerr
  601.                 ; fall through to next record check
  602. ;
  603. ; next record of multiple record check
  604. ;
  605. nxtrec:    lxi    h,numrec    ; point to numrec in iopb
  606.     dcr    m        ; numrec=numrec-1
  607.     rz            ; return if numrec=0
  608.     lhld    dmaadd        ; else get dma address
  609.     lxi    d,128
  610.     dad    d        ; hl=hl+128
  611.     shld    dmaadd        ; update dma address
  612.     lxi    h,sect        ; point to sector # in iopb
  613.     inr    m        ; sect=sect+1
  614.     mov    a,m
  615.     cpi    27        ; greater than 26 ??
  616.     jc    ddio        ; continue if range ok
  617.     jmp    adrerr        ; otherwise error
  618. ;
  619. ; verify loop
  620. ;
  621. vloop:    in    wait        ; wait for drq or intrq
  622.     ora    a        ; set flags
  623.     jp    vdone        ; if p then was intrq and done
  624.     in    ddata        ; otherwise drq so get data
  625.                 ; we wont use data if a verify op
  626.     inx    h        ; do pointer anyway
  627.     jmp    vloop        ; go for next byte
  628. ;
  629. ; verify exit
  630. ;
  631. vdone:    in    dstat        ; get operation status
  632.     ani    09dh        ; mask appropiate bits
  633.     jnz    dskerr        ; go to error tree if I/O error
  634.     jmp    nxtrec        ; see if more records to do
  635. ;
  636. ; write loop
  637. ;
  638. wloop:    in     wait        ; wait for drq or intrq
  639.     ora    a        ; set flags
  640.     jp    wdone        ; if p then was intrq, done
  641.     mov    a,m        ; get a byte from memory
  642.     out     ddata        ; send to 1771
  643.     inx    h        ; bump memory pointer
  644.     jmp    wloop        ; continue writing
  645. ;
  646. ; write done
  647. ;
  648. wdone:    in     dstat        ; read status
  649.     ani    0fdh        ; look at these error bits
  650.     jz    nxtrec        ; see if more records
  651. ;
  652. ; disk I/O error sorting tree that converts 1771 error codes into
  653. ; those required to emulate an INTEL disk controller
  654. ;
  655. dskerr:    cpi    10000000b    ; test for not ready
  656.     jz    rdyerr
  657.     cpi    01000000b    ; test for write protect
  658.     jz    wprot
  659.     cpi    00000100b    ; test for lost data
  660.     jz    losdat
  661.     cpi    00011000b    ; test for id crc error
  662.     jz    idcrc
  663.     cpi    00010000b    ; test for record not found
  664.     jz    idcrc
  665.                 ; lets say all else is crc
  666. crcerr:    mvi    a,00000010b    ; make code for crc error
  667.     ret
  668. ;
  669. wprot:    mvi    a,00100000b    ; make code for write protect
  670.     ret
  671. ;
  672. rdyerr:    mvi    a,10000000b    ; make code for not ready
  673.     ret
  674. ;
  675. losdat:    mvi    a,00010000b    ; make code for lost data
  676.     ret
  677. ;
  678. idcrc:    mvi    a,00001010b    ; make code for id crc
  679.     ret
  680. ;
  681. adrerr:    mvi    a,00001000b    ; make code for adress error
  682.     ret
  683. ;
  684. ; format a track-this routine here due to fact that INTEL controller
  685. ; directly supports a track format operation for the "idisk" command
  686. ;
  687. ifrmat:    in    dstat        ; read disk status
  688.     ani    01000000b
  689.     jnz    wprot        ; error if write protected
  690.     call    seek        ; seek desired track
  691.     lda    chword        ; get channel word
  692.     ani    01000000b    ; look at format sequence
  693.     jnz    random        ; go setup table for random
  694. ;
  695. ; sequential format-fill table with fill characters and sequential
  696. ; sector numbers fill byte pointed to by dmaadd
  697. ;
  698. seq:    lhld    dmaadd        ; point to fill byte
  699.     mov    d,m        ; put fill byte into (d)
  700.     mvi    a,01h        ; start sector number
  701.     lxi    h,fmttab    ; point to format table
  702. seqlp:    mov    m,a        ; put sector into table
  703.     inx    h
  704.     mov    m,d        ; put fill char into the table
  705.     inx    h
  706.     inr    a        ; increment sector number
  707.     cpi    27        ; table all filled yet?
  708.     jnz    seqlp
  709.     jmp    seq1        ; go start format
  710. ;
  711. ; random format-fill table with sector and fill bytes that was
  712. ; built by caller in the iopb pointed data buffer
  713. ;
  714. random:    lhld    dmaadd        ; point to callers table
  715.     mvi    b,52        ; number of entries to move across
  716.     lxi    d,fmttab    ; point to our table
  717. randlp:    mov    a,m        ; get users byte
  718.     stax    d        ; put into our table
  719.     inx    h        ; do pointer adjust for loop
  720.     inx    d
  721.     dcr    b        ; moved all bytes yet?
  722.     jnz    randlp
  723. seq1:    lxi    h,fmttab    ; point to format order table
  724.     lda    itrack        ; get track number
  725.     mov    c,a        ; put it in c
  726.     mvi    e,26        ; set max # sectors
  727.     mvi    b,40        ; gap 4 preindex 40 bytes of 0ffh
  728.     mvi    a,0f4h        ; load track write command
  729.     out    dcom        ; issue track write
  730. ;
  731. ; write preindex fill
  732. ;
  733. preind:    in    wait        ; wait for drq
  734.     ora    a        ; set flags
  735.     jp    fmterr        ; jmp out if error
  736.     mvi    a,0ffh        ; byte=0ffh
  737.     out    ddata        ; write it on disk
  738.     dcr    b        ; count=count-1
  739.     jnz    preind        ; loop til count=0
  740.     mvi    b,6        ; count=6
  741. prein1:    in    wait        ; wait for drq
  742.     ora    a        ; set flags
  743.     jp    fmterr        ; jmp out if error
  744.     xra    a        ; byte=0
  745.     out    ddata        ; write it on disk
  746.     dcr    b        ; count=count-1
  747.     jnz    prein1        ; loop til count=0
  748. ;
  749. ; write address mark on track
  750. ;
  751.     in    wait        ; wait for drq
  752.     ora    a        ; set flags
  753.     jp    fmterr        ; jmp out if error
  754.     mvi    a,0fch        ; load address mark
  755.     out    ddata        ; write it on disk
  756. ;
  757. ; post index gap
  758. ;
  759. postgap:mvi    b,26        ; count=26
  760. postid:    in    wait        ; wait for drq
  761.     ora    a        ; set flags
  762.     jp    fmterr        ; jmp out if error
  763.     mvi    a,0ffh        ; byte=0ffh
  764.     out    ddata        ; write it on disk
  765.     dcr    b        ; count=count-1
  766.     jnz    postid        ; loop til count=0
  767. ;
  768. ; pre id section
  769. ;
  770. asect:    mvi    b,6        ; count=6
  771. sector:    in    wait        ; wait for drq
  772.     ora    a        ; set flags
  773.     jp    fmterr        ; jmp out if error
  774.     xra    a        ; byte=0
  775.     out    ddata        ; write it on track
  776.     dcr    b        ; count=count-1
  777.     jnz    sector        ; loop til count=0
  778. ;
  779. ; write id address mark
  780. ;
  781.     in    wait        ; wait for drq
  782.     ora    a        ; set flags
  783.     jp    fmterr        ; if error jmp out
  784.     mvi    a,0feh        ; get address mark
  785.     out    ddata        ; write it on disk
  786. ;
  787. ; write track number on disk
  788. ;
  789.     in    wait        ; wait for drq
  790.     ora    a        ; set flags
  791.     jp    fmterr        ; jmp out if error
  792.     mov    a,c        ; get track number
  793.     out    ddata        ; write it on disk
  794. ;
  795. ; write one byte of 00
  796. ;
  797.     in    wait        ; wait for drq
  798.     ora    a        ; set flags
  799.     jp    fmterr        ; jmp out if error
  800.     xra    a        ; byte=0
  801.     out    ddata        ; write it on disk
  802. ;
  803. ; write sector # on disk
  804. ;
  805.     in    wait        ; wait for drq
  806.     ora    a        ; set flags
  807.     jp    fmterr        ; jmp out if error
  808.     mov    a,m        ; get sector #
  809.     out    ddata        ; write it on disk
  810. ;
  811. ; increment table pointer to next byte to point to sector fill byte
  812. ;
  813.     inx    h        ; point to fill byte
  814. ;
  815. ; one more byte 0
  816. ;
  817.     in    wait        ; wait for drq
  818.     ora    a        ; set flags
  819.     jp    fmterr        ; jmp out if error
  820.     xra    a        ; byte=0
  821.     out    ddata        ; write it on disk
  822.     inr    d        ; bump sector count
  823. ;
  824. ; write 2 crc's on this sector
  825. ;
  826.     in    wait        ; wait for drq
  827.     ora    a        ; set flags
  828.     jp    fmterr        ; jmp out if error
  829.     mvi    a,0f7h        ; get crc pattern
  830.     out    ddata        ; write it on disk
  831. ;
  832. ; get sector fill byte to (d) and inx table pointer for next sector
  833. ;
  834.     mov    d,m        ; get fill byte
  835.     inx    h        ; point to next sector number
  836. ;
  837. ; pre data 17 bytes 00
  838. ;
  839.     mvi    b,11        ; count=11
  840. predat:    in    wait        ; wait for drq
  841.     ora    a        ; set flags
  842.     jp    fmterr        ; jmp out if error
  843.     mvi    a,0ffh        ; byte=0ffh
  844.     out    ddata        ; write it on disk
  845.     dcr    b        ; count=count-1
  846.     jnz    predat        ; loop til count=0
  847.     mvi    b,6        ; count=6
  848. preda1:    in    wait        ; wait for drq
  849.     ora    a        ; set flags
  850.     jp    fmterr        ; jmp out if error
  851.     xra    a        ; byte=0
  852.     out    ddata        ; write it to disk
  853.     dcr    b        ; count=count-1
  854.     jnz    preda1        ; loop til count=0
  855. ;
  856. ; data address mark
  857. ;
  858.     in    wait        ; wait for drq
  859.     ora    a        ; set flags
  860.     jp    fmterr        ; jmp out if error
  861.     mvi    a,0fbh        ; get data address mark
  862.     out    ddata        ; write it on disk
  863. ;
  864. ; fill data field with data from table
  865. ;
  866.     mvi    b,128        ; count=128
  867. dfill:    in    wait        ; wait for drq
  868.     ora    a        ; set flags
  869.     jp    fmterr        ; jmp out if error
  870.     mov    a,d        ; get fill byte
  871.     out    ddata        ; write it on disk
  872.     dcr    b        ; count=count-1
  873.     jnz    dfill        ; loop til count=0
  874. ;
  875. ; write crc's
  876. ;
  877.     in    wait        ; wait till drq
  878.     ora    a        ; set flags
  879.     jp    fmterr        ; jmp out if error
  880.     mvi    a,0f7h        ; get crc byte
  881.     out    ddata        ; write it on disk
  882. ;
  883. ; end of sector fill
  884. ;
  885.     dcr    e        ; sectorcount=sectorcount-1
  886.     jz    endtrk        ; jmp if sectorcount=0
  887. datgap:    in    wait        ; wait for drq
  888.     ora    a        ; set flags    
  889.     jp    fmterr        ; jmp out if error
  890.     mvi    a,0ffh        ; byte=0ffh
  891.     out    ddata        ; write it on disk
  892.     jmp    postgap        ; do next sector
  893. ;
  894. ; do track and sector house keeping
  895. ;
  896. endtrk:    in    wait        ; wait for drq or intrq
  897.     ora    a        ; set flags
  898.     jp    fdone        ; jmp out if error
  899.     mvi    a,0ffh        ; load a with 0ffh
  900.     out    ddata        ; write it on disk
  901.     jmp    endtrk        ; do until intrq
  902. ;
  903. ; format error sort routine
  904. ;
  905. fdone:    in    dstat        ; read status
  906.     ora    a        ; test for flag
  907.     rz            ; return if no errors
  908. fmterr:    in    dstat
  909.     jmp    dskerr        ; error if not zero
  910. ;
  911. ; read a character from reader device
  912. ;
  913. reader:    mvi    a,1ah        ; always return an eof char
  914. ;
  915. punch:    ret            ; punch is a do nothing output
  916. ;
  917. ; print data pointed to by h and l until a zero is found
  918. ;
  919. pmsg:    mov    a,m        ; get character
  920.     ora    a        ; set flags
  921.     rz            ; ret if char is a zero
  922.     mov    c,a        ; put char in "c"
  923.     call    conout        ; print character
  924.     inx    h        ; bump message pointer
  925.     jmp    pmsg        ; do another character
  926. ;
  927. ; bios messages
  928. ;
  929. stmsg:    db    cr,lf
  930.     db    'ISIS 4.0 Bios,  Ver.1.0 implemented by Kelly Smith'
  931.     db    cr,lf
  932.     db    'Use "I" to boot ISIS disk or "C" to boot CP/M disk'
  933.     db    cr,lf,cr,lf,0
  934. isisms:    db    cr,lf,cr,lf,'ISIS disk in drive A:, type return ',0
  935. cpmms:    db    cr,lf,cr,lf,'CP/M disk in drive A:, type return ',0
  936. ;
  937. crlf:    db    cr,lf,0
  938. ;
  939. bmsg:    db    cr,lf,'+++Disk Boot Error+++',0
  940. ;
  941. ; bios scratch area placed at top of ram in system uses max of 256
  942. ; bytes in top ram page
  943. ;
  944.     org    memmax*256        ; set for top page of ram
  945. ;
  946. ;
  947. trtab:    ds    5        ; track table
  948. diskno:    ds    1        ; current disk number
  949. latch:    ds    1        ; current latch code
  950. resbyt:    ds    1        ; result byte
  951. ostack:    ds    2        ; old stack storage
  952. iopb:    ds    2        ; pointer to iopb
  953. ;
  954. ; copy of i/o parameter block
  955. ;
  956. ioblk:    equ    $
  957. chword:    ds    1        ; channel byte
  958. dskins:    ds    1        ; disk instruction
  959. numrec:    ds    1        ; number of records to do
  960. itrack:    ds    1        ; track address
  961. sect:    ds    1        ; current sector address
  962. dmaadd:    ds    2        ; current r/w address
  963. fmttab:    ds    52        ; storage for format table
  964.     ds    20        ; stack space
  965. newstk:    ds    1    
  966. ;
  967.     end
  968.