home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_32.arc / DRIVER.ASM < prev    next >
Assembly Source File  |  1979-12-31  |  8KB  |  276 lines

  1. ;************************************************************************
  2. ;                                    *
  3. ;         PARALLEL PRINTER DRIVER                *
  4. ;                                     *
  5. ;         Written by Don Fletcher                *
  6. ;                                    *
  7. ;************************************************************************
  8. ;
  9. ;
  10. ;================== DEVICE HEADER BLOCK =================================
  11. ;
  12. ;    All device drivers start with a defined 18 byte block
  13. ;    of data called the 'Device Header', which must start at
  14. ;    origin 0 within the device driver segment.
  15. ;
  16. CODE    SEGMENT PUBLIC 'CODE'    
  17. DEVICE    Proc    far
  18.     ASSUME    CS:CODE,DS:CODE,ES:CODE
  19. ;
  20.     Org    0
  21. ;
  22. ;    Data Constants
  23. ;
  24. ;    If you have a monochrome display and printer adapter,
  25. ;    add 44H to the three addresses that follow.
  26. ;
  27. Print_Dat    Equ    378H    ;or 3BCH - Printer data port
  28. Print_Stat    Equ    379H    ;or 3BDH - Printer status port
  29. Print_Out    Equ    37AH    ;or 3BEH - Status output port
  30. ;
  31. Busy        Equ    80H    ;Busy test mask
  32. Strobe_Hi    Equ    0DH    ;Strobe output high
  33. Strobe_Low    Equ    0CH    ;Strobe output low
  34. ;
  35. ;
  36. ;
  37. ;    Within this 'Device Header' block must be:
  38. ;
  39. ;    1) The Device Chain Pointer -- Double word, set to -1,-1
  40. ;       (FFFF:FFFF) in your code.  MS-DOS uses this location
  41. ;       for a double wide pointer to the next device in the
  42. ;       chain.
  43. ;
  44.     DW    -1,-1        ;Pointer to the next device
  45. ;
  46. ;    2) The Device Header Attribute word -- 16 single bit fields
  47. ;       that tell MS-DOS the type and capabilities of the device
  48. ;       driver.  We will use the standard character device for
  49. ;       our printer driver - 8000H.  
  50. ;
  51.     DW    8000H        ;Standard Character device
  52. ;
  53. ;    3) The Strategy entry pointer -- Holds the entry offset
  54. ;       address if the Strategy code.  Since the offset is only
  55. ;       16 bits, the strategy code must be in the same segment as
  56. ;       the device header block.
  57. ;
  58.     DW    Strategy    ;Strategy code offset
  59. ;
  60. ;    4) The Interrupt entry pointer -- Sixteen bit entry offset
  61. ;       for the Interrupt code.  As with the strategy code above,
  62. ;       the Interrupt code must be in the same segment as the 
  63. ;       device header block.
  64. ;
  65.     DW    Interrupt;Interrupt code offset
  66. ;
  67. ;    5) An 8 byte block which, if a character driver, contains the 
  68. ;       name of the device driver padded with blanks.  If a block mode
  69. ;       driver, only the first byte is used to indicate how many 
  70. ;       separate devices are supported by this driver.
  71. ;
  72.     DB    'SAMPLE  '    ;Device name
  73. ;
  74. ;
  75. ;=================== REQUEST HEADER BLOCK ==============================
  76. ;
  77. ;    When MS-DOS invokes a device driver, commands and data to the
  78. ;    device driver are assembled into a Request header.  A pointer
  79. ;    to this data is passed to the device driver in the ES:BX register
  80. ;    pair.  Since the memory allocation is dynamic in this case, a
  81. ;     block of equates must be allocated referenced to the above 
  82. ;    pointer.  By far the easiest method of accessing this block
  83. ;    of data is to use the Structure command for the MS assembler.
  84. ;
  85. Request equ    ES:[DI]    ;Set base address of Header block
  86. ;
  87. Reqhdr    Struc
  88. Numb    DB    ?    ;num of bytes in block        -byte 0
  89. Unit    DB    ?    ;unit number [block drivers]    -byte 1
  90. Cmmd    DB    ?    ;command byte            -byte 2
  91. Stat    DW    ?    ;return status             -bytes 3-4
  92. Dos    DB    4 dup(?);addr link used by DOS        -bytes 5-8
  93. Intlnk    DB    4 dup(?);linkage to other blocks    -bytes 9-12
  94. ;
  95. ;    After the above 'standard' locations, come the following
  96. ;    locations in the Header block used for init, read and write
  97. ;    operations. 
  98. ;
  99. Media    DB    ?    ;Media Descripter        -byte 13
  100. Address DD    ?    ;Data transfer address        -bytes 14-17
  101. Count    DW    ?    ;Byte count value        -bytes 18-19
  102. Reqhdr    Ends
  103. ;
  104. ;=================== COMMAND OFFSET TABLE =============================
  105. ;
  106. ;    Jump table for the commands passed in byte 2 (Cmmd) of the
  107. ;    Request Header Block.
  108. ;
  109. Jumptbl:
  110.     DW    Allinit        ;Init device driver           # 0
  111.     DW    Exitt        ;(media check) block command  # 1
  112.     DW    Exitt        ;(Build Bios Parm Block)      # 2
  113.     DW    Exitt        ;(IOCTL for input) not sup    # 3
  114.     DW    Exitt        ;(Input - read) not used      # 4
  115.     DW    Exitt        ;(Input non destructive)      # 5
  116.     DW    Exitt        ;(Input Status)               # 6
  117.     DW     Exitt        ;(Input Flush)                  # 7
  118.     DW    Outchar        ;Output character           # 8
  119.     DW    Outchar        ;Output char with verify      # 9
  120.     DW    Outstat        ;Output status                # 10
  121.     DW    Exitt        ;(Output flush)              # 11
  122.     DW    Exitt        ;(IOCTL for output)           # 12
  123.     DW    Exitt        ;(Device open)              # 13
  124.     DW    Exitt        ;(Device close)               # 14
  125.     DW    Exitt        ;(Removable media)          # 15
  126. ;
  127. ;
  128. ;=================== STRATEGY CODE BLOCK ===============================
  129. ;
  130. ;    The sole purpose of the Strategy code is to accept and store
  131. ;    the passed pointer to the Request Header Block.  After MS-Dos
  132. ;    calls the Strategy code in the correct device driver, it then
  133. ;    calls the Interrupt code to execute the command.
  134. ;
  135. Savadd    DD    ?        ;reserve a double word for the pointer
  136. ;
  137. ;    Pointer to request header block is in ES:BX registers
  138. ;    saved in Savadd area. 
  139. ;
  140. Strategy proc    far
  141. ;
  142.     Mov    CS:word ptr [Savadd],BX        ;Save pointer address
  143.     Mov    CS:word ptr [Savadd + 2],ES
  144.     Ret
  145. Strategy  endp
  146. ;
  147. ;
  148. ;=================== INTERRUPT ROUTINES ===============================
  149. ;
  150. ;    The Interrupt code area handles the actual work of the device
  151. ;    driver.  The command is decoded, then done, any errors are
  152. ;    returned to MS-DOS.  The pointer to the interrupt commands
  153. ;    is contained in Savadd in the form OFFSET:Segment.
  154. ;
  155. Interrupt  proc  far
  156. ;
  157.     Push    AX        ;save all registers
  158.     Push    BX
  159.     Push    CX
  160.     Push    DX
  161.     Push    BP
  162.     Push    SI
  163.     Push    DI
  164.     Push    DS
  165.     Push    ES
  166.     Pushf
  167. ;
  168.     Push    CS        ;Since we're in only one segment,
  169.     Pop    DS        ;equate CS and DS making local data
  170.                 ;available
  171. ;
  172.     Les    DI,[Savadd]    ;ES:DI = Request Header block pointer
  173.     Xor    BH,BH        ;clear AH
  174.     Mov    BL,Request.Cmmd     ;get the command byte
  175. ;
  176.     Cmp    BX,16        ;Check that command is in range
  177.     Jle    Exx        ;OK
  178.     Jmp    Exitt        ;Error exit
  179. ;
  180. Exx:    Shl    BX,1        ;Multiply by 2 and go to command
  181. ;
  182.     Call    Word ptr [BX+Jumptbl]    ;Return AX = error status
  183.     Jmp    Exit            ;Go back to MS-Dos
  184. ;
  185. Exitt:        ;Unsupported commands
  186.     Mov    AX,3            ;Signal command error
  187.     Or    AX,8000H        ;Add error bit 
  188.  
  189. Exit:        ;Common exit return AX contains error status
  190.     Les    DI,[Savadd]        ;Restore pointer
  191.     Or    AX,100H            ;Set the done bit
  192.     Mov    Request.Stat,AX        ;put error status in block
  193.     Popf                ;Restore all registers and flags
  194.     Pop    ES
  195.     Pop    DS
  196.     Pop    DI
  197.     Pop    SI
  198.     Pop    BP
  199.     Pop    DX
  200.     Pop    CX
  201.     Pop    BX
  202.     Pop    AX
  203.     Ret                ;Go back to MS-Dos
  204.  
  205.  
  206. Outchar proc near    ;Output character(s) to printer
  207. ;
  208.     Lds    BX,[Request.Address]    ;Get pointer to transferred data
  209.     Mov    CX,[Request.Count]    ;Get byte transfer count
  210. ;
  211. Outlp:    Mov    AL,DS:[BX]        ;Go get character
  212.     Call    Prntout            ;Print it
  213.     Inc    BX            ;Point to next character
  214.     Dec    CX            ;Decrement character pointer
  215.     Jnz    Outlp            ;Repeat until CX = 0
  216. ;
  217. ;    Number of bytes passed is the number of bytes printed
  218. ;    which is already in the proper location within the 
  219. ;    Request Header Block.
  220. ;
  221.     Xor    AX,AX            ;No errors
  222.     Ret                ;Exit
  223. Outchar Endp
  224. ;
  225.  
  226.  
  227. Outstat proc near    ;Get printer status
  228. ;
  229.     Mov    DX,Print_Stat    ;Point to 'Input Status' Port
  230.     In    AL,DX        ;Read the printer status
  231.     Shl    AX,1        ;Put busy status bit in proper location
  232.     Shl    AX,1
  233.     Not    AX        ;Invert busy bit
  234.     And    AX,200H        ;Clear all but busy bit
  235.     Ret            ;Go back
  236. Outstat Endp
  237. ;
  238. ;
  239. Prntout proc near    ;Character output is in AL
  240. ;
  241. ;
  242.     Mov    DX,Print_Dat    ;Address of 'Output Data' Port
  243.     Out    DX,AL        ;Output the char to be printed
  244. ;
  245. ;    Check the input status
  246. ;
  247.     Mov    DX,Print_Stat    ;Address of 'Input Status' Port
  248. Wait:    In    AL,DX        ;Read the printer status
  249.     Test    AL,Busy        ;Check the busy bit
  250.     Jz    Wait        ;Stay in loop until printer isn't busy
  251. ;
  252. ;    When we reach here, the printer isn't busy
  253. ;
  254.     Mov    DX,Print_Out    ;Address of 'Output control' port
  255.     Mov    AL,Strobe_Hi    ;Strobe bit = 1
  256.     Out    DX,AL        ;Strobe the printer
  257.     Mov    AL,Strobe_Low    ;Strobe bit = 0
  258.     Out    DX,AL        ;Turn Printer Strobe off
  259.     Ret            
  260. Prntout    Endp
  261. Allinit proc near     ;Called once, must return end address of 
  262.             ;code and proper status
  263. ;
  264.     Mov    Request.Address,offset Allinit    ;End of program code
  265.     Mov    Request.Address+2,CS        ;Segment
  266.     Xor    AX,AX                ;no errors
  267.     Ret
  268. Allinit endp
  269. ;
  270. Interrupt  Endp
  271. Device    Endp
  272. Code    Ends
  273.     End
  274.  
  275.