home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu / 2008-06-02_hobbes.nmsu.edu.zip / dos / Usb4pas.zip / USB.PAS < prev   
Pascal/Delphi Source File  |  1999-01-25  |  23KB  |  729 lines

  1. {$A+,B-,D+,E+,F-,G+,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+,Y+}
  2.  
  3. { ************************************************************************ }
  4. { USB.PAS:   SB BASIC Routines by Dieter R. Pawelczak <dieterp@bigfoot.de> }
  5. { ======================================================================== }
  6. {                                                                          }
  7. {              Unit to initialize and address the USB Host Controller      }
  8. {                                                                          }
  9. { (c) 1998 by Dieter Pawelczak, <dieterp@bigfoot.de>                       }
  10. { This is public domain Software - selling this software is prohibeted!    }
  11. {                                                                          }
  12. { function DetectVirtualRealMode(..) detects virtual real mode
  13. { function USBdetect(..);     detects an PCI USB Controller - done by INIT
  14. { function USBEnable          enables USB Controller PCI-BUS Master
  15. { function USBGetDeviceIOSpace(..)        reads I/O port address
  16. { function USBSetDeviceIOSpace(..)        sets I/O port address
  17. { function USBReadCommandReg  read access IOCommandRegister
  18. { procedure USBWriteCommandReg write access IOCommandRegister
  19. {
  20. { Initialization should first check the USB device (test USBdetected),
  21. { read the I/O address space and if zero set an unused port address space
  22. { (32 byte), now PIC-BUS Master Control can be enabled by USBenable
  23. {                                                                          }
  24. { ************************************************************************ }
  25.  
  26. {$define DEBUG} { Enables DEBUG Output }
  27.  
  28. unit usb;
  29.  
  30. interface
  31.  
  32. {$IFDEF DEBUG}
  33. uses PCI,dutils;
  34. {$ELSE}
  35. uses PCI;
  36. {$ENDIF}
  37.  
  38.  
  39.  
  40.  
  41.  
  42. const { USB-Command Regiser }
  43.  
  44.       MAXP=$80;
  45.       CF=$40;
  46.       SWDBG=$20;
  47.       FGR=$10;
  48.       EGSM=$08;
  49.       GRESET=$04;
  50.       HCRESET=$02;
  51.       RS=$01;
  52.  
  53.  
  54.  
  55. type FrameListPointer = longint;            { 32 bit address + Q & T flag }
  56. type FrameListPointerArray = Array[0..1023] of FrameListPointer;
  57. type FrameList = ^FrameListPointerArray;
  58.  
  59.  
  60. type LinkPointer = longint;            { 32 bit address + Vf & Q & T flag }
  61. type BufferPointer = longint;          { 32 bit address of the data buffer }
  62.  
  63. type TransferDescriptor = record
  64.         next:LinkPointer;                   { points to next T/Q descriptor or indicates termination by T-flag }
  65.         ActLen: word;                       { presents the actual length (11 bit ) = and 2047 }
  66.         Status: byte;                       { presents the Status }
  67.         Flags:Byte;                         { Flags SPD(5), C_ERR(4,3), LS(2), ISO(1), IOC (0)}
  68.         Token: longint;                   { MaxLen/R/R/EndPt/DeviceAddr/PID to be sent }
  69.         BufferPtr: BufferPointer;              { Buffer Pointer for Data }
  70.         res:array[0..3] of longint;
  71.      end;
  72. type transmitstatusptr=^byte;
  73. type QueueHeadLinkPointer = longint;        { 32 bit address + Q & T flag }
  74. type QueueHeadElementPointer = longint;     { 32 bit address + Q & T flag, bit 2 is undefined (write as 0) }
  75.  
  76. type QueueHead = record
  77.         next:QueueHeadLinkPointer;          { points to next T/Q descriptor or indicates termination by T-flag }
  78.         Element:QueueHeadElementPointer;    { points to next Queue Operation or indicates termination by T-flag }
  79.      end;
  80.  
  81. type PortState = (port_disabled, port_newAttached, port_enabled, port_configured);
  82.  
  83. type USBRequest = record
  84.         bmRequestType:Byte;
  85.         bRequest:byte;
  86.         wValue:word;
  87.         wIndex:word;
  88.         wLength:word;
  89.     end;
  90.  
  91. const GetDeviceDescriptor : USBRequest =
  92.        (bmRequestType:$80;bRequest:$06;wValue:$0001;wIndex:$0000;wLength:$0012);
  93. const SetAddress : USBRequest =
  94.        (bmRequestType:$00;bRequest:$05;wValue:$0001;wIndex:$0000;wLength:$0000);
  95.  
  96.  
  97. var USBDeviceID,USBVendorID:word;           { PCI-Identification USB Controller }
  98.     USBBusNumber,USBFunctionNumber:Byte;
  99.     USBDescription:string;                  { Text Description }
  100.     USBIOSpace:word;                        { I/O address space set/read }
  101.     USBdetected:boolean;                    { Flag set by INIT }
  102.  
  103.  
  104. var ISADeviceID,ISAVendorID:word;           { PCI-Identification PCI-ISA Controller }
  105.     ISABusNumber,ISAFunctionNumber:Byte;    { needed by USBSetInt }
  106.     ISADescription:string;                  { Text Description }
  107.     ISAdetected:boolean;                    { Flag set by INIT }
  108.  
  109. var FrameListPtr:FrameList;                 { pointer to the frame list }
  110.     FrameListBase:longint;                  { frame list 32 bit base address}
  111.     FrameListHandle:pointer;                { TP memory handle }
  112.  
  113.  
  114. { LOW LEVEL: USB-Host Controller and PCI functions }
  115. function USBdetect(Var DeviceID,VendorID:word;VAR BusNumber,FunctionNumber:Byte;var Description:string):boolean;
  116. function USBEnable:boolean;
  117. function USBDisable:boolean;
  118. function USBGetDeviceIOSpace(var IOSpace:word):boolean;
  119. function USBSetDeviceIOSpace(IOSpace:word):boolean;
  120. function USBReadCommandReg:word;
  121. function USBReadStatusReg:word;
  122. function USBReadPort0Reg:word;
  123. function USBReadPort1Reg:word;
  124. function USBReadInterruptReg:word;
  125. function USBReadFrameBaseReg:longint;
  126. function USBReadFrameNumberReg:word;
  127. procedure USBWriteCommandReg(value:word);
  128. procedure USBWriteStatusReg(value:word);
  129. procedure USBWriteInterruptReg(value:word);
  130. procedure USBWriteFrameNumberReg(value:word);
  131. procedure USBWritePort0Reg(value:word);
  132. procedure USBWritePort1Reg(value:word);
  133. function USBSetInterruptNumber(IntNo:word; active:boolean):boolean;
  134. function USBGetInterruptNumber(Var IntNo:word;Var active:boolean):boolean;
  135. function USBAllocateFrameList(Var FList:FrameList;VAR FLBase:FrameListPointer):boolean;
  136. procedure USBCommandRun;
  137. procedure USBCommandStop;
  138. procedure USBDone;
  139. procedure usbclearframelist;
  140.  
  141. { General USB Functions }
  142.  
  143. function AllocateTransferDescriptor:pointer; { Returns pointer to TD or nil }
  144. procedure FreeTransferDescriptor(p:pointer);
  145. function CreateTransferDescriptor(Terminate,Queue,Depth:boolean;Link:linkpointer;
  146.                                   Actln:word;State:word;IOC,IOS,LS:Boolean;C_error:byte;SPD:boolean;
  147.                                   PID,DeviceAddress,EndPt:Byte;DataToggle:boolean;MaxLen:word;
  148.                                   BPtr:BufferPointer):pointer; { Allocates and configures TD - Returns pointer to TD or nil }
  149. procedure AlterTransferDescriptor(p:pointer;Actln:word;State:word;IOC,IOS,LS:Boolean;C_error:byte;SPD:boolean);
  150.  
  151. procedure InsertQueueDescriptorInFrameList(Number:word;p:pointer);
  152. procedure InsertTransferDescriptorInFrameList(Number:word;p:pointer);
  153. function GetLinkPointerFromTransferDescriptor(p:pointer):LinkPointer;
  154. function GetLinkPointerFromFrameList(number:word):LinkPointer;
  155. function GetTransferDescriptorFromFrameList(number:word):pointer;
  156. function GetTransferDescriptorFromLinkPointer(l:linkpointer):pointer;
  157. { Helpers }
  158.  
  159. function DetectVirtualRealMode:boolean;
  160. function GetPtrBase(p:pointer):longint;
  161. function GetBasePtr(b:longint):pointer;
  162.  
  163.  
  164. {$IFDEF DEBUG}
  165. procedure USBprintTD(P:pointer);
  166. procedure USBprintFrameList;
  167. {$ENDIF}
  168.  
  169. implementation
  170.  
  171. function USBdetect(Var DeviceID,VendorID:word;VAR BusNumber,FunctionNumber:Byte;var Description:string):boolean;
  172. var i:byte;
  173.     error,found:boolean;
  174. begin
  175.   BusNumber:=0;FunctionNumber:=0;
  176.   USBdetect:=false;
  177.   i:=0;
  178.   error:=false;
  179.   found:=false;
  180.   repeat { check different possible USB-PCI devices ... }
  181.   case i of
  182.     0: begin deviceId:=$7020;vendorId:=$8086; description:='Intel 82371SB USB controller'; end;
  183.     1: begin deviceId:=$7112;vendorId:=$8086; description:='Intel PIIX4 USB controller'; end;
  184.     2: begin deviceId:=$0571;vendorId:=$1106; description:='VIA AMD-645 USB controller'; end;
  185.     3: begin deviceId:=$A0F8;vendorID:=$1045; description:='Opti 82C750 (Vendetta) USB controller'; end;
  186.     4: begin deviceId:=$C861;vendorID:=$1045; description:='Opti 82C861/871 (Firelink/FireBlast) USB controller'; end;
  187.   end;
  188.   inc(i);
  189.   found:=detectPCIdevice(deviceId,vendorId,BusNumber,FunctionNumber);
  190.   error:=i>4;
  191.   until error or found;
  192.   USBdetect:=found;
  193. end;
  194.  
  195. function ISAdetect(Var DeviceID,VendorID:word;VAR BusNumber,FunctionNumber:Byte;var Description:string):boolean;
  196. var i:byte;
  197.     error,found:boolean;
  198. begin
  199.   BusNumber:=0;FunctionNumber:=0;
  200.   ISAdetect:=false;
  201.   i:=0;
  202.   error:=false;
  203.   found:=false;
  204.   repeat { check different possible ISA-PCI devices ... }
  205.   case i of
  206.     0: begin deviceId:=$7000;vendorId:=$8086; description:='Intel 82371SB ISA-PCI controller'; end;
  207.     1: begin deviceId:=$7110;vendorId:=$8086; description:='Intel PIIX4 ISA-PCI controller'; end;
  208. {    2: begin deviceId:=$0571;vendorId:=$1106; description:='VIA AMD-645 USB controller'; end;
  209.     3: begin deviceId:=$A0F8;vendorID:=$1045; description:='Opti 82C750 (Vendetta) USB controller'; end;
  210.     4: begin deviceId:=$C861;vendorID:=$1045; description:='Opti 82C861/871 (Firelink/FireBlast) USB controller'; end; }
  211.   end;
  212.   inc(i);
  213.   found:=detectPCIdevice(deviceId,vendorId,BusNumber,FunctionNumber);
  214.   error:=i>2;
  215.   until error or found;
  216.   ISAdetect:=found;
  217. end;
  218.  
  219. function USBGetDeviceIOSpace(var IOSpace:word):boolean;
  220. var okay:boolean;
  221.     result:word;
  222.     setiospace:word;
  223. begin
  224.   okay:=false;
  225.   if readPCIRegisterWord($20,USBBusNumber,USBFunctionNumber,result) then
  226.     begin
  227.       okay:=true;
  228.       IOSpace:=result and $FFFE;
  229.       USBIOSpace:=IOSpace;
  230.     end;
  231.   USBGetDeviceIOSpace:=okay;
  232. end;
  233.  
  234. function USBSetDeviceIOSpace(IOSpace:word):boolean;
  235. var okay:boolean;
  236.     result:word;
  237.     setiospace:word;
  238. begin
  239.   okay:=false;
  240.   IOSpace:=IOSpace ;
  241.   if writePCIRegisterWord($20,USBBusNumber,USBFunctionNumber,IOSpace) then
  242.     begin
  243.       okay:=true;
  244.       USBIOSpace:=IOSpace;
  245.     end;
  246.   USBSetDeviceIOSpace:=okay;
  247. end;
  248.  
  249. function USBReadCommandReg:word;
  250. begin
  251.   USBReadCommandReg:=portw[USBIOSpace];
  252. end;
  253.  
  254. function USBReadStatusReg:word;
  255. begin
  256.   USBReadStatusReg:=portw[USBIOSpace+2];
  257. end;
  258.  
  259. function USBReadInterruptReg:word;
  260. begin
  261.   USBReadInterruptReg:=portw[USBIOSpace+4];
  262. end;
  263.  
  264. function USBReadPort0Reg:word;
  265. begin
  266.   USBReadPort0Reg:=portw[USBIOSpace+16];
  267. end;
  268.  
  269. procedure USBWritePort0Reg(value:word);
  270. begin
  271.   portw[USBIOSpace+16]:=value;
  272. end;
  273.  
  274. function USBReadPort1Reg:word;
  275. begin
  276.   USBReadPort1Reg:=portw[USBIOSpace+18];
  277. end;
  278.  
  279. procedure USBWritePort1Reg(value:word);
  280. begin
  281.   portw[USBIOSpace+18]:=value;
  282. end;
  283.  
  284. procedure USBWriteInterruptReg(value:word);
  285. begin
  286.   portw[USBIOSpace+4]:=value;
  287. end;
  288.  
  289. procedure USBWriteStatusReg(value:word);
  290. begin
  291.   portw[USBIOSpace+2]:=value;
  292. end;
  293.  
  294. procedure USBWriteCommandReg(value:word);
  295. begin
  296.   portw[USBIOSpace]:=value;
  297. end;
  298.  
  299. procedure USBWriteFrameNumberReg(value:word);
  300. begin
  301.   portw[USBIOSpace+6]:=value;
  302. end;
  303.  
  304. function USBReadFrameNumberReg:word;
  305. begin
  306.   USBReadFrameNumberReg:=portw[USBIOSpace+6];
  307. end;
  308.  
  309. function USBReadFrameBaseReg:longint;
  310. begin
  311.   asm
  312.         mov dx,USBIOSpace
  313.         add dx,08h
  314.         db 66h; in ax,dx                       { in dx,eax  }
  315.         db 66h; mov word ptr FrameListBase,ax  { mov ..,eax }
  316.   end;
  317.   USBReadFrameBaseReg:=FrameListBase;
  318. end;
  319.  
  320. function USBEnable:boolean;
  321. var okay:boolean;
  322.     command:word;
  323. begin
  324.   okay:=false;
  325.   if usbdetected and (USBIOspace<>0) then
  326.     if readPCIRegisterWord($4,USBBusNumber,USBFunctionNumber,command) then
  327.       begin
  328.         okay:=command and 5=5;
  329.         command:=command or 5;
  330.         if writePCIRegisterWord($4,USBBusNumber,USBFunctionNumber,command) then
  331.           okay:=true;
  332.       end;
  333.   USBenable:=okay;
  334. end;
  335.  
  336. function USBGetInterruptNumber(Var IntNo:word;Var active:boolean):boolean;
  337. var okay:boolean;
  338.     command:longint;
  339.     command2:longint;
  340. begin
  341.   okay:=false;
  342.   active:=false;
  343.   if isadetected then
  344.       if readPCIRegisterDWord($60,ISABusNumber,ISAFunctionNumber,command) then
  345.         begin
  346.           intno:=command shr 24;
  347.           active:=intno and 128=0;
  348.           intno:=intno and 15;
  349.           okay:=true;
  350.         end;
  351.    USBGetInterruptNumber:=okay;
  352. end;
  353.  
  354. function USBSetInterruptNumber(IntNo:word;active:boolean):boolean;
  355. var okay:boolean;
  356.     command:byte;
  357.     command2:word;
  358.     dummy:word;
  359. begin
  360.   okay:=false;
  361.   asm
  362.     cli
  363.   end;
  364.   if isadetected then
  365.       if readPCIRegisterByte($63,ISABusNumber,ISAFunctionNumber,command) then
  366.         begin
  367.           { Redirect IRQD = Register 63h  to ISA-BUS IRQ }
  368.           command:=IntNo+ord(not active)*128; { Set interrupt Number to MSB }
  369.           command2:=1 shl intno;
  370.           if command2>255 then
  371.               begin
  372.                 dummy:=port[$4d1] and (not (command2 shr 8));
  373.                 port[$4d1]:=port[$4d1] and (not (command2 shr 8));
  374.               end else
  375.               begin
  376.                 dummy:=port[$4d0] and (not (command2 shr 8));
  377.                 port[$4d0]:=port[$4d0] and (not (command2));
  378.               end;
  379.           dummy:=port[$21];
  380.           if writePCIRegisterByte($63,ISABusNumber,ISAFunctionNumber,command) then
  381.             begin
  382.               dummy:=port[$21];
  383.               { Set Interrupt Sensitive Mode }
  384.                 okay:=true;
  385.             end;
  386.           if intno>7 then
  387.              begin
  388.                asm
  389.                  in al,0a1h
  390.                  mov cl,byte ptr intno
  391.                  sub cl,8
  392.                  mov dl,1
  393.                  shl dl,cl
  394.                  not dl
  395.                  and al,dl
  396.                  out 0a1h,al
  397.                  in al,021h
  398.                  mov dl,2
  399.                  not dl
  400.                  and al,dl
  401.                  out 021h,al
  402.                end;
  403.              end else
  404.              begin
  405.                asm
  406.                  in al,021h
  407.                  mov cl,byte ptr intno
  408.                  mov dl,1
  409.                  shl dl,cl
  410.                  not dl
  411.                  and al,dl
  412.                  out 021h,al
  413.                end;
  414.              end;
  415.  
  416.           end;
  417.    asm
  418.      sti
  419.    end;
  420.    USBSetInterruptNumber:=okay;
  421.   end;
  422.  
  423. function USBDisable:boolean;
  424. var okay:boolean;
  425. begin
  426.   okay:=false;
  427.   if usbdetected and (USBIOspace<>0) then
  428.     if WritePCIRegisterWord($4,USBBusNumber,USBFunctionNumber,0) then
  429.       begin
  430.         okay:=true;
  431.       end;
  432.   USBDisable:=okay;
  433. end;
  434.  
  435. procedure usbclearframelist;
  436. var i:word;
  437. begin
  438.       for i:=0 to 1023 do
  439.         FrameListPtr^[i]:= 1; { Set Terminate }
  440. end;
  441.  
  442. function USBAllocateFrameList(Var FList:FrameList;VAR FLBase:FrameListPointer):boolean;
  443. var okay:boolean;
  444.     i:word;
  445. begin
  446.   if memavail>8192 then
  447.     begin
  448.       getmem(FrameListHandle,8192);
  449.       FrameListBase:=longint(seg(FrameListHandle^)) shl 4+longint(ofs(FrameListHandle^));
  450.       { 4K alignment }
  451.       FrameListBase:=longint(FrameListbase + 4096) and $fffff000;
  452.       FrameListPtr:=getbaseptr(FrameListBase);
  453.       FList:=FrameListPtr;
  454.       FLBase:=FrameListBase;
  455.       USBWriteFrameNumberReg(0);
  456.       for i:=0 to 1023 do
  457.         FrameListPtr^[i]:= 1; { Set Terminate }
  458.       asm
  459.         mov dx,USBIOSpace
  460.         add dx,08h
  461.         db 66h; mov ax, word ptr FrameListBase  { mov eax, ... }
  462.         db 66h; out dx,ax                       { out dx,eax  }
  463.       end;
  464.       USBWriteFrameNumberReg(0);
  465.       okay:=true;
  466.     end;
  467.   USBAllocateFrameList:=okay;
  468. end;
  469.  
  470. procedure InsertTransferDescriptorInFrameList(Number:word;p:pointer);
  471. begin
  472.   FrameListPtr^[Number]:= getPtrBase(p) and $fffffffc;
  473. end;
  474.  
  475. function GetLinkPointerFromFrameList(number:word):LinkPointer;
  476. begin
  477.   GetLinkPointerFromFrameList:=FrameListPtr^[Number] and $fffffffc;
  478. end;
  479.  
  480. procedure InsertQueueDescriptorInFrameList(Number:word;p:pointer);
  481. begin
  482.   FrameListPtr^[Number]:= getPtrBase(p) and $fffffffc +2;
  483. end;
  484.  
  485.  
  486.  
  487. procedure USBCommandRun;
  488. var value:word;
  489. begin
  490.   value:=USBReadCommandReg;
  491.   value:=value or 1;
  492.   USBWriteCommandReg(value);
  493. end;
  494.  
  495. procedure USBCommandStop;
  496. var value:word;
  497. begin
  498.   value:=USBReadCommandReg;
  499.   value:=value and $fe;
  500.   USBWriteCommandReg(value);
  501. end;
  502.  
  503.  
  504. function DetectVirtualRealMode:boolean;assembler;
  505. asm
  506.   smsw ax
  507.   and ax,1
  508. end;
  509.  
  510. function GetPtrBase(p:pointer):longint;
  511. begin
  512.   GetPtrBase:=longint(seg(p^)) shl 4 + longint(ofs(p^));
  513. end;
  514.  
  515. function GetBasePtr(b:longint):pointer;
  516. var h1,h2:longint;
  517. begin
  518.   h1:=b shr 4;
  519.   h2:=b and $f;
  520.   GetbasePtr:=Ptr(h1,h2);
  521. end;
  522.  
  523. function AllocateTransferDescriptor:pointer;
  524. var i,j,k:word;
  525.     p1:^transferdescriptor;
  526.     PA:array[1..1000] of pointer;
  527. begin
  528.   p1:=nil;
  529.   getmem(p1,32);
  530.   if ofs(p1^) and $f<>0 then
  531.      begin
  532.         j:=0;
  533.         repeat
  534.           inc(j);
  535.           freemem(p1,32);p1:=NIL;
  536.           getmem(pa[j],1);
  537.           getmem(p1,32);
  538.         until (j=1000) or (ofs(p1^)=0);
  539.         if j=1000 then
  540.           begin
  541.             writeln('Fatal: Allocating TD memory error...');
  542.             halt(3);
  543.           end;
  544.         for k:=1 to j do Freemem(pa[k],1);
  545.     end;
  546.   if p1<>NIL then
  547.   with p1^ do
  548.         begin
  549.           next:=0;
  550.           ActLen:=0;
  551.           Status:=0;
  552.           Flags:=0;
  553.           token:=0;
  554.           BufferPtr:=0;
  555.          end;
  556.   AllocateTransferDescriptor:=p1;
  557. end;
  558.  
  559. procedure FreeTransferDescriptor(p:pointer);
  560. var td:^TransferDescriptor;
  561. begin
  562.   freemem(p,32);
  563. end;
  564.  
  565. function GetLinkPointerFromTransferDescriptor(p:pointer):LinkPointer;
  566. begin
  567.   GetLinkPointerFromTransferDescriptor:=getptrbase(p);
  568. end;
  569.  
  570. function GetTransferDescriptorFromLinkPointer(l:linkpointer):pointer;
  571. begin
  572.   GetTransferDescriptorFromLinkPointer:=getbaseptr(l and $fffffffc) ;
  573. end;
  574.  
  575. function GetTransferDescriptorFromFrameList(number:word):pointer;
  576. begin
  577.   GetTransferDescriptorFromFrameList:=getbaseptr(FrameListPtr^[Number] and $fffffffc);
  578. end;
  579.  
  580. procedure AlterTransferDescriptor(p:pointer;Actln:word;State:word;IOC,IOS,LS:Boolean;C_error:byte;SPD:boolean);
  581. var td:^TransferDescriptor;
  582. begin
  583.   td:=p;
  584.   if td<>nil then with td^ do
  585.     begin
  586.       Actlen:=Actln;
  587.       flags:=ord(IOC)+ord(IOS) shl 1 +ord(ls) shl 2+(c_error and 3) shl 3+ord(spd) shl 5;
  588.       Status:=state;
  589.     end;
  590. end;
  591.  
  592. function CreateTransferDescriptor(Terminate,Queue,Depth:boolean;Link:linkpointer;
  593.                                   Actln:word;State:word;IOC,IOS,LS:Boolean;C_error:byte;SPD:boolean;
  594.                                   PID,DeviceAddress,EndPt:Byte;DataToggle:boolean;MaxLen:word;
  595.                                   BPtr:BufferPointer):pointer; { Allocates and configures TD - Returns pointer to TD or nil }
  596. var td:^TransferDescriptor;
  597. begin
  598.   td:=AllocateTransferDescriptor;
  599.   if td<>nil then with td^ do
  600.     begin
  601.       next:=link and $fffffff0+ord(Terminate)+ord(Queue) shl 1+ord(Depth) shl 2;
  602.       Actlen:=Actln;
  603.       Status:=state;
  604.       flags:=ord(IOC)+ord(IOS) shl 1 +ord(ls) shl 2+(c_error and 3) shl 3+ord(spd) shl 5;
  605.       token:=pid+longint(DeviceAddress) shl 8+longint(EndPt) shl 15+longint(ord(DataToggle)) shl 19+longint(maxlen) shl 21;
  606.       bufferPtr:=Bptr;
  607.  
  608.     end;
  609.   CreateTransferDescriptor:=td;
  610. end;
  611.  
  612. {$IFDEF DEBUG}
  613. procedure USBprintLinkPtr(L:LinkPointer);
  614. var h:longint;
  615.     i:word;
  616. begin
  617.       h:=l and $fffffff0;
  618.       write('LinkPtr:  ');
  619.       if h=0 then write('-EMPTY- [');
  620.       write('- [',hexs(h));
  621.       if l and 4=4 then write('] Vf ') else write('] -- ');
  622.       if l and 2=2 then write(' Q ') else write(' - ');
  623.       if l and 1=1 then write(' T ') else write(' - ');
  624.       writeln;
  625. end;
  626.  
  627. procedure USBprintFrameList;
  628. var i,j:word;
  629.     l:longint;
  630. begin
  631.   write('FrameList---------------[',hexs(FrameListBase),']---------------------------------------');
  632.   for i:=0 to 1023 do
  633.     begin
  634.       if i mod 6=0 then writeln;
  635.       l:=FrameListPtr^[i];
  636.       write('[',hexs(l),']');
  637.       if l and 2=2 then write('Q') else write('-');
  638.       if l and 1=1 then write('T') else write('-');
  639.       write(' ');
  640.     end;
  641.   writeln;
  642.   writeLn('-------------------------------------------------------------------------');
  643. end;
  644.  
  645. procedure USBprintTD(P:pointer);
  646. var td:^TransferDescriptor;
  647.     i:word;
  648.     h:longint;
  649.     hp:^byte;
  650. begin
  651.   td:=p;
  652.   with td^ do
  653.     begin
  654.       writeLn('Transfer Descriptor-----[',hexs(GetPtrBase(p)),']---------------------------------------');
  655.       USBprintLinkPtr(next);
  656.       write('Control:  ');
  657.       if flags and 32=32 then write(' SP ') else write(' -- ');
  658.       write('C_ERROR: ',chr(48+ord(flags and 16=16)),chr(48+ord(flags and 8=8)));
  659.       if flags and 4=4 then write(' LS ') else write(' -- ');
  660.       if flags and 2=2 then write(' ISO ') else write(' --- ');
  661.       if flags and 1=1 then write(' ICO ') else write(' --- ');
  662.       write(' Status: ',bins8(status));
  663.       writeln(' Len: ',Actlen);
  664.       write('Token:    MaxLen: ',Token shr 21 and $7ff);
  665.       write('  Toggle: ',(Token shr 19) and 1);
  666.       WRite('  EndPt:',hexs8((Token shr 15) and $f));
  667.       WRite('  DevAddr:',hexs8((Token shr 8) and $7f));
  668.       WRite('  PID:',hexs8((Token) and $ff));
  669.       writeln;
  670.       write('BufferPtr:',hexs(bufferptr));
  671.       if bufferptr<>0 then
  672.         begin
  673.           write(' - ');
  674.           hp:=getBasePtr(bufferptr);
  675.           for i:=1 to 8 do
  676.             begin
  677.               write(hexs8(hp^),' ');
  678.               inc(hp);
  679.             end;
  680.         end;
  681.       writeln;
  682.  
  683.  
  684.       writeLn('-------------------------------------------------------------------------');
  685.     end;
  686.   end;
  687.  
  688.  
  689.  
  690. {$ENDIF}
  691.  
  692.  
  693. var oldmasterintmask:byte;
  694.     oldslaveintmask:byte;
  695.     old_port4d0:byte;
  696.     old_port4d1:byte;
  697.     old_pirqd:byte;
  698.  
  699. procedure USBDone;
  700. begin
  701.        port[$4d0]:=old_port4d0;
  702.        port[$4d1]:=old_port4d1;
  703.        WritePCIRegisterByte($63,ISABusNumber,ISAFunctionNumber,old_pirqd);
  704.     asm
  705.       mov al,oldslaveintmask
  706.       out 0a1h,al
  707.       mov al,oldmasterintmask
  708.       out 021h,al
  709.     end;
  710. end;
  711.  
  712. begin
  713.   USBdetected:=false;
  714.   if detectPCIbios then
  715.     begin
  716.        USBdetected:=USBdetect(USBDeviceId,USBVendorId,USBBusNumber,USBFunctionNumber,USBdescription);
  717.        ISAdetected:=ISAdetect(ISADeviceId,ISAVendorId,ISABusNumber,ISAFunctionNumber,ISAdescription);
  718.        old_port4d0:=port[$4d0];
  719.        old_port4d1:=port[$4d1];
  720.        readPCIRegisterByte($63,ISABusNumber,ISAFunctionNumber,old_pirqd);
  721.        asm
  722.         in al,0a1h
  723.         mov oldslaveIntMask,al
  724.         in al,021h
  725.         mov oldmasterIntMask,al
  726.        end;
  727.     end;
  728. end.
  729.