?? prnusb.asm
字號(hào):
;this version queries the printer status before executing the output
;command from DOS.
;it will not report, if paper empty while executing the command,
;the printer will send NAKs and this driver will wait for the
;situation to be cleared by the user - who probably is interested
;whether his print is done
;
;****************************************************************
;* This is a Printer Device Driver for the DosUHCI driver *
;* *
;* Compile: tasm prnusb.asm *
;* Link: tlink prnusb.obj /t,prnusb.sys *
;****************************************************************
cseg segment para public 'code'
org 0000h
;showflag equ 1
showflag equ 0
printer proc far
assume cs:cseg, es:cseg, ds:cseg
;structures ****************************************************
rh struc ;request header
rh_len db ? ;len of packet
rh_unit db ? ;unit code
;(block devices only)
rh_cmd db ? ;device driver command
rh_status dw ? ;returned by device driver
rh_res1 dd ? ;reserved
rh_res2 dd ? ;reserved
rh ends ;
rh0 struc ;Initialization (command 0)
rh0_rh db size rh dup (?) ;fixed portion
rh0_nunits db ? ;number of units
;(block devices only)
rh0_brk_ofs dw ? ;offset address for break
rh0_brk_seg dw ? ;segment address for break
rh0_bpb_tbo dw ? ;offset address of pointer
;to BPB array
rh0_bpb_tbs dw ? ;segment address of pointer
;to BPB array
rh0_drv_ltr db ? ;first available drive
;(DOS 3+) (block only)
rh0 ends ;
rh3 struc ;IOCTL_INPUT (command 3)
rh3_rh db size rh dup(?) ;fixed portion
rh3_media db ? ;media descriptor from DPB
rh3_buf_ofs dw ? ;offset address of
;data transfer area
rh3_buf_seg dw ? ;segment address of
;data transfer area
rh3_count dw ? ;transfer count
;(sectors for block)
;(bytes for character)
rh3_start dw ? ;start sector number
;(block only)
rh3 ends ;
rh8 struc ;OUTPUT (command 8)
rh8_rh db size rh dup(?) ;fixed portion
rh8_media db ? ;media descriptor from DPB
rh8_buf_ofs dw ? ;offset address of
;data transfer area
rh8_buf_seg dw ? ;segment address of
;data transfer area
rh8_count dw ? ;transfer count
;(sectors for block)
;(bytes for character)
rh8_start dw ? ;start sector number
;(block only)
rh8 ends ;
rh9 struc ;OUTPUT_VERIFY (command 9)
rh9_rh db size rh dup(?) ;fixed portion
rh9_media db ? ;media descriptor from DPB
rh9_buf_ofs dw ? ;offset address of
;data transfer area
rh9_buf_seg dw ? ;segment address of
;data transfer area
rh9_count dw ? ;transfer count
;(sectors for block)
;(bytes for character)
rh9_start dw ? ;start sector number (block only)
rh9 ends ;
rh10 struc ;Output_Status (command 10)
rh10_len db ? ;len of packet
rh10_unit db ? ;unit code
;(block devices only)
rh10_cmd db ? ;device driver command
rh10_status dw ? ;returned by device driver
rh10_res1 dd ? ;reserved
rh10_res2 dd ? ;reserved
rh10 ends ;
rh12 struc ;IOCTL_OUTPUT (command 12)
rh12_rh db size rh dup(?) ;fixed portion
rh12_media db ? ;media descriptor from DPB
rh12_buf_ofs dw ? ;offset address of
;data transfer area
rh12_buf_seg dw ? ;segment address of
;data transfer area
rh12_count dw ? ;transfer count
;(sectors for block)
;(bytes for character)
rh12_start dw ? ;start sector number
;(block only)
rh12 ends ;
rh16 struc ;OUTPUT_BUSY (command 16)
rh16_rh db size rh dup (?) ;fixed portion
rh16_media db ? ;media descriptor
rh16_buf_ofs dw ? ;offset address of
;data transfer area
rh16_buf_seg dw ? ;segment address of
;data transfer area
rh16_count dw ? ;byte count returned
;from device driver
rh16 ends ;
;commands that do not have unique portions to the request header:
; INPUT_STATUS (command 6)
; INPUT_FLUSH (command 7)
; OUTPUT_STATUS (command 10)
; OUTPUT_FLUSH (command 11)
; OPEN (command 13)
; CLOSE (command 14)
; REMOVEABLE (command 15)
;
;****************************************************************
;* MAIN PROCEDURE CODE *
;****************************************************************
begin:
;****************************************************************
;* DEVICE HEADER REQUIRED BY DOS *
;****************************************************************
next_dev dd -1 ;no other drivers following
attribute dw 08000h ;char
strategy dw dev_strategy ;Strategy routine address
interrupt dw dev_interrupt ;Interrupt routine address
dev_name db 'PRNUSB ' ;name of our Printer driver
;****************************************************************
;* WORK SPACE FOR OUR DEVICE DRIVER *
;****************************************************************
rh_ofs dw ? ;offset address of the request header
rh_seg dw ? ;segment address of the request header
devicenr db 1
endpointnr db 2
bytes_to_print dw 0
bytes_done dw 0
retry_count dw 0
showptr dw 0
;define data type of URB
urbstruc struc
transaction_token db ? ;control, in, out
chain_end_flag db ?
dev_add db ?
end_point db ?
error_code db ? ;error codes returned by dosuhci
status db ? ;status byte returned by controller
transaction_flags dw ? ;reserved
buffer_off dw ? ;for in/out
buffer_seg dw ? ;for in/out
buffer_length dw ? ;for in/out
actual_length dw ? ;for in/out
setup_buffer_off dw ? ;for control
setup_buffer_seg dw ? ;for control
start_frame dw ? ;reserved
nr_of_packets dw ? ;iso
int_interval db ? ;int
error_count db ? ;reserved
timeout dw ? ;reserved
next_urb_off dw ? ;reserved
next_urb_seg dw ? ;reserved
urbstruc ends ;32 byte long
;define urb with this type
urb urbstruc <>
class_req db 0A1h,01h
dw 0000h,0000h,0001h
temp_buffer db 8 dup(0)
prtstatus db 0
;****************************************************************
;* THE STRATEGY PROCEDURE *
;****************************************************************
dev_strategy: mov cs:rh_seg,es ;save the segment address
mov cs:rh_ofs,bx ;save the offset address
ret ;return to DOS
;****************************************************************
;* THE INTERRUPT PROCEDURE *
;****************************************************************
;device interrupt handler - 2nd call from DOS
dev_interrupt:
cld ;save machine state on entry
pushf
push ds
push es
push ax
push bx
push cx
push dx
push di
push si
mov ax,cs:rh_seg ;restore ES as saved by STRATEGY call
mov es,ax ;
mov bx,cs:rh_ofs ;restore BX as saved by STRATEGY call
;jump to appropriate routine to process command
mov al,es:[bx].rh_cmd ;get request header header command
if showflag
mov cl,al
call show ;show commands sent by DOS
endif
;rol al,1 ;times 2 for index into word table
shl al,1 ;times 2 for index into word table
lea di,cmdtab ;function (command) table address
mov ah,0 ;clear hi order
add di,ax ;add the index to start of table
jmp word ptr[di] ;jump indirect
;CMDTAB is the command table that contains the word address
;for each command. The request header will contain the
;command desired. The INTERRUPT routine will jump through an
;address corresponding to the requested command to get to
;the appropriate command processing routine.
CMDTAB label byte ;* = char devices only
dw INITIALIZATION ; initialization
dw done ; media check (block only)
dw done ; build bpb
dw done ; ioctl in
dw done ; input (read)
dw done ;*non destructive input no wait
dw done ;*input status
dw done ;*input flush
dw OUTPUT ; output (write)
dw OUTPUT ; output (write) with verify
dw done ;*output status
dw done ;*output flush
dw done ; ioctl output
dw done ; device open
dw done ; device close
dw done ; removeable media
dw OUTPUT ; output til busy
;****************************************************************
;* YOUR LOCAL PROCEDURES *
;****************************************************************
do_out proc near
mov bytes_done,0
mov retry_count,0
repeat_out:
mov ax,es:[bx].rh8_count ;load output count
cmp ax,bytes_done ;all done?
ja not_all_done
mov cs:urb.status,0
ret ;exit function
not_all_done:
sub ax,bytes_done ;how many left?
mov bytes_to_print,ax ;bytes_to_print
cmp bytes_to_print,64
jbe bytes_ok ;less or equal the max
mov bytes_to_print,64 ;max packet size for bulk
bytes_ok: ;also retry label!
;set up URB for out transaction
mov urb.transaction_token,0E1h
mov urb.chain_end_flag,0
mov al,devicenr
mov urb.dev_add,al
mov al,endpointnr
mov urb.end_point,al
mov urb.error_code,0
mov urb.status,0
mov urb.transaction_flags,0
mov ax,es:[bx].rh8_buf_ofs ;load offset address
add ax,bytes_done ;start at this offset if 64 max
mov urb.buffer_off,ax
mov ax,es:[bx].rh8_buf_seg ;load segment address
mov urb.buffer_seg,ax
;mov ax,es:[bx].rh8_count ;load output count
mov ax,bytes_to_print
mov urb.buffer_length,ax
mov urb.actual_length,64
mov urb.setup_buffer_off,0
mov urb.setup_buffer_seg,0
mov urb.start_frame,0
mov urb.nr_of_packets,0
mov urb.int_interval,0
mov urb.error_count,0
mov urb.timeout,0
mov urb.next_urb_off,0
mov urb.next_urb_seg,0
;now call DosUHCI
mov dx,offset urb
int 65h
;transaction successful?
inc retry_count ;always inc error counter
cmp retry_count,32000 ;allow for 32000 NAK's
jae error_out ;yes, report error to DOS
cmp urb.status,0 ;transaction OK?
je transaction_ok ;yes
cmp urb.status,88h ;NAK?
jne error_out ;no, different error - exit without retry
jmp bytes_ok ;got NAK, retry
transaction_ok:
mov retry_count,0 ;reset error counter
mov ax,bytes_to_print
add bytes_done,ax ;count how many done
jmp repeat_out
error_out: ;if urb.status is <> 0, an error will be reported to DOS
mov ax,800Ah ;return write error
if 0 ;can't get DOS to handle these errors right
xor ax,ax ;clear
mov bl,urb.status ;readstatus destroys urb.status
push bx
call readstatus ;find out if printer reports an error
pop bx
mov urb.status,bl ;restore - need in 8 command function
cmp ax,0
je test_for_done ;no error found
ret ;error found
test_for_done:
;no error, continue - forever!!!
mov retry_count,0
jmp bytes_ok
endif
ret
do_out endp
;***************************************************************
;query printer for errors
;returns status read in prtstatus and DOS-return word in AX reg
;set carry if status not read successfully
readstatus proc near
push es
push bx
mov cs:retry_count,0
repeat_get_status:
;set up URB for ctrl+in+out transaction
mov cs:urb.transaction_token,2Dh
mov cs:urb.chain_end_flag,0
mov al,cs:devicenr
mov cs:urb.dev_add,al
mov cs:urb.end_point,0 ;control e.p.
mov cs:urb.error_code,0
mov cs:urb.status,0
mov cs:urb.transaction_flags,0
mov ax,offset cs:temp_buffer ;load temp buffer offset address
mov cs:urb.buffer_off,ax
mov ax,cs ;load segment address
mov cs:urb.buffer_seg,ax
mov cs:urb.buffer_length,8
mov cs:urb.actual_length,8
mov ax,offset cs:class_req
mov cs:urb.setup_buffer_off,ax
mov ax,cs
mov cs:urb.setup_buffer_seg,ax
mov cs:urb.start_frame,0
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -