
; buffer       dup 32768,?    ; multi-use buffer
;                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

;                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



        mov  word ptr dev_index,00h
FindUSBL:
                call FindUSB               
                or   ah,ah                   ; if ah = !0, then no more
                jnz  short exit_ptr        
; if IOAddr < 100h then write to port + 20h = 120h ???
; 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

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; 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


;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
;  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

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



