⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prnusb.asm

📁 DOS下的USB驱动源码,包括UHCI
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -