home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol043 / cbios.a86 < prev    next >
Encoding:
Text File  |  1984-04-29  |  17.0 KB  |  622 lines

  1.     title    'Customized Basic I/O System'
  2.  
  3. ;*********************************************
  4. ;*                                           *
  5. ;* This Customized BIOS adapts CP/M-86 to    *
  6. ;* the following hardware configuration      *
  7. ;*     Processor:  8085/8088 Dual Processor  *
  8. ;*     Brand:  CompuPro (Godbout)            *
  9. ;*     Controller:  iCom 3712                *
  10. ;*                                           *
  11. ;*                                           *
  12. ;*     Programmer:  Bruce R. Ratoff          *
  13. ;*     Revisions :  04/30/81 20:40           *
  14. ;*                                           *
  15. ;*********************************************
  16.  
  17. true        equ -1
  18. false        equ not true
  19. cr        equ 0dh ;carriage return
  20. lf        equ 0ah ;line feed
  21.  
  22. ;*********************************************
  23. ;*                                           *
  24. ;* Loader_bios is true if assembling the     *
  25. ;* LOADER BIOS, otherwise BIOS is for the    *
  26. ;* CPM.SYS file.                             *
  27. ;*                                           *
  28. ;*********************************************
  29.  
  30. loader_bios    equ false
  31. bdos_int    equ 224 ;reserved BDOS interrupt
  32.  
  33. ;*********************************************
  34. ;*                         *
  35. ;*           I/O Port Assignments            *
  36. ;*                         *
  37. ;*********************************************
  38. ;
  39. ;Diskette interface (iCom 3712)
  40. ;Note: Port numbers are "doubled up" because iCom card
  41. ;    counts on 8080 "address mirror" effect.
  42. datai    equ    0c0c0h    ;data/status input port
  43. datao    equ    0c1c1h    ;data output port
  44. cntrl    equ    0c0c0h    ;command output port
  45. ;
  46. ;Console interface (IMSAI SIO2-2 port 1)
  47. cstat    equ    3    ;status
  48. cdata    equ    2    ;data
  49. cimsk    equ    2    ;input ready mask
  50. comsk    equ    1    ;output ready mask
  51. ;
  52. ;Printer interface (IMSAI SIO2-2 port 2)
  53. lstat    equ    5    ;status
  54. ldata    equ    4    ;data
  55. lomsk    equ    1    ;output ready mask
  56. limsk    equ    2    ;input ready mask
  57.  
  58.  
  59.     IF    not loader_bios
  60. ;---------------------------------------------
  61. ;|                                           |
  62. bios_code    equ 2500h
  63. ccp_offset    equ 0000h
  64. bdos_ofst    equ 0B06h ;BDOS entry point
  65. ;|                                           |
  66. ;---------------------------------------------
  67.     ENDIF    ;not loader_bios
  68.  
  69.     IF    loader_bios
  70. ;---------------------------------------------
  71. ;|                                           |
  72. bios_code    equ 1200h ;start of LDBIOS
  73. ccp_offset    equ 0003h ;base of CPMLOADER
  74. bdos_ofst    equ 0406h ;stripped BDOS entry
  75. ;|                                           |
  76. ;---------------------------------------------
  77.     ENDIF    ;loader_bios
  78.  
  79.     cseg
  80.     org    ccpoffset
  81. ccp:
  82.     org    bios_code
  83.  
  84. ;*********************************************
  85. ;*                                           *
  86. ;* BIOS Jump Vector for Individual Routines  *
  87. ;*                                           *
  88. ;*********************************************
  89.  
  90.  jmp INIT    ;Enter from BOOT ROM or LOADER
  91.  jmp WBOOT    ;Arrive here from BDOS call 0  
  92.  jmp CONST    ;return console keyboard status
  93.  jmp CONIN    ;return console keyboard char
  94.  jmp CONOUT      ;write char to console device
  95.  jmp LISTOUT    ;write character to list device
  96.  jmp PUNCH    ;write character to punch device
  97.  jmp READER      ;return char from reader device 
  98.  jmp HOME    ;move to trk 00 on cur sel drive
  99.  jmp SELDSK      ;select disk for next rd/write
  100.  jmp SETTRK      ;set track for next rd/write
  101.  jmp SETSEC      ;set sector for next rd/write
  102.  jmp SETDMA      ;set offset for user buff (DMA)
  103.  jmp READ    ;read a 128 byte sector
  104.  jmp WRITE    ;write a 128 byte sector
  105.  jmp LISTST      ;return list status 
  106.  jmp SECTRAN     ;xlate logical->physical sector 
  107.  jmp SETDMAB     ;set seg base for buff (DMA)
  108.  jmp GETSEGT     ;return offset of Mem Desc Table
  109.  jmp GETIOBF    ;return I/O map byte (IOBYTE)
  110.  jmp SETIOBF    ;set I/O map byte (IOBYTE) 
  111.  
  112. ;*********************************************
  113. ;*                                           *
  114. ;* INIT Entry Point, Differs for LDBIOS and  *
  115. ;* BIOS, according to "Loader_Bios" value    *
  116. ;*                                           *
  117. ;*********************************************
  118.  
  119. INIT:    ;print signon message and initialize hardware
  120.     mov ax,cs    ;we entered with a JMPF so use
  121.     mov ss,ax    ;CS: as the initial value of SS:,
  122.     mov ds,ax    ;DS:,
  123.     mov es,ax    ;and ES:
  124.     ;use local stack during initialization
  125.     mov sp,offset stkbase
  126.     cld        ;set forward direction
  127.  
  128.     IF    not loader_bios
  129. ;---------------------------------------------
  130. ;|                                           |
  131.     ; This is a BIOS for the CPM.SYS file.
  132.     ; Setup all interrupt vectors in low
  133.     ; memory to address trap
  134.  
  135.     push ds        ;save the DS register
  136.     mov IOBYTE,0    ;clear IOBYTE
  137.     mov ax,0
  138.     mov ds,ax
  139.     mov es,ax     ;set ES and DS to zero
  140.     ;setup interrupt 0 to address trap routine
  141.     mov int0_offset,offset int_trap
  142.     mov int0_segment,CS
  143.     mov di,4
  144.     mov si,0    ;then propagate
  145.     mov cx,510    ;trap vector to
  146.     rep movs ax,ax    ;all 256 interrupts
  147.     ;BDOS offset to proper interrupt
  148.     mov bdos_offset,bdos_ofst
  149.     mov int0_offset,offset int0_trap
  150.     mov int4_offset,offset int4_trap
  151.     pop ds        ;restore the DS register
  152.  
  153. ;    (additional CP/M-86 initialization)
  154. ;|                                           |
  155. ;---------------------------------------------
  156.     ENDIF    ;not loader_bios
  157.  
  158.     IF    loader_bios
  159. ;---------------------------------------------
  160. ;|                                           |
  161.     ;This is a BIOS for the LOADER
  162.     push ds        ;save data segment
  163.     mov ax,0
  164.     mov ds,ax    ;point to segment zero
  165.     ;BDOS interrupt offset
  166.     mov bdos_offset,bdos_ofst
  167.     mov bdos_segment,CS ;bdos interrupt segment
  168. ;    (additional LOADER initialization)
  169.     pop ds        ;restore data segment
  170. ;|                                           |
  171. ;---------------------------------------------
  172.     ENDIF    ;loader_bios
  173.  
  174.     mov bx,offset signon
  175.     call pmsg    ;print signon message
  176.     mov cl,0    ;default to dr A: on coldstart
  177.     jmp ccp        ;jump to cold start entry of CCP
  178.  
  179. WBOOT:    jmp ccp+6    ;direct entry to CCP at command level
  180.  
  181.     IF    not loader_bios
  182. ;---------------------------------------------
  183. ;|                                           |
  184. int0_trap:
  185.     cli
  186.     mov bx,offset int0_trp
  187.     jmps int_halt
  188. int4_trap:
  189.     cli
  190.     mov bx,offset int4_trp
  191.     jmps int_halt
  192. int_trap:
  193.     cli        ;block interrupts
  194.     mov bx,offset int_trp
  195. int_halt:
  196.     mov ax,cs
  197.     mov ds,ax    ;get our data segment
  198.     call pmsg
  199.     pop bx        ;get offset
  200.     pop ax        ;print segment
  201.     push bx        ;save offset
  202.     call PHEX
  203.     mov cl,':'    ;colon
  204.     call CONOUT
  205.     pop ax        ;print offset
  206.     call PHEX
  207.     hlt        ;hardstop
  208.  
  209. PHEX:
  210.     push ax
  211.     mov al,ah
  212.     call PHXB    ;print upper byte
  213.     pop ax        ;restore to print lower byte
  214. PHXB:
  215.     push ax        ;save byte
  216.     mov cl,4    ;get high nibble
  217.     shr al,cl    ;into low bits
  218.     call PHXD    ;print digit
  219.     pop ax        ;restore byte
  220.     and al,0fh    ;isolate low nibble
  221. PHXD:
  222.     add al,90h    ;first half of conversion trick
  223.     daa
  224.     add al,40h    ;second half of same
  225.     daa
  226.     mov cl,al    ;now print digit
  227.     jmps CONOUT
  228. ;|                                           |
  229. ;---------------------------------------------
  230.     ENDIF    ;not loader_bios
  231.  
  232. ;*********************************************
  233. ;*                                           *
  234. ;*   CP/M Character I/O Interface Routines   *
  235. ;*                                           *
  236. ;*********************************************
  237.  
  238. CONST:        ;console status
  239.     in    al,cstat    ;get status byte
  240.     and    al,cimsk    ;check input mask
  241.     jz    const1        ;not ready yet...return al=0, ZF=1
  242.     or    al,0ffh        ;ready...return al=0FFh, ZF=0
  243. CONST1:
  244.     ret
  245.  
  246. CONIN:            ;console input
  247.     call CONST
  248.     jz CONIN    ;wait for RDA
  249.     in    al,cdata;get byte
  250.     and    al,7fh    ;strip parity
  251.     ret
  252.  
  253. CONOUT:        ;console output
  254.     in    al,cstat    ;get status
  255.     test    al,comsk    ;check output bits
  256.     jz    conout        ;loop till ready
  257.     mov    al,cl        ;setup
  258.     out    cdata,al    ;send character
  259.     ret        ;then return data
  260.  
  261. LISTOUT:        ;list device output
  262.     call    LISTST    ;get output status
  263.     jz    LISTOUT    ;wait for TBE
  264.     mov    al,cl    ;setup
  265.     out    ldata,al    ;send char
  266.     in    al,lstat    ;check for handshake received
  267.     and    al,limsk
  268.     jz    LISTOUT2    ;no handshake...exit
  269.     in    al,ldata    ;get handshake char
  270.     and    al,7fh        ;strip parity
  271.     cmp    al,'S'-40h    ;XOFF?
  272.     jnz    LISTOUT2    ;nope
  273.     mov    lstactive,0ffh    ;set list active flag
  274. LISTOUT2:
  275.     ret
  276.  
  277. LISTST:            ;poll list status
  278.     in    al,lstat    ;get status byte
  279.     and    al,lomsk    ;test output bits
  280.     jz    LISTST1        ;not ready...exit with al=0, zf=1
  281.     mov    al,lstactive    ;line ready...waiting for XON?
  282.     not    al
  283.     test    al,al
  284.     jnz    LISTST1        ;not waiting...say ready
  285.     in    al,lstat    ;check for handshake
  286.     and    al,limsk
  287.     jz    LISTST1        ;not yet...say still busy
  288.     in    al,ldata    ;got something...
  289.     and    al,7fh        ;strip parity
  290.     cmp    al,'Q'-40h    ;is it XON?
  291.     mov    al,0
  292.     jnz    LISTST1        ;no, return false
  293.     not    al        ;ready...exit with al=0ffh, zf=0
  294.     mov    lstactive,0    ;clear list active flag
  295. LISTST1:
  296.     test    al,al        ;make sure flags are set
  297.     ret
  298.  
  299. PUNCH:        ;write punch device
  300.     ret    ;is a "bit bucket"
  301.  
  302. READER:
  303.     mov    al,1ah    ;is an EOF source
  304.     ret
  305.  
  306. GETIOBF:
  307.     mov al,IOBYTE
  308.     ret
  309.  
  310. SETIOBF:
  311.     mov IOBYTE,cl    ;set iobyte
  312.     ret        ;iobyte not implemented
  313.  
  314. pmsg:
  315.     mov al,[BX]     ;get next char from message
  316.     test al,al
  317.     jz return    ;if zero return
  318.     mov CL,AL
  319.     call CONOUT      ;print it
  320.     inc BX
  321.     jmps pmsg    ;next character and loop
  322.  
  323. ;*********************************************
  324. ;*                                           *
  325. ;*          Disk Input/Output Routines       *
  326. ;*                                           *
  327. ;*********************************************
  328.  
  329. SELDSK:        ;select disk given by register CL
  330. ndisks    equ    2 ;number of disks (up to 16)
  331.     mov seekfg,0ffh    ;set seek flag
  332.     mov disk,cl    ;save disk number
  333.     mov bx,0000h    ;ready for error return
  334.     cmp cl,ndisks    ;n beyond max disks?
  335.     jnb return    ;return if so
  336.     mov ch,0    ;double(n)
  337.     mov bx,cx    ;bx = n
  338.     mov cl,4    ;ready for *16
  339.     shl bx,cl    ;n = n * 16
  340.     mov cx,offset dpbase
  341.     add bx,cx    ;dpbase + n * 16
  342. return:    ret        ;bx = .dph
  343.  
  344. HOME:    ;move selected disk to home position (Track 0)
  345.     mov cx,0    ;set disk i/o to track zero
  346.             ;**** fall through ****
  347. SETTRK: ;set track address given by CX
  348.     mov trk,CX
  349.     mov seekfg,0ffh    ;set seek flag
  350.     ret
  351.  
  352. SETSEC: ;set sector number given by cx
  353.     mov sect,CX
  354.     ret
  355.  
  356. SECTRAN: ;translate sector CX using table at [DX]
  357.     mov bx,cx
  358.     add bx,dx    ;add sector to tran table address
  359.     mov bl,[bx]    ;get logical sector
  360.     ret
  361.  
  362. SETDMA: ;set DMA offset given by CX
  363.     mov dma_adr,CX
  364.     ret
  365.  
  366. SETDMAB: ;set DMA segment given by CX
  367.     mov dma_seg,CX
  368.     ret
  369. ;
  370. GETSEGT:  ;return address of physical memory table
  371.     mov bx,offset seg_table
  372.     ret
  373.  
  374. ;*********************************************
  375. ;*                                           *
  376. ;*  All disk I/O parameters are setup:       *
  377. ;*     DISK     is disk number      (SELDSK) *
  378. ;*     TRK      is track number     (SETTRK) *
  379. ;*     SECT     is sector number    (SETSEC) *
  380. ;*     DMA_ADR  is the DMA offset   (SETDMA) *
  381. ;*     DMA_SEG  is the DMA segment  (SETDMAB)*
  382. ;*  READ reads the selected sector to the DMA*
  383. ;*  address, and WRITE writes the data from  *
  384. ;*  the DMA address to the selected sector   *
  385. ;*  (return 00 if successful,  01 if perm err)*
  386. ;*                                           *
  387. ;*********************************************
  388.  
  389. READ:
  390.     mov cl,10    ;set retry count
  391. READ1:
  392.     call STUP    ;set up unit/track/sector
  393.     mov al,3    ;send read command
  394.     call DLOOP
  395.     mov dx,datai    ;set port number
  396.     in al,dx    ;get back status
  397.     test al,8    ;check CRC flag
  398.     jz RDOK        ;no error...go get data
  399.     dec cl        ;got an error...count retrys
  400.     jnz READ2    ;some retrys left...continue
  401.     mov al,1    ;bad news....return error
  402.     ret
  403. READ2:
  404.     test cl,3    ;time for a re-seek?
  405.     jpo READ1    ;no, just reread
  406.     mov seekfg,0ffh    ;yes, set seek flag
  407.     call RESET    ;clear errors, home drive
  408.     jmps READ1    ;try read again
  409. RDOK:
  410.     mov cx,128    ;set byte counter
  411.     cld        ;set forward direction
  412.     push es        ;save extra segment
  413.     les di,dword ptr dma_adr    ;set dest index and segment
  414.     mov dx,cntrl
  415. RDLUP:
  416.     mov ax,40h    ;send "examine read buffer" command
  417.     out dx,al    ;to disk control port
  418.     in al,dx    ;get data byte
  419.     stos al        ;store it, bump pointer and count
  420.     mov al,41h    ;send "step read buffer" command
  421.     out dx,al    ;to controller
  422.     loop RDLUP    ;repeat 128 times
  423.     pop es        ;restore extra segment
  424.     mov al,0    ;return good status
  425.     out dx,al    ;also put controller in status mode
  426.     ret
  427.  
  428. WRITE:
  429.     mov cx,128    ;set 128 byte counter
  430.     cld        ;set forward direction
  431.     push ds        ;save current data segment
  432.     lds si,dword ptr dma_adr    ;set source index
  433. WRLUP:
  434.     lods al        ;get next byte
  435.     mov dx,datao
  436.     out dx,al    ;send to controller
  437.     mov al,31h    ;send "shift write buffer" command
  438.     mov dx,cntrl
  439.     out dx,al    ;to controller
  440.     mov al,0    ;remove command
  441.     out dx,al    ;(bit 0 must toggle to be seen)
  442.     loop WRLUP    ;repeat for sector length times
  443.     pop ds
  444. RTRYP:
  445.     call STUP    ;setup for write
  446.     in al,dx    ;check controller status
  447.     test al,10h    ;write protected?
  448.     jz TRYWR    ;no, continue
  449.     mov bx,offset prtmsg    ;say "protected"
  450.     call ERROR    ;and wait for user action
  451.     jmps RTRYP    ;retry if user hits return key
  452. TRYWR:
  453.     mov al,5    ;send write command
  454.     call DLOOP    ;to controller with wait
  455. WROK:
  456.     mov al,0    ;return good status
  457.     ret
  458.  
  459. ;*********************************************
  460. ;*                         *
  461. ;*          Disk Utility Routines         *
  462. ;*                         *
  463. ;*********************************************
  464. ;
  465. ;print an error message and wait for user response
  466. ;if control-c, then abort to cp/m, else return
  467. ;to caller and (usually) retry operation
  468. ERROR:
  469.     call PMSG    ;print an error message
  470.     call CONIN    ;wait for user response
  471.     push ax        ;save character
  472.     mov bx,offset crlf    ;echo cr, lf
  473.     call PMSG
  474.     pop ax        ;now look at char
  475.     cmp al,3    ;control-c?
  476.     jz ERR1        ;yes, return to cp/m
  477.     ret        ;else retry error'd operation
  478. ERR1:
  479.     mov cl,0    ;tell cp/m user 0, drive A
  480.     jmp ccp        ;bye-bye
  481.  
  482. ;Perform select and possibly seek logic for either a
  483. ;read or write operation.
  484. STUP:
  485.     mov al,0bh    ;issue "reset errors" command
  486.     call DLOOP    ;to controller with wait
  487.     mov al,disk    ;get drive number
  488.     mov cl,6    ;prepare to shift into
  489.     shl ax,cl    ;high 2 bits of cmd byte
  490.     or ax,sect    ;put sector number in low bits
  491.     mov dx,datao
  492.     out dx,al    ;send to controller
  493.     mov al,21h    ;issue "set unit/sector" command
  494.     call DLOOP
  495.     mov dx,datai
  496.     mov cx,100    ;set up delay loop
  497. STUP0:
  498.     mov bx,8000    ;inner delay loop
  499. STUP1:
  500.     in al,dx    ;get controller status
  501.     test al,20h    ;check "drive fail" (ready) flag
  502.     jz STUP2    ;no problem...continue
  503.     dec bx        ;count down inner delay loop
  504.     jnz STUP1
  505.     loop STUP0    ;count down outer delay loop
  506.     mov bx,offset rdymsg    ;timed out...complain
  507.     call error    ;and wait for response
  508.     jmps STUP    ;retry the whole mess
  509. STUP2:
  510.     mov al,0    ;clear seek flag
  511.     xchg al,seekfg    ;and fetch previous value
  512.     test al,al    ;was it set?
  513.     jnz stup3    ;yes, go do seek or home
  514.     ret        ;no seek needed...exit
  515. STUP3:
  516.     mov ax,trk    ;look at track number
  517.     test al,al    ;is it 0?
  518.     jz RESET    ;yes, do a home
  519.     mov dx,datao
  520.     out dx,al    ;otherwise, set new track
  521.     mov al,11h    ;give "set track" command
  522.     call DLOOP
  523.     mov al,9    ;then give "seek" command
  524.             ;**** fall through ****
  525. ;
  526. ;This routine issues a controller command and waits for completion
  527. DLOOP:
  528.     mov dx,cntrl
  529.     out dx,al    ;send command
  530.     mov al,0    ;strobe it off
  531.     out dx,al
  532. LOOP1:
  533.     in al,dx    ;get controller status
  534.     test al,1    ;check ready bit
  535.     jnz LOOP1    ;loop till ready
  536.     ret        ;then exit
  537. ;
  538. ;This routine issues a "clear" command followed by a "home" command
  539. RESET:
  540.     mov al,81h    ;send "clear"
  541.     call DLOOP
  542.     mov al,0dh    ;send "home"
  543.     jmps DLOOP
  544.  
  545.  
  546. ;*********************************************
  547. ;*                                           *
  548. ;*               Data Areas                  *
  549. ;*                                           *
  550. ;*********************************************
  551. data_offset    equ offset $
  552.  
  553.     dseg
  554.     org    data_offset    ;contiguous with code segment
  555. lstactive    db    0    ;set if list handshake active
  556. IOBYTE    db    0    ;i/o assignments (unused at present)
  557. seekfg    db    0    ;set to 0ffh if next access requires seek
  558. disk    db    0    ;disk number
  559. trk    dw    0    ;track number
  560. sect    dw    0    ;sector number
  561. dma_adr    dw    0    ;DMA offset from DS
  562. dma_seg    dw    0    ;DMA Base Segment
  563.  
  564. signon     db    cr,lf,cr,lf
  565.     db    'CP/M-86 Version 1.0 for iCom 3712',cr,lf
  566.     db    'System Generated 04/30/81'
  567.     db    cr,lf,0
  568.  
  569. int_trp    db    cr,lf
  570.     db    'Interrupt Trap Halt at ',0
  571.  
  572. int0_trp db    cr,lf
  573.     db    'Divide Trap Halt at ',0
  574.  
  575. int4_trp db    cr,lf
  576.     db    'Overflow Trap Halt at ',0
  577.  
  578. rdymsg    db    cr,lf
  579.     db    'Drive not ready',0
  580.  
  581. prtmsg    db    cr,lf
  582.     db    'Drive write protected',0
  583.  
  584. crlf    db    cr,lf,0
  585.  
  586. ;    System Memory Segment Table
  587.  
  588. segtable db 1    ;1 segment
  589.     dw tpa_seg    ;1st seg starts after BIOS
  590.     dw tpa_len    ;and extends to 0ffff
  591.  
  592.     include singles.lib ;read in disk definitions
  593.  
  594. loc_stk    rw  32    ;local stack for initialization
  595. stkbase    equ offset $
  596.  
  597. lastoff    equ offset $
  598. tpa_seg    equ (lastoff+0400h+15) / 16
  599. tpa_len    equ 0fffh - tpa_seg    ; 64K less 16 byte reset vector less cp/m size
  600.  
  601.     db 0    ;fill last address for GENCMD
  602.  
  603. ;*********************************************
  604. ;*                                           *
  605. ;*          Dummy Data Section               *
  606. ;*                                           *
  607. ;*********************************************
  608.     dseg    0    ;absolute low memory
  609.     org     0    ;(interrupt vectors)
  610. int0_offset    rw    1
  611. int0_segment    rw    1
  612. ;    pad to overflow trap vector
  613.         rw    6
  614. int4_offset    rw    1
  615. int4_segment    rw    1
  616. ;    pad to system call vector
  617.     rw    2*(bdos_int-5)
  618.  
  619. bdos_offset    rw    1
  620. bdos_segment    rw    1
  621.     END
  622.