|
USB in DOS
I have been getting a lot of emails asking about USB and I apoligize if I haven't gotten back to your emails yet.
You can get the two files at pciusb.cpp and pciusb.h. There are lots of comments and a full working USB stack. If you study this code a bit, I think it will help you greatly. Do remember that this code is emulating hardware. i.e.: This code is the hardware side of the USB. Your code is the software side.
I am currently working on my USB book that does not use the BIOS or any other "outside" source. Simply your code only. Some items included are:
- PCI USB root hub detection.
- stack frame.
- descriptors and configure.
- data in and data out.
- also includes detailed information on a few USB items included a flash disk (Thumb Drive).
- I have been using the Beagle USB Protocol Analyzer
from Total Phase for my research, and will be including a chapter about using a protocol analyzer, such
as this one, in your usb development.
Please be patient, for I must do this in my spare time and it seems I have less and
less spare time every day :-).
Update: I have been able to make good progress on this book/tutorial. I hope to have another announcement
soon saying that it is almost complete and ready for review.
The below code is for DOS and is not complete by any means. I quickly put it together with the idea of returning
and fixing it. However, I never got back to it. From comments from you, it seems it is worse than I remember :-).
Please realize that the code below contains errors and things that are just absolutely wrong. I am still including
it here for the moment. As soon as my book is out, I will replace this following code.
Thank you for your patience.
Side Note: The below code uses the PCI BIOS to scan for and retrieve information about a USB device. If you would like to not use the PCI BIOS, and would like to find out more about how a USB stack frame works, then have a look at the pciusb[.cc|.cpp] and pciusb.h files included with the source of
bochs. I wrote and maintain these two files, which show how the USB hardware actually works. As of this writing, I have a lot more code that I would like to add to the collection, but need to "tweak" a few more things. Anyway, check it out, it may help you with your USB programming.
Here is a little bit of code to detect the USB ports and the status of these ports. It isn't commented much, and no where near complete, but it should help you out a little bit.
Thanks goes to Dieter Pawelczak and Jan Axelson for thier help. Have a look at my books page for Jan's book on USB.
This code is not complete and even has a few pascal comments and code. However, it should run under a DOS box and display the PCI version, and all Root Hubs connected to it.
However, please take into consideration that I do not take any responibility for what this code may or may not do. It has not been tested on more than one machine, so it might be that machine dependant.
This code uses this binary file (required) to identify each item.
It is simply a list of vendors and parameters "compiled" from this text file.
Only the first of the two is needed, but you would benefit from them both.
Let me know if you have any questions or comments about this code. I would appreciate any comments and/or documentation that will help the progress of this code. And as you can see, I leave credit where credit is due (smile)
(the following code was assembled with NBASM v24.9x)
; =-=-=-=-=-=-=-=-=- CUT HERE -=-=-=-=-=-=-=-=-=
;
; assembled with NBASM v24.9x
; http://www.frontiernet.net/~fys/newbasic.htm
;
; I suggest you don't run this program with anything plugged in to the root hubs.
; This program tends to confuse the items, and they go into a reset loop....
;
;
.model tiny
.code
.386P
; =-=-=-=-=- includes
include usb.inc ; <---- see below
org 100h
; =-=-=-=-=- resize memory, etc.
.start
; =-=-=-=-=- Make sure is .386+
;;;;;;
; this part is commented out. It will not run in a DOS window under Windows.
; =-=-=-=-=- Detect V86 mode
; smsw ax ; store machine status word (.386P !!)
; and ax,1 ;
; jz short notv86mode ;
; mov si,offset v86_mode_s ;
; call prtstring ;
; .exit ;
;notv86mode:
; =-=-=-=-=- Startup string
; print startup string here. (Cosmetic)
; =-=-=-=-=- Print detect string
mov si,offset DetectS ; print finding PCI BIOS
call prtstring ;
; =-=-=-=-=- Detect PCI BIOS
mov ax,0B101h ; Detect PCI BIOS
int 1Ah ; on return bh:bl = version (BCD)
jnc short FoundPCI ;
mov si,offset PCIBoisNS ; not found, so post
call prtstring ;
.exit 1 ; and exit with RC = 1
; =-=-=-=-=- Found PCI BIOS
FoundPCI: mov si,offset PCIBoisFS ; found it, cont.
call prtstring ;
xor ah,ah ;
mov al,bh ;
call PrtHexN ; print major version
mov ah,02 ;
mov dl,'.' ; .
int 21h ;
xor ah,ah ;
mov al,bl ;
call PrtHexN ; print minor version
; =-=-=-=-=- Find USB devices
mov word dev_index,00h ; start with 0
FindUSBL: call FindUSB ;
or ah,ah ; if ah = !0, then no more
jnz short usb_done ;
;;;; if IOAddr < 100h then write to port + 20h = 120h ???
; =-=-=-=-=- Try to enable current PCI port found
mov si,offset enable_s ;
call prtstring ;
call pci_enable ; enable PCI->USB port
jnc short pci_enable_good ;
mov si,offset e_bad_s ; print bad_enable string
call prtstring ;
.exit ; and exit to DOS
pci_enable_good: ;
mov si,offset e_good_s ;
call prtstring ;
; =-=-=-=-=- Allocate Frame List Buffer
mov dx,IOAddr ; dx -> IOaddr space
call alloc_f_list ;
jnc short frame_ok ;
mov si,offset no_memory_s ;
call prtstring ;
jmp short usb_get_next ;
frame_ok: ;
; =-=-=-=-=- Try to enable all USB ports on current hub (1 and 2)
mov dx,IOAddr ; dx -> IOaddr space
call usb_enable ; enable USB ports
; =-=-=-=-=- Get/Print status of current PCI port found
mov dx,IOAddr ; dx -> IOaddr space
call usb_status ; print status
; does nothing, yet. I got to here with my research
; and have yet to come back to it. :-)
call get_dev_id
; =-=-=-=-=- get int number
; call usb_get_int_num
; ditto
usb_get_next:
inc word dev_index ;
jmp short FindUSBL ; continue on to next device
usb_done:
.exit
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; finds a USB card/hub on given PCI index
; on entry:
; dev_index = index
; on exit:
; ah = 00h if card found
FindUSB proc near uses bx cx dx si di
mov si,dev_index
mov ax,0B103h ; find PCI CLASS
mov ecx,000C0300h ; (USB = base=C, sub=3)
int 1Ah ;
jnc short UFoundOne ; on return: bh = bus
mov ah,01 ; bl = dev num/func num
ret ;
UFoundOne: mov si,offset FoundUSBTS ; print found USB controller
call prtstring ;
mov bus_num,bh ; save bus/dev/function
mov dev_func,bl ;
xor di,di ; read word at 0000h (Vendor ID)
call ReadPCIW ; read it (returns in AX)
mov VendorID,ax ; save it
mov di,02h ; read word at 0002h (Device ID)
call ReadPCIW ; read it (returns in AX)
mov DeviceID,ax ; save it
call dev_names ; get vendor and device names
mov si,offset VendorIDS ;
call prtstring ;
mov ax,VendorID ;
call prthex ; print VendorID
mov si,offset Vendor_N ; print vendor name
call prtstring ;
mov si,offset DeviceIDS ; print device type
call prtstring ;
mov ax,DeviceID ;
call prthex ; print DeviceID
mov si,offset Device_N ; print device name
call prtstring ;
mov si,offset BusNumberS ;
call prtstring ;
mov al,bus_num ; bh = Bus Number
xor ah,ah ;
call prthex ; print Bus Number
mov dl,'/' ; print a slash
mov ah,06 ;
int 21h ;
mov al,dev_func ; bl = Dev Number
shr al,03 ; (bits 7-3)
xor ah,ah ;
call prthex ; print Dev Number
mov dl,'/' ; print a slash
mov ah,06 ;
int 21h ;
mov al,dev_func ; bl = Func Number
and al,00000111b ; (bits 2-0)
xor ah,ah ;
call prthex ; print Func Number
mov si,offset CommandRS
call prtstring
mov di,04h ; read word at 0004h (Command Reg)
call ReadPCIW ; read it (returns in AX)
call prthex ;
mov si,offset StatusRS
call prtstring
mov di,06h ; read word at 0006h (Status Reg)
call ReadPCIW ; read it (returns in AX)
call prthex ;
mov si,offset RevisionS
call prtstring
mov di,08h ; read byte at 0008h (Revision Byte)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov si,offset ClassCodeS
call prtstring
mov di,0Bh ; read byte at 000Bh (Class)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov dl,'/' ; print a slash
mov ah,06 ;
int 21h ;
dec di ; read byte at 000Ah (Sub Class)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov dl,'/' ; print a slash
mov ah,06 ;
int 21h ;
dec di ; read byte at 0009h (Program Inter.)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov si,offset CacheS ;
call prtstring ;
mov di,0Ch ; read byte at 000Ch (Cache Line Size)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov si,offset BusLatS ;
call prtstring ;
mov di,0Dh ; read byte at 000Dh (Bus Latency)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov si,offset HeaderS
call prtstring
mov di,0Eh ; read byte at 000Eh (Header Type)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov si,offset SelfTestS
call prtstring
mov di,0Fh ; read byte at 000Fh (Self Test)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov si,offset IOPortsS
call prtstring
; don't do high word???
;mov di,22h ; read word at 0022h (base address 4)
;call ReadPCIW ; read it (returns in AX)
;call prthex ;
mov di,20h ; read word at 0020h (base address 4)
call ReadPCIW ; read it (returns in AX)
and ax,0FFFEh ; clear bit 0 ???
mov IOAddr,ax ; save if for testing the devices
call prthex ;
push ax ; save address space start
mov dl,'-' ;
mov ah,02 ;
int 21h ;
pop ax ;
add ax,31 ; print address space end
call prthex ;
mov si,offset IRQNumS ;
call prtstring ;
mov di,3Ch ; read byte at 000Fh (IRQ #)
call ReadPCIB ; read it (returns in AX)
call prthexn ;
mov si,offset IntNumS ;
call prtstring ;
mov di,3Dh ; read byte at 000Fh (INT #)
call ReadPCIB ; read it (returns in AX)
add al,09h ; (A-D)
call prthexn ;
mov ah,00 ; found one, continue
ret
FindUSB endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io space start
; on exit
; nothing
usb_status proc near uses all
mov si,offset status_str ;
call prtstring ;
call get_status_reg ; get status register
call prthex ;
mov si,offset cmmnd_str ;
call prtstring ;
call get_cmmnd_reg ; get command register
call prthex ;
mov si,offset frame_str ;
call prtstring ;
call get_frame_num ; get frame number
call prthex ;
mov si,offset frameb_str ;
call prtstring ;
call get_frame_base ; get frame list base
ror eax,16 ; print hi word first
call prthex ;
ror eax,16 ; print lo word last
call prthex ;
mov si,offset port0_str ;
call prtstring ;
call get_port_zero ; get port 1 (of 2)
call prthex ;
call prt_port_stat ; print port status
mov si,offset port1_str ;
call prtstring ;
call get_port_one ; get port 2 (of 2)
call prthex ;
call prt_port_stat ; print port status
; no need to be in usb_status
; ;;; ??????? reseting registers ???
; mov ax,0FFFFh ; write 0FFFFh to status register
; call w_status_reg ; (clears all bits)
ret
usb_status endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; ax = portx status register contents
; on exit
; nothing
prt_port_stat proc near uses dx si
mov dx,ax
and dx,0001000000000100b ; extract bits 12 and 2
test dx,0000000000000100b ; if bit 2 = 0, then disabled
jnz short prt_not_dis ;
mov si,offset port_dis_s ;
call prtstring ;
ret ;
prt_not_dis:
cmp dx,0001000000000100b ; if both set, then suspended
jne short prt_not_susp ;
mov si,offset port_susp_s ;
call prtstring ;
ret ;
prt_not_susp:
mov si,offset port_enbl_s ; else must be 0,1 and enabled
call prtstring ;
test ax,0000000000000001b ; bit 0 = device present (set)
jnz short prt_dev_here ;
mov si,offset port_dev_np ; else a device is not present
call prtstring ;
ret ;
prt_dev_here: ;
mov si,offset port_dev_p ; device is present
call prtstring ;
mov si,offset port_low_s ; assume low speed
test ax,0000000100000000b ; bit 8 = low speed (set)
jnz short prt_is_low ;
mov si,offset port_full_s ; else is full speed
prt_is_low: ;
call prtstring ;
ret
prt_port_stat endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Enable the PCI->USB hardware
; on entry
; nothing
; on exit
; carry = status
pci_enable proc near uses alld
mov di,04h ; read word at 0004h (command reg)
call ReadPCIW ; read it (returns in AX)
jc short no_enable ;
push ax ; save it
and ax,0000000101b ; bus master enable/io access enable
cmp ax,0000000101b ; are they both already set?
pop ax ; restore ax
je short good_enable ; yes, so don't toggle them
or ax,0000000101b ; no, so set bits 0 and 2, then
mov di,04h ; write to word at 0004h (command reg)
call WritePCIW ; write it
jc short no_enable ;
;;; ??? do we need to check to see if enabled as wanted;;;
good_enable: ;
clc ; else, good enable
ret ;
no_enable: stc ; enable failed
ret ;
pci_enable endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; Enable the current USB port
; on entry
; dx = io space start (base)
; on exit
; carry = status
usb_enable proc near uses ax bx
call get_port_zero ; returns bits in ax
mov bx,ax ;
and bx,0001000000000100b ;
cmp bx,0001000000000100b ;
je short usb_e_zero ;
or ax,0001000000000100b ;
call put_port_zero ; write ax to port_zero status
usb_e_zero:
call get_port_one ; returns bits in ax
mov bx,ax ;
and bx,0001000000000100b ;
cmp bx,0001000000000100b ;
je short usb_e_one ;
or ax,0001000000000100b ;
call put_port_one ; write ax to port_one status
usb_e_one:
ret
usb_enable endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io space start (base)
; on exit
; carry = status
alloc_f_list proc near uses alld es
xor eax,eax ; clear out high word of eax
mov ah,48h ; allocate memory
mov bx,(8192>4) ; 8192 bytes
int 21h ; ax = segment of memory
jc short alloc_f_err ; no memory
mov fram_l_bse,ax ; save it in fram_l_bse for unallocating
add ax,0FFh ; place it on a 4k boundary
and ax,0FF00h ;
shl eax,4 ; eax = physical of memory returned
push eax ; save it
shr eax,4 ; convert physical address
mov es,ax ; to es:0000
xor di,di ; di = 0000
mov al,01h ; write 1's (terminate)
mov cx,1024 ; 1024 bytes
rep ;
stosb ;
pop eax ; restore physical address
add dx,08 ; dx = io space from caller
out dx,eax ; store it
dec dx ; make dx = 06h
dec dx ;
xor ax,ax ; write a zero
out dx,ax ; to frame number register
clc ; frame is set okay
ret ;
alloc_f_err: ;
stc ; no memory
ret ;
alloc_f_list endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io space start
; on exit
;
usb_get_int_num proc near uses
ret
usb_get_int_num endp
;function USBGetInterruptNumber(Var IntNo:word;Var active:boolean):boolean;
;var okay:boolean;
; command:longint;
; command2:longint;
;begin
; okay:=false;
; active:=false;
; if isadetected then
; if readPCIRegisterDWord($60,ISABusNumber,ISAFunctionNumber,command) then
; begin
; intno:=command shr 24;
; active:=intno and 128=0;
; intno:=intno and 15;
; okay:=true;
; end;
; USBGetInterruptNumber:=okay;
;end;
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address
; on exit
; ax = USB status register contents
get_status_reg proc near uses dx
inc dx
inc dx ; USB status register (base+02)
in ax,dx ; word sized
and ax,0000000001111111b ; bits 15-6 reserved
ret
get_status_reg endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address
; on exit
; ax = USB command register contents
get_cmmnd_reg proc near uses dx
in ax,dx ; USB command register (base+00)
and ax,0000000011111111b ; bits 15-8 reserved
ret
get_cmmnd_reg endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address
; on exit
; ax = usb frame number contents
get_frame_num proc near uses dx
add dx,06 ; USB frame register (base+06)
in ax,dx ; word sized
and ax,0000011111111111b ; bits 15-11 reserved
ret
get_frame_num endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address
; on exit
; eax = USB frame list base register contents
get_frame_base proc near uses dx
add dx,08 ; USB frame base register (base+08)
in eax,dx ; dword sized
ret
get_frame_base endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address (base)
; on exit
; ax = port 1 (of 2) status/control register contents
get_port_zero proc near uses dx
add dx,10h ; USB port 1 register (base+10h)
in ax,dx ; word sized
and ax,0001111111111111b ; bits 15-13 reserved
ret
get_port_zero endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address (base)
; ax = port 1 (of 2) status/control register contents
; on exit
; ax = port 1 (of 2) status/control register contents after write
put_port_zero proc near uses dx
add dx,10h ; USB port 1 register (base+10h)
and ax,0001111111111111b ; bits 15-13 reserved
out dx,ax ; put it
mov ax,50 ; delay for 50 milliseconds
call delay ;
in ax,dx ; word sized
and ax,0001111111111111b ; bits 15-13 reserved
ret
put_port_zero endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address (base)
; on exit
; ax = port 2 (of 2) status/control register contents
get_port_one proc near uses dx
add dx,12h ; USB port 2 register (base+12h)
in ax,dx ; word sized
and ax,0001111111111111b ; bits 15-13 reserved
ret
get_port_one endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address (base)
; ax = port 2 (of 2) status/control register contents
; on exit
; ax = port 2 (of 2) status/control register contents after write
put_port_one proc near uses dx
add dx,12h ; USB port 2 register (base+12h)
and ax,0001111111111111b ; bits 15-13 reserved
out dx,ax ; put it
mov ax,50 ; delay for 50 milliseconds
call delay ;
in ax,dx ; word sized
and ax,0001111111111111b ; bits 15-13 reserved
ret
put_port_one endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; dx = io starting address (base)
; ax = value to write
; on exit
; nothing
w_status_reg proc near uses dx ;
inc dx ; USB status register (base+02)
inc dx ;
out dx,ax ; word sized
ret ;
w_status_reg endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; di = byte to read
; on exit
; ax = byte read (ah = 0)
ReadPCIB proc near uses bx cx dx si di
mov bh,bus_num ;
mov bl,dev_func ;
mov ax,0B108h ; read word
int 1Ah ;
mov al,cl
xor ah,ah
ret
ReadPCIB endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; di = word to read
; on exit
; ax = word read
ReadPCIW proc near uses bx cx dx si di
mov bh,bus_num ;
mov bl,dev_func ;
mov ax,0B109h ; read word
int 1Ah ;
mov ax,cx
ret
ReadPCIW endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; on entry
; di = word to write to
; ax = word to write
; on exit
; carry = status
WritePCIW proc near uses bx cx dx si di
mov bh,bus_num ;
mov bl,dev_func ;
mov ax,0B10Ch ; read word
int 1Ah ;
mov ax,cx
ret
WritePCIW endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; opens 'devnums.bin' and finds a line starting with 'V xxxx'
; where xxxx = VendorID.
; once found, copys the string found after 'V xxxx ' to Vendor_N+3
; then continues to find 'D xxxx ' where xxxx = DeviceID.
; if 'V xxxx' found before device number is found, then error.
; if number is found, then copies to Device_N+3
dev_names proc near uses all es
push cs ; make sure es = cs
pop es ;
mov ax,3D00h ; open for read only
mov dx,offset devfile ;
int 21h ;
jc short dev_names_d ;
mov bx,ax ;
mov ah,3Fh ; read from file
mov dx,offset buffer ;
mov cx,max_f_size ;
int 21h ;
jc short dev_names_d ;
mov ah,3Eh ; close the file
int 21h ;
mov si,offset buffer ;
dev_names_l: ;
mov al,[si] ;
or al,al ; if null found, then end of file
je short dev_names_d ;
cmp al,'V' ;
je short dev_names_v ;
dev_names_n:
add si,dn_line_s ; length of each line
jmp short dev_names_l ;
dev_names_v:
mov ax,[si+1] ; get vendor id number
cmp ax,VendorID ;
jne short dev_names_n ;
mov di,(Vendor_N+3) ;
add si,03 ;
dev_n_v_l: lodsb ;
stosb ;
or al,al ;
jnz short dev_n_v_l ;
dev_names_l1:
mov al,[si] ;
or al,al ; if null found, then end of file
je short dev_names_d ;
cmp al,'V' ; if 'V' found then no more devices
je short dev_names_d ; for this vendor
cmp al,'D' ;
je short dev_names_e ;
dev_names_n1: ;
add si,dn_line_s ; length of each line
jmp short dev_names_l1 ;
dev_names_e:
mov ax,[si+1] ; get device id number
cmp ax,DeviceID ;
jne short dev_names_n1 ;
mov di,(Device_N+3) ;
add si,03 ;
dev_n_v_l1: ;
lodsb ;
stosb ;
or al,al ;
jnz short dev_n_v_l1 ;
dev_names_d:
ret
dev_names endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; delay -- Delay in milliseconds
; on entry:
; ax = delay time in milliseconds
; on exit:
; nothing
delay proc near uses ax cx dx
mov dx,1000 ; multiply by 1000 (convert to micro)
mul dx ; dx:ax = time in microseconds
xchg ax,dx ; cx:dx = time
xchg ax,cx ;
mov ah,86h ; BIOS delay service
int 15h ;
ret ;
delay endp ;
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Prtstring proc near uses ax bx dx si
mov ah,06 ; DOS print char service
Ps1: lodsb ; Get character & point to next one
or al,al ; End of string?
jz short ps2 ; Yes, so exit
mov dl,al ;
int 21h ; Output a character
jmp short Ps1 ; Keep doing it
Ps2: ret
Prtstring endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
PrtHex proc near uses ax
xchg ah,al
call prthexn
xchg ah,al
call prthexn
ret
PrtHex endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
PrtHexN proc near uses ax bx cx dx
mov cx,02
PLoopN: rol al,04 ;
push ax ;
and al,0Fh ;
daa ;
add al,0F0h ;
adc al,40h ;
mov ah,02 ;
mov dl,al ;
int 21h ;
pop ax ;
loop PLoopN ;
ret
PrtHexN endp
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
PrtDec proc near uses ax cx dx di
mov cx,0FFFFh ; Ending flag
push cx
mov cx,10
PD1: xor dx,dx
div cx ; Divide by 10
add dl,30h ; Convert to ASCII
push dx ; Store remainder
or ax,ax ; Are we done?
jnz short PD1 ; No, so continue
PD2: pop dx ; Character is now in DL
cmp dx,0FFFFh ; Is it the ending flag?
je short PD3 ; Yes, so continue
mov ah,02 ;
int 21h ;
jmp short PD2 ; Keep doing it
PD3: ret
PrtDec endp
;';';';';
get_dev_id proc near uses alld ds es
push cs
push cs
pop ds
pop es
;;;;;;;;; clear out our buffer
mov di,offset buffer
mov cx,800h
mov al,20h
rep
stosb
;;;;;;;;;;
xor eax,eax
xor edx,edx
mov ax,ds
shl eax,4
mov dx,offset get_dev_dis
add eax,edx
mov si,offset stand_req_id
mov [si+14],eax
xor eax,eax
xor edx,edx
mov ax,ds
shl eax,4
mov dx,offset buffer
add eax,edx
mov si,offset stand_req_id
mov [si+14],eax
mov dx,IOAddr
add dx,08h
in eax,dx
shr eax,4
mov es,ax
xor di,di
xor eax,eax
xor edx,edx
mov ax,ds
shl eax,4
mov dx,offset stand_req_id
add eax,edx
mov es:[di],eax
xor eax,eax
xor edx,edx
mov ax,ds
shl eax,4
mov dx,offset buffer
add eax,edx
mov es:[di+4],eax
;';';';';';
mov ah,3Ch
mov cx,20h
mov dx,offset tempfile
int 21h
mov bx,ax
mov ah,40h
mov dx,offset buffer
mov cx,800h
int 21h
mov ah,3Eh
int 21h
ret
get_dev_id endp
tempfile db 'temp.bin',0
.para ; align on a 16-byte boundary
; 33222222 22221111 11111100 00000000
; 10987654 32109876 54321098 76543210
stand_req_id db 00000000b,00000000b,00000000b,00000001b
db 00001001b,10000000b,00000000b,00000000b
db 00000000b,11100000b,00000001b,00101101b
dw 00h,00h
get_dev_dis db 80h ; [bmRequest type] device->host, standard, device
db 06h ; [bRequest] GET_DESCRIPTOR
dw 01h ; [wValue] device
dw 00h ; [wIndex] zero
dw 08h ; [wLength] 8 bytes
.para ; align on a 16-byte boundary
; 33222222 22221111 11111100 00000000
; 10987654 32109876 54321098 76543210
stand_req_in db 00000000b,00000000b,00000000b,00000001b
db 00001001b,10000000b,00000111b,11111111b
db 11111111b,11101000b,00000001b,01101001b
dw 00h,00h
;';';';';'
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
v86_mode_s db 13,10,'Can not run in V86 mode. Must be real mode DOS',0
DetectS db 13,10,'Detecting PCI BIOS ... ',0
PCIBoisFS db ' found. v',0
PCIBoisNS db ' NOT found!',0
FoundUSBTS db 13,10,10,'Found USB Controller: ',0
VendorIDS db 13,10,' Vendor ID: ',0
DeviceIDS db 13,10,' Device ID: ',0
BusNumberS db 13,10,' Bus #/Dev #/Func #: ',0
CommandRS db 13,10,' Command Register: ',0
StatusRS db 13,10,' Status Register: ',0
RevisionS db 13,10,' Revision Code: ',0
ClassCodeS db 13,10,' Class/Sub/Interface: ',0
BusLatS db 13,10,' Bus Latency: ',0
HeaderS db 13,10,' Header Type: ',0
CacheS db 13,10,' Cache Line Size: ',0
SelfTestS db 13,10,' Self Test Byte: ',0
IOPortsS db 13,10,' Address Space: ',0
IRQNumS db 13,10,' IRQ Number: ',0
IntNumS db 13,10,' INT Number: ',0
status_str db 13,10,' Status Register: ',0
cmmnd_str db 13,10,' Command Register: ',0
frame_str db 13,10,' Frame Register: ',0
frameb_str db 13,10,' Frame Base Register: ',0
port0_str db 13,10,' Root Hub port 1: (',0
port1_str db 13,10,' Root Hub port 2: (',0
port_dis_s db ') Port disabled',0
port_susp_s db ') Port suspened',0
port_enbl_s db ') Port enabled:',0
port_dev_p db ' A device is present at ',0
port_dev_np db ' No device present.',0
port_low_s db 'low speed',0
port_full_s db 'full speed',0
enable_s db 13,10,10,'Enabling PCI bus...',0
e_bad_s db 'Error!',0
e_good_s db 'Successful.',0
no_memory_s db 13,10,'Out of memory',0
VendorID dw 00h ; Vendor ID number
DeviceID dw 00h ; Device ID number
Vendor_N db ' - '
dup dn_line_s,0
Device_N db ' - '
dup dn_line_s,0
devfile db 'devnums.bin',0
IOAddr dw ? ; Address space of port (32 bytes)
fram_l_ptr dup 4,0 ; physical dword pointer to 1024 byte frame
fram_l_bse dw ? ; segment to 8192 byte frame base
dev_index dw 00h
bus_num db 00h
dev_func db 00h
buffer dup 32768,? ; multi-use buffer
.end
; =-=-=-=-=-=-=-=-=- CUT HERE -=-=-=-=-=-=-=-=-=
; =-=-=-=-=-=-=-=-=- CUT HERE -=-=-=-=-=-=-=-=-=
; usb.inc
; =-=-=-=-=- boolean
true equ 1
false equ 0
; =-=-=-=-=- max size of 'devnums.bin'
max_f_size equ 16384 ; max size of 'devnums.bin' file
; =-=-=-=-=- Size of each line in 'devnums.bin'
dn_line_s equ 48 ; 48 bytes per line
.end
; =-=-=-=-=-=-=-=-=- CUT HERE -=-=-=-=-=-=-=-=-=
All rights reserved
Legal Notice
Copyright © 1984-2008 Forever Young Software
Return to My Home Page

|