Advertisement
iocoder

USB Host Controller Interface Driver

Dec 6th, 2012
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 27.08 KB | None | 0 0
  1. #define UHCI    0x00    // Universal Host Controller Interface. Supports USB1 and USB1.1.
  2.  
  3. #define UHCI_REG_USBCMD     0x00
  4. #define UHCI_REG_USBSTS     0x02
  5. #define UHCI_REG_USBINTR    0x04
  6. #define UHCI_REG_FRNUM      0x06
  7. #define UHCI_REG_FRBASEADD  0x08
  8. #define UHCI_REG_SOFMOD     0x0C
  9. #define UHCI_REG_PORTBASE   0x10
  10.  
  11. #define UHCI_USBLEGSUP      0xc0        /* legacy support      */
  12. #define UHCI_USBLEGSUP_RWC  0x8f00      /* the R/WC bits       */
  13. #define UHCI_USBLEGSUP_RO   0x5040      /* R/O and reserved bits   */
  14. #define UHCI_USBCMD_RUN     0x0001      /* RUN/STOP bit        */
  15. #define UHCI_USBCMD_HCRESET 0x0002      /* Host Controller reset   */
  16. #define UHCI_USBCMD_GRESET  0x0004      /* Global Reset        */
  17. #define UHCI_USBCMD_EGSM    0x0008      /* Global Suspend Mode     */
  18. #define UHCI_USBCMD_CONFIGURE   0x0040      /* Config Flag         */
  19. #define UHCI_USBINTR_RESUME 0x0002      /* Resume interrupt enable */
  20.  
  21. #include <keypad.h>
  22.  
  23. struct uhci_td {
  24.     unsigned char  T;   // Termination (1: Link is not valid, 0: Link is valid).
  25.     unsigned char  QH;  // Queue Head (1: Link is to a QH, 0: Link is to a TD).
  26.     unsigned char  Vf;  // Depth/Breadth Select (1: Depth First, 0: Breadth First).
  27.     unsigned int   link;    // 32-Bit Memory Address of next descriptor.
  28.     unsigned short ActLen;  // Actual Length.
  29.     unsigned char  status;  // Status.
  30.     unsigned char  IOC; // Interrupt on Complete (1: Issue IOC after the current time frame).
  31.     unsigned char  ISO; // Isochronous Select (1: Isochronous TD, 0: Non-isochronous).
  32.     unsigned char  LS;  // Low Speed Drive (1: Low Speed, 0: Full Speed).
  33.     unsigned char  C_ERR;   // Error Counter.
  34.     unsigned char  SPD; // Short Packet Detect (1: Enable, 0: Disable).
  35.     unsigned char  PID; // Packet Identification (0x69: IN, 0xE1: OUT, 0x2D: Setup).
  36.     unsigned char  device;  // Device Address.
  37.     unsigned char  EndPt;   // End Point.
  38.     unsigned char  D;   // Data Toggle Synchronization.
  39.     unsigned short MaxLen;  // Maximum Length.
  40.     unsigned int   buffer;  // Buffer Pointer.
  41. };
  42.  
  43. struct sixteenbytelen {
  44.     unsigned int  lng[4];
  45. };
  46.  
  47. struct eightbytelen {
  48.     unsigned int  lng[2];
  49. };
  50.  
  51. unsigned int    *uhci_frlst;        // Frame List.
  52. sixteenbytelen  *uhci_tdlst;        // TD List.
  53. eightbytelen    *uhci_qhlst;        // QH List.
  54.  
  55. unsigned int    uhci_ports;     // Number of Ports.
  56. unsigned char   uhci_buffer[0x200];
  57. unsigned short  ds;
  58.  
  59. void uhci_set_td(uhci_td td, unsigned int index) {
  60.     uhci_tdlst[index].lng[0] =  (td.T       <<  0)|
  61.                     (td.QH      <<  1)|
  62.                     (td.Vf      <<  2)|
  63.                     (td.link    <<  0);
  64.     uhci_tdlst[index].lng[1] =  (td.ActLen  <<  0)|
  65.                     (td.status  << 16)|
  66.                     (td.IOC     << 24)|
  67.                     (td.ISO     << 25)|
  68.                     (td.LS      << 26)|
  69.                     (td.C_ERR   << 27)|
  70.                     (td.SPD     << 29);
  71.     uhci_tdlst[index].lng[2] =  (td.PID     <<  0)|
  72.                     (td.device  <<  8)|
  73.                     (td.EndPt   << 15)|
  74.                     (td.D       << 19)|
  75.                     (td.MaxLen  << 21);
  76.     uhci_tdlst[index].lng[3] =  (td.buffer  <<  0);
  77. }
  78.  
  79.  
  80. // Control Transfer:
  81. // ---------------------->
  82. // 1- Setup Stage [1 Transaction]:-
  83. //  Token PID: SETUP
  84. //  DATA PID:  DATA0
  85. //  Handshake:
  86. // 2- Data Stage [0 or more transactions]:
  87. //  Token PID: IN/OUT
  88. //  DATA PID:  DATA0/DATA1
  89. //  Handshake:
  90. // 3- Status Stage [1 Transaction]:
  91. //  Token PID: OUT/IN
  92. //  DATA PID:  DATA1
  93. //  Handshake:
  94.  
  95.  
  96. // PIDs of Token Packet
  97. #define UHCI_PID_SETUP  0x2D
  98. #define UHCI_PID_IN 0x69
  99. #define UHCI_PID_OUT    0xE1
  100.  
  101. // PIDs of Data Packet
  102. #define UHCI_DATA0  0x00
  103. #define UHCI_DATA1  0x01
  104.  
  105. // Hub Requests:
  106. #define CLEAR_FEATURE   0x01
  107. #define CLEAR_TT_BUFFER 0x08
  108. #define GET_DESCRIPTOR  0x06
  109. #define GET_STATUS  0x00
  110. #define RESET_TT    0x09
  111. #define SET_DESCRIPTOR  0x07
  112. #define SET_FEATURE 0x03
  113. #define GET_TT_STATE    0x0A
  114. #define STOP_TT     0x0B
  115.  
  116. unsigned char uhci_root_hub_control_transfer(unsigned char bmRequestType, unsigned char bRequest, unsigned short wValue,
  117.                          unsigned short wIndex, unsigned short wLength, unsigned int buf) {
  118.    
  119.     // This is a special function for the root hub's control transfers
  120.     switch (bRequest) {
  121.         case CLEAR_FEATURE:     if (bmRequestType == 0x20) {
  122.                         // ClearHubFeature
  123.                        
  124.                     } else if (bmRequestType == 0x23) {
  125.                         // ClearPortFeature
  126.                        
  127.                     }
  128.                         break;
  129.                        
  130.         case CLEAR_TT_BUFFER:   if (bmRequestType == 0x23) {
  131.                         // ClearTTBuffer
  132.                        
  133.                     }
  134.                     break;
  135.        
  136.         case GET_DESCRIPTOR:    if (bmRequestType == 0xA0) {
  137.                         // GetHubDescriptor
  138.                         if (wValue == 0x2900) {
  139.                             if (wLength > 0) kwriteb(7, buf + 0);
  140.                             if (wLength > 1) kwriteb(0x29, buf + 1);
  141.                             if (wLength > 2) kwriteb(uhci_ports, buf + 2);
  142.                             if (wLength > 3) kwriteb(0, buf + 3);
  143.                             if (wLength > 4) kwriteb(0, buf + 4);
  144.                             if (wLength > 5) kwriteb(0, buf + 5);
  145.                             if (wLength > 6) kwriteb(0, buf + 6);
  146.                         }
  147.                     }
  148.                     break;
  149.                    
  150.         case GET_STATUS:    if (bmRequestType == 0xA0) {
  151.                         // GetHubStatus
  152.                        
  153.                     } else if (bmRequestType == 0xA3) {
  154.                         // GetPortStatus
  155.                         unsigned short PORTSC = usbio.readregw(((wIndex - 1) * 2) + 0x10);
  156.                         unsigned char CCS = (PORTSC>> 0) & 1;   // Current Connect Status
  157.                         unsigned char CSC = (PORTSC>> 1) & 1;   // Connect Status Change
  158.                         unsigned char PE  = (PORTSC>> 2) & 1;   // Port Enable
  159.                         unsigned char PEC = (PORTSC>> 3) & 1;   // Port Enable Change
  160.                         unsigned char RD  = (PORTSC>> 6) & 1;   // Resume Detect
  161.                         unsigned char LS  = (PORTSC>> 8) & 1;   // Low Speed Device
  162.                         unsigned char PR  = (PORTSC>> 9) & 1;   // Port Reset
  163.                         unsigned char PS  = (PORTSC>>12) & 1;   // Port Suspend
  164.                         unsigned char PP  = 1;          // Port Power
  165.                        
  166.                         if (wLength > 0) kwriteb((CCS<<0) + (PE <<1) + (PS <<2) + (PR <<4), buf + 0);
  167.                         if (wLength > 1) kwriteb((PP <<0) + (LS <<1), buf + 1);
  168.                         if (wLength > 2) kwriteb((CSC<<0) + (PEC<<1) + (RD <<2), buf + 2);
  169.                         if (wLength > 3) kwriteb(0, buf + 3);
  170.                     }
  171.                     break;
  172.                    
  173.         case RESET_TT:      if (bmRequestType == 0x23) {
  174.                         // ResetTT
  175.                        
  176.                     }
  177.                     break;
  178.                    
  179.         case SET_DESCRIPTOR:    if (bmRequestType == 0x20) {
  180.                         // SetHubDescriptor
  181.                        
  182.                     }
  183.                     break;
  184.                    
  185.         case SET_FEATURE:   if (bmRequestType == 0x20) {
  186.                         // SetHubFeature
  187.                        
  188.                     } else if (bmRequestType == 0x23) {
  189.                         // SetPortFeature
  190.                         unsigned int PORTSC = ((wIndex - 1) * 2) + 0x10;
  191.                         if (wValue == 4) {
  192.                             usbio.writeregw(usbio.readregw(PORTSC) | 0x0200, PORTSC); // Reset
  193.                             while (!(usbio.readregw(PORTSC) & 0x0200)); // Wait until Bit 9 is set.
  194.                             sleep(100);
  195.                            
  196.                            
  197.                            
  198.                             usbio.writeregw(usbio.readregw(PORTSC) & 0xFDFF, PORTSC); // Stop Reset
  199.                             while ( (usbio.readregw(PORTSC) & 0x0200)); // Wait until Bit 9 is cleared.
  200.                             sleep(100);
  201.                            
  202.                            
  203.            
  204.                             usbio.writeregw(usbio.readregw(PORTSC) | 0x0004, PORTSC); // Enable the Port
  205.                             while (!(usbio.readregw(PORTSC) & 0x0004)); // Wait until Bit 4 is set.
  206.                         }
  207.                     }
  208.                     break;
  209.                    
  210.         case GET_TT_STATE:  if (bmRequestType == 0xA3) {
  211.                         // GetTTState
  212.                        
  213.                     }
  214.                     break;
  215.                    
  216.         case STOP_TT:       if (bmRequestType == 0x23) {
  217.                         // StopTT
  218.                        
  219.                     }
  220.                     break;
  221.                    
  222.         default:        break;
  223.     }
  224.    
  225.     return 0;
  226. }
  227.  
  228.  
  229. unsigned char uhci_control_transfer(unsigned char device, unsigned char bmRequestType, unsigned char bRequest, unsigned short wValue,
  230.                     unsigned short wIndex, unsigned short wLength, unsigned int buf) {
  231.                    
  232.     if (device == 128) return uhci_root_hub_control_transfer(bmRequestType, bRequest, wValue, wIndex, wLength, buf);
  233.    
  234.     static uhci_td td;
  235.     unsigned int i, status;
  236.     unsigned char speed = devices[device].speed;                    // 0: Low Speed, 1: Full Speed.
  237.     unsigned int Max_Packet_Size = devices[device].Max_Packet;          // Max Packet Size for Endpoint Zero.
  238.     unsigned int tds = ((wLength + Max_Packet_Size - 1) / Max_Packet_Size) + 2; // Number of needed TDs.
  239.    
  240.     unsigned char  data_stage_tokens_pid   = (bmRequestType & 0x80) ? UHCI_PID_IN : UHCI_PID_OUT;
  241.     unsigned char  status_stage_token_pid;
  242.     if (tds == 2)
  243.         status_stage_token_pid = UHCI_PID_IN;
  244.     else
  245.         status_stage_token_pid = (data_stage_tokens_pid == UHCI_PID_IN) ? UHCI_PID_OUT : UHCI_PID_IN;  
  246.    
  247.     td.IOC     = 0;
  248.     td.ISO     = 0;
  249.     td.LS      = 1-speed; // 1: Low Speed, 0: Full Speed.
  250.     td.SPD     = 0;
  251.     td.ActLen  = 0;
  252.     td.C_ERR   = 0;
  253.     td.device  = device;
  254.     td.EndPt   = 0; // Control Transfers always use Endpoint Zero.
  255.    
  256.     // I: Setup Stage:
  257.     // -------------------
  258.     // This Stage is done by sending 1 Transaction to the device containing the following packets:
  259.     // A: Token Packet: With a PID of SETUP.
  260.     // B: Data  Packet: With a PID of DATA0. This Packet contains Setup Information.
  261.     // C: Handshake Packet: This is sent by the device and tells us the results.
  262.  
  263.     unsigned static char setup_info[8];
  264.     setup_info[0] = bmRequestType;
  265.     setup_info[1] = bRequest;
  266.     setup_info[2] = (wValue  & 0x00FF)>>0;
  267.     setup_info[3] = (wValue  & 0xFF00)>>8;
  268.     setup_info[4] = (wIndex  & 0x00FF)>>0;
  269.     setup_info[5] = (wIndex  & 0xFF00)>>8;
  270.     setup_info[6] = (wLength & 0x00FF)>>0;
  271.     setup_info[7] = (wLength & 0xFF00)>>8;
  272.    
  273.     td.T      = 0;  // Link is valid
  274.     td.QH     = 0;  // Link refers to a TD.
  275.     td.Vf     = 1;  // Depth first.
  276.     td.link   = krnl_get_selector_base(ds) + ((int) &uhci_tdlst[2]);    // Next TD.
  277.  
  278.     td.PID    = UHCI_PID_SETUP; // Token Packet PID.
  279.     td.D      = UHCI_DATA0;     // Data Packet PID.
  280.     td.status = 0x80;       // Handshake Packet PID will be set here.
  281.    
  282.     td.buffer = krnl_get_selector_base(ds) + ((int) setup_info);
  283.     td.MaxLen = 7;
  284.  
  285.     uhci_set_td(td, 1);
  286.    
  287.     // II: Data Stage:
  288.     // -----------------
  289.     // This stage is optional, a transaction or more is/are sent in this stage containing the following packets:
  290.     // A:   Token   Packet: With a PID of IN or OUT.
  291.     // B:   Data    Packet: With a PID of DATA0 or DATA1, this packet is sent by the device if the token is OUT.
  292.     // C: Handshake Packet: From the host or from the device.
  293.  
  294.     for (i = 2; i < tds; i++) {
  295.  
  296.         td.T      = 0;  // Link is valid
  297.         td.QH     = 0;  // Link refers to a TD.
  298.         td.Vf     = 1;  // Depth first.
  299.         td.link   = krnl_get_selector_base(ds) + ((int) &uhci_tdlst[i + 1]);    // Next TD.
  300.  
  301.         td.PID    = data_stage_tokens_pid;  // Token PID.
  302.         td.D      = 1 - td.D;           // Data PID.
  303.         td.status = 0x80;           // Handshake PID will be set here.
  304.  
  305.         td.buffer = buf;
  306.         td.MaxLen = ((Max_Packet_Size < wLength) ? Max_Packet_Size : wLength) - 1;
  307.  
  308.         uhci_set_td(td, i);
  309.  
  310.         wLength -= Max_Packet_Size; // Calculate the size of the rest data.
  311.         buf += Max_Packet_Size; // Update the pointer.
  312.     }
  313.    
  314.     // III: Status Stage:
  315.     // ----------------------
  316.     // This stage doesn't send data, but it sends an IN or an OUT Token then receives a handshake:
  317.     // Token Packet: With PID of OUT [If Data Stage's tokens are IN] and vice versa.
  318.     // Handshake Packet: from the device or the Host, its PID confirming the success of the transfer.
  319.  
  320.     td.T      = 1;  // Link is not valid
  321.     td.QH     = 0;
  322.     td.Vf     = 0; 
  323.     td.link   = 0;
  324.    
  325.     td.PID    = status_stage_token_pid; // Token Packet PID.
  326.     td.D      = UHCI_DATA1;         // Data Packet PID of a non existent Packet.
  327.     td.status = 0x80;           // Handshake will be set here.
  328.  
  329.     td.buffer = 0;
  330.     td.MaxLen = 0x7FF; // No Data Packet.
  331.  
  332.     uhci_set_td(td, i);
  333.  
  334.     // Do the transfer:
  335.     uhci_qhlst[0].lng[1] = ((unsigned int) &uhci_tdlst[1] + krnl_get_selector_base(ds));
  336.    
  337.     for (i = 1; i <= tds; i++) {
  338.         //printk(" I: %x\n", i);
  339.         while ((status = ((uhci_tdlst[i].lng[1] & 0x00FF0000)>>16)) & 0x80);
  340.         if (status) break;
  341.     }
  342.    
  343.     uhci_qhlst[0].lng[1] = 0x00000001;
  344.     return status;
  345. }
  346.  
  347. unsigned char uhci_interrupt_transfer (unsigned char device, unsigned char EndPt, unsigned int buffer) {
  348.                
  349.     if (device == 128) return 0;
  350.    
  351.     unsigned int i, j, status;
  352.     for (i = 0; i < 10; i++) {
  353.         for (j = 0; j < 16; j++)
  354.             if ((devices[device].interfaces[i].endpoints[j].address & 0xF) == (EndPt & 0xF)) break;
  355.         if (j != 16) break;
  356.     }
  357.    
  358.     if (i == 10) return 1;
  359.     EndPt = devices[device].interfaces[i].endpoints[j].address;
  360.     static uhci_td td;
  361.     unsigned char speed = devices[device].speed;
  362.     unsigned char token_pid = (EndPt & 0x80) ? UHCI_PID_IN : UHCI_PID_OUT;
  363.     unsigned char data_pid = devices[device].interfaces[i].endpoints[j].Data_Toggle;
  364.     unsigned char Max_Packet = devices[device].interfaces[i].endpoints[j].Max_Packet;
  365.    
  366.     td.T       = 1;      // Link is not valid
  367.     td.QH      = 0;
  368.     td.Vf      = 0;
  369.     td.link    = 0;
  370.  
  371.     td.IOC     = 0;
  372.     td.ISO     = 0;
  373.     td.LS      = 1-speed; // 1: Low Speed, 0: Full Speed.
  374.     td.SPD     = 0;
  375.     td.ActLen  = 0;
  376.     td.C_ERR   = 0;
  377.    
  378.     td.device  = device;
  379.     td.EndPt   = EndPt & 0xF;
  380.     td.PID     = token_pid;     // Token Packet PID.
  381.     td.D       = data_pid;      // Data Packet PID.
  382.     td.status  = 0x80;      // Handshake Packet PID will be set here.
  383.     td.buffer  = buffer;
  384.     td.MaxLen  = Max_Packet - 1;
  385.  
  386.     uhci_set_td(td, 1);
  387.    
  388.     // Do the transfer:
  389.     uhci_qhlst[0].lng[1] = ((unsigned int) &uhci_tdlst[1] + krnl_get_selector_base(ds));
  390.     while ((status = ((uhci_tdlst[1].lng[1] & 0x00FF0000)>>16)) & 0x80);
  391.     if (status) printk(" Error: %x\n", status);
  392.     uhci_qhlst[0].lng[1] = 0x00000001;
  393.     return status;
  394. }
  395.  
  396.  
  397. unsigned char uhci_enumerate(unsigned char speed) {
  398.  
  399.     // This function is called when a new device is found. Any new device is normally in the default state.
  400.     unsigned int buf = krnl_get_selector_base(ds) + (int) uhci_buffer;
  401.     unsigned int i, j, k;
  402.     unsigned int config_size, string_size;
  403.     unsigned char iManufacturer, iProduct, iSerial, iConfiguration;
  404.    
  405.     // I: Clear the buffer
  406.     // -----------------------
  407.     for (i = 0; i < 0x200; i++) uhci_buffer[i] = 0;
  408.    
  409.     // II: Search for an empty device:
  410.     // -------------------------------
  411.     for (i = 1; i < 128; i++) if (!devices[i].Max_Packet) break;
  412.     if (i == 128) return 1;
  413.  
  414.     // III: Set Necessary & Default Device Information:
  415.     // --------------------------------------------------
  416.     devices[0].speed = devices[i].speed = speed;
  417.     devices[0].Max_Packet = devices[i].Max_Packet = 8; // The lowest Max Packet Size for EndPoint Zero.
  418.  
  419.     // IV: Set Address:
  420.     // -------------------
  421.     // The variable (i) is containing the new address of the device.
  422.     if (uhci_control_transfer(0, 0x00, 0x05, i, 0x0000, 0x0000, 0x00)) {
  423.         printk(" Error...\n");
  424.         return 0;
  425.     }
  426.  
  427.     // V: Get Device Descriptor:
  428.     // -----------------------------
  429.     uhci_control_transfer(i, 0x80, 0x06, 0x0100, 0x0000, 8, buf);   // First 8 bytes of Device Descriptor.
  430.     devices[i].Max_Packet = uhci_buffer[0x07];          // Get Max Packet Size for EndPoint Zero.
  431.     uhci_control_transfer(i, 0x80, 0x06, 0x0100, 0x0000, 18, buf);  // Read all of the Device Descriptor.
  432.  
  433.     // VI: Set Device Info:
  434.     // ---------------------------
  435.     devices[i].specs = (uhci_buffer[0x03]<<8) + uhci_buffer[0x02];
  436.     devices[i].cls   = (uhci_buffer[0x04]<<16) + (uhci_buffer[0x05]<<8) + uhci_buffer[0x06];
  437.     iManufacturer = uhci_buffer[0x0E];
  438.     iProduct = uhci_buffer[0x0F];
  439.     iSerial = uhci_buffer[0x10];
  440.    
  441.     // VII: Get Config Descriptor & Enter Configured State:
  442.     // --------------------------------------------------------
  443.     uhci_control_transfer(i, 0x80, 0x06, 0x0100, 0x0000, 18, buf);
  444.     uhci_control_transfer(i, 0x80, 0x06, 0x0200, 0, 8, buf); // Read First 8 Bytes of the Config Descriptor.
  445.     config_size = (uhci_buffer[0x3]<<8) + uhci_buffer[0x2];
  446.     uhci_control_transfer(i, 0x00, 0x09, uhci_buffer[0x5],0, 0, 0); // SET CONFIGURATION
  447.     uhci_control_transfer(i, 0x80, 0x06, 0x0200, 0, config_size, buf); // Read the full descriptor.
  448.     iConfiguration = uhci_buffer[0x6];
  449.  
  450.     // IIX: Analyse Config Desriptor:
  451.     // -------------------------------
  452.     unsigned int   ptr       = 0;
  453.     unsigned char  interface = 0xFF;
  454.     unsigned char  endpoint  = 0;
  455.    
  456.     while (ptr < config_size) {
  457.         // Ptr Refers to the start of a sub-descriptor;
  458.  
  459.         if (uhci_buffer[ptr + 1] == 4 && uhci_buffer[ptr + 2] != interface) {
  460.             // a Non-Alternative Interface Descriptor
  461.            
  462.             interface = uhci_buffer[ptr + 2];
  463.             endpoint = 0;   // Start a new endpoints list.
  464.             if (interface >= 10) break; // That's enough! we don't support more than 10 interfaces for a device.
  465.            
  466.             // Set Class Code:
  467.             devices[i].interfaces[interface].cls = (uhci_buffer[ptr + 5]<<16) +
  468.                         (uhci_buffer[ptr + 6]<<8) + uhci_buffer[ptr + 7];
  469.             if (!devices[i].interfaces[interface].cls) devices[i].interfaces[interface].cls = devices[i].cls;
  470.            
  471.             // String Desribes the Interface:
  472.             devices[i].interfaces[interface].string[0] = uhci_buffer[ptr + 8];
  473.         }
  474.        
  475.         if (uhci_buffer[ptr + 1] == 5) {
  476.             // an Endpoint Descriptor
  477.             // It is sure that the variable "interface" is reset before coming here...
  478.             devices[i].interfaces[interface].endpoints[endpoint].address = uhci_buffer[ptr + 2];
  479.             devices[i].interfaces[interface].endpoints[endpoint].attribs = uhci_buffer[ptr + 3];
  480.             devices[i].interfaces[interface].endpoints[endpoint].Max_Packet =
  481.                         (uhci_buffer[ptr + 5]<<8) + uhci_buffer[ptr + 4];
  482.             devices[i].interfaces[interface].endpoints[endpoint].interval = uhci_buffer[ptr + 6];
  483.             endpoint++;
  484.         }
  485.        
  486.         ptr += uhci_buffer[ptr]; // Next Descriptor
  487.     }
  488.    
  489.     // IX: Get Strings:
  490.     // ---------------------
  491.     if (iManufacturer) {
  492.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iManufacturer, 0x0409, 2, buf);
  493.         if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
  494.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iManufacturer, 0x0409, string_size, buf);
  495.         k = 0;
  496.         for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].manufacturer[k++] = uhci_buffer[j];
  497.     }
  498.        
  499.     if (iProduct) {
  500.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iProduct, 0x0409, 2, buf);
  501.         if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
  502.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iProduct, 0x0409, string_size, buf);
  503.         k = 0;
  504.         for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].product[k++] = uhci_buffer[j];
  505.     }
  506.    
  507.     if (iSerial) {
  508.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iSerial, 0x0409, 2, buf);
  509.         if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
  510.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iSerial, 0x0409, string_size, buf);
  511.         k = 0;
  512.         for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].serial[k++] = uhci_buffer[j];
  513.     }
  514.    
  515.     if (iConfiguration) {
  516.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iConfiguration, 0x0409, 2, buf);
  517.         if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
  518.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + iConfiguration, 0x0409, string_size, buf);
  519.         k = 0;
  520.         for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].configuration[k++] = uhci_buffer[j];
  521.     }
  522.    
  523.     for (unsigned int x = 0; devices[i].interfaces[x].cls; x++) {
  524.         unsigned int str;
  525.         if (!(str = devices[i].interfaces[x].string[0])) continue;
  526.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + str, 0x0409, 2, buf);
  527.         if ((string_size = uhci_buffer[0]) > 0x80) string_size = 0x80;
  528.         uhci_control_transfer(i, 0x80, 0x06, 0x0300 + str, 0x0409, string_size, buf);
  529.         k = 0;
  530.         for (j = 2; j < string_size; j+=2) if (uhci_buffer[j]) devices[i].interfaces[x].string[k++] = uhci_buffer[j];
  531.     }
  532.  
  533.     // X: Register device(s):
  534.     // ---------------------------
  535.     // Register Each Interface of the device in Device Manager
  536.     for(j = 0; devices[i].interfaces[j].cls; j++) {
  537.         unsigned static char id;
  538.         unsigned static short sel1, sel2;
  539.         unsigned static int off;
  540.         krnl_devman_add(0xFFFF, 0x02000000 | devices[i].interfaces[j].cls, &id,  &sel1, &sel2, &off);
  541.         devices[i].interfaces[j].devid = id;
  542.    
  543.         unsigned static int packet[32];
  544.         packet[0] = id;     // Device ID.
  545.         packet[1] = 1;      // Initialization Function
  546.         packet[2] = devid;  // The ID of this hc device driver.
  547.         packet[3] = id;     // The ID of the device.
  548.         packet[4] = i;      // The Device Address of the hub. 128 means this is the root hub.
  549.         packet[5] = j;      // The ID of the interface.
  550.         krnl_taskman_add_service(1, packet);    // Execute this after returning from this function (uhci_init).
  551.     }
  552.  
  553.     printk("\n");
  554.     printk(" Manufacturer: %s\n", devices[i].manufacturer);
  555.     printk(" Product: %s\n", devices[i].product);
  556.     printk(" Serial: %s\n", devices[i].serial);
  557.     printk(" Configuration: %s\n", devices[i].configuration);
  558.     printk(" Device: %d, Class: %x, Speed: %x, EndPt0 Max Packet: %x\n",i,devices[i].cls,devices[i].speed,devices[i].Max_Packet);
  559.     for(j = 0; devices[i].interfaces[j].cls; j++) {
  560.         printk("     Interface: %d, Class: %x, Title: %s\n", j, devices[i].interfaces[j].cls, devices[i].interfaces[j].string);
  561.         for (k = 0; devices[i].interfaces[j].endpoints[k].Max_Packet; k++)
  562.             printk("        - Endpoint %d, Address: %x, Attribs: %x, Max Packet: %d\n", k,
  563.                     devices[i].interfaces[j].endpoints[k].address,
  564.                     devices[i].interfaces[j].endpoints[k].attribs,
  565.                     devices[i].interfaces[j].endpoints[k].Max_Packet);
  566.     }
  567.     printk("\n");
  568.     getc();
  569.  
  570.     return i;
  571. }
  572.  
  573. void uhci_init() {
  574.    
  575.     asm("movw %%ds, %%ax":"=a"(ds));
  576.  
  577.     unsigned int  i, ehci;
  578.        
  579.     printk(" Initializing UHCI USB Device Driver ...\n");
  580.  
  581.     // I: Initialize UHCI Descriptors:
  582.     // ------------------------------------
  583.     // 1- Pointers:
  584.     uhci_frlst = (unsigned int   *)((unsigned int)(buffer     + 0x0FFF) & 0xFFFFF000);
  585.     uhci_qhlst = (eightbytelen   *)((unsigned int) uhci_frlst + 0x1000);
  586.     uhci_tdlst = (sixteenbytelen *)((unsigned int) uhci_qhlst + 0x0010);
  587.  
  588.     // 2- TDs:
  589.     uhci_tdlst[0].lng[0] = 0x00000001;
  590.     uhci_tdlst[0].lng[1] = 0x00000000;
  591.     uhci_tdlst[0].lng[2] = 0x00000000;
  592.     uhci_tdlst[0].lng[3] = 0x00000000;
  593.    
  594.     // 3- QHs:
  595.     uhci_qhlst[0].lng[0] = ((unsigned int) &uhci_qhlst[1] + krnl_get_selector_base(ds)) | 0x00000002;
  596.     uhci_qhlst[0].lng[1] = 0x00000001;
  597.     uhci_qhlst[1].lng[0] = 0x00000001;
  598.     uhci_qhlst[1].lng[1] = ((unsigned int) &uhci_tdlst[0] + krnl_get_selector_base(ds)) | 0x00000000;
  599.  
  600.     // 4- Frame List:
  601.     for (i = 0; i < 0x400; i++)
  602.         uhci_frlst[i] = ((unsigned int) &uhci_qhlst[0] + krnl_get_selector_base(ds)) | 0x00000002;
  603.  
  604.     // II: Setup PCI Registers:
  605.     // ----------------------------
  606.     // Search for the EHCI function in the bus\device...
  607.     for (ehci = 0; ehci < 8; ehci++)
  608.         if ((pci_readl(bus, dev, ehci, 8)>>8) == 0x0C0320) break;
  609.    
  610.     if (ehci < 8) {
  611.         static iospace eio;
  612.         unsigned int EECP, CAPID, CAPID_off;
  613.        
  614.         // There is a companion EHCI in the device, lets get its I/O or memory Base.
  615.         for (i = 0x10; i < 0x28; i += 4)
  616.             if (base = eio.configbase(pci_readl(bus, dev, ehci, i)))
  617.                 break;
  618.                
  619.         // The register [USBBASE + 8] is a dword. The second byte of it [EHCI Extended Capabilities Pointer]
  620.         // refers to the first PCI USBLEGSUP Register.
  621.         EECP = (eio.readregl(8) & 0x0000FF00) >> 8;
  622.        
  623.         if (EECP >= 0x40) {
  624.            
  625.             // The lowest bit of Byte 2 [Bit 16]: HCBIOSSEM [Host Controller BIOS Semaphore].
  626.             // The lowest bit of Byte 3 [Bit 24]: HCOSSEM [Host Controller OS Semaphore].
  627.             pci_writeb(pci_readb(bus, dev, ehci, EECP + 3) | 1, bus, dev, ehci, EECP + 3);  // Set HCOSSEM
  628.                
  629.             // Wait for BIOS to update HCBIOSSEM, if timeout occures, we will clear the word [EECP + 4].
  630.             timeout = tick_count() + 100; // 1sec.
  631.             while ((pci_readb(bus, dev, ehci, EECP + 2) & 1) and (tick_count() < timeout));
  632.             if (pci_readb(bus, dev, ehci, EECP + 2) & 1) pci_writew(0, bus, dev, ehci, EECP + 4);
  633.            
  634.             // Wait for HCOSSEM to be set.
  635.             timeout = tick_count() + 100; // 1sec.
  636.             while ((!(pci_readb(bus, dev, ehci, EECP + 3) & 1)) and (tick_count() < timeout));
  637.        
  638.             // After taking control over EHCI, delay for 10ms...
  639.             sleep(10);
  640.            
  641.             // The lowest byte of this PCI register is called "Capability ID". it indicates whether another
  642.             // PCI Register [EECP + 4] exists or not. Writing 0 to the word [EECP + 4] disables SMIs.
  643.             if (pci_readb(bus, dev, ehci, EECP + 0) == 0x01)
  644.                 pci_writew(0, bus, dev, ehci, EECP + 4);
  645.            
  646.             // Now We have the full control...
  647.             EECP = pci_readb(bus, dev, func, EECP + 1); // Next USBLEGSUP Register, if EECP = 0, the loop will stop.
  648.         }
  649.        
  650.  
  651.         // The lowest byte of the register [USBBASE + 0] is a dword contains the base address of Operational registers.
  652.         // The first byte of the dword register at [OP + 0x40] of these operational register will be set to Zero, in order
  653.         // to clear CF. clearing CF will make EHCI routes all its ports to UHCI.
  654.         eio.writeregb(0, eio.readregb(0) + 0x40);
  655.  
  656.     }
  657.    
  658.     // Turn off UHCI PIRQ and disable SMI. this shall turn off BIOS's legacy support.
  659.     pci_writew(0x8F00, bus, dev, func, 0xC0);
  660.    
  661.     // III: Initialize UHCI:
  662.     // ------------------------
  663.     // 1- Halt the HC:
  664.     usbio.writeregw(0xFFFF, UHCI_REG_USBSTS); // Clear Status Register.
  665.     unsigned int cmd = usbio.readregw(UHCI_REG_USBCMD);
  666.     if (cmd & 1) {
  667.         // the HC is running, we have to stop it.
  668.         cmd = cmd & 0xFFFE;
  669.         usbio.writeregw(cmd, UHCI_REG_USBCMD);
  670.         while (!(usbio.readregw(UHCI_REG_USBSTS) & 0x0020));
  671.     }
  672.    
  673.     // 2- Do a HCReset:
  674.     cmd &= 2;
  675.     usbio.writeregw(cmd, UHCI_REG_USBCMD);
  676.     while ((cmd = usbio.readregw(UHCI_REG_USBCMD)) & 2);
  677.    
  678.     // 3- Do a GReset:
  679.     cmd &= 4;
  680.     usbio.writeregw(cmd, UHCI_REG_USBCMD);
  681.     sleep(15);  // 1.5 Times is the minimum.
  682.     cmd &= 0xFFF8;  // Make Sure the least three bits are clear. [RUN, HCRESET, and GRESET].
  683.     usbio.writeregw(cmd, UHCI_REG_USBCMD);
  684.    
  685.     // 4- Make Devices Ready or Bus Activity:
  686.     cmd |= 0x0018;  // Enter Global Suspend Mode & Force Global Resume.
  687.     usbio.writeregw(cmd, UHCI_REG_USBCMD);
  688.     sleep(30);  // In this period, Global Resume Signals are active.
  689.     cmd = 0;    // Clear Command Register.
  690.     usbio.writeregw(cmd, UHCI_REG_USBCMD);
  691.     while (usbio.readregw(UHCI_REG_USBCMD)); // Wait Until Cleared.
  692.    
  693.     // 5- Setup Registers:
  694.     usbio.writeregw(0xFFFF, UHCI_REG_USBSTS);// Clear Status Register.
  695.     usbio.writeregw(0x00, UHCI_REG_USBINTR); // No Interrupts
  696.     usbio.writeregw(0x00, UHCI_REG_FRNUM);   // Start from Frame Number 0.
  697.     usbio.writeregl((unsigned int) uhci_frlst + krnl_get_selector_base(ds), UHCI_REG_FRBASEADD);
  698.     usbio.writeregb(64, UHCI_REG_SOFMOD);    // 64+11936=12000. (1ms for each frame).
  699.     usbio.writeregw(1, UHCI_REG_USBCMD);     // Change HC State to start.
  700.    
  701.     // IV: Initialize a Root Hub Driver:
  702.     // ------------------------------------
  703.     // 1- Set Information
  704.     devices[128].speed = 1;     // Full-Speed.
  705.     devices[128].specs = 0x0101;    // USB1.1.
  706.     devices[128].cls   = 0x090000;  // Hub
  707.     devices[128].Max_Packet = 8;    // Max Packet For EndPt Zero.
  708.     copystr("USB Root Hub", devices[128].product);
  709.     devices[128].interfaces[0].cls = 0x090000; // Hub;
  710.     devices[128].interfaces[0].endpoints[0].address    = 0x81; // EndPt1 - IN
  711.     devices[128].interfaces[0].endpoints[0].attribs    = 0x03; // Interrupt
  712.     devices[128].interfaces[0].endpoints[0].Max_Packet = 0x02; // Max Packet Size;
  713.     devices[128].interfaces[0].endpoints[0].interval   = 0x00; // Interval;
  714.    
  715.     // 2- Get the number of root ports:
  716.     for (i = 0x10; (usbio.readregw(i) != 0xFFFF) && (usbio.readregw(i) & 0x0080) && (i < 0x32); i+=2);
  717.     if (i == 0x30) i == 0x14;
  718.     uhci_ports = (i - 0x10) / 2;
  719.    
  720.     // 3- Register a device driver for it:
  721.     unsigned static char id;
  722.     unsigned static short sel1, sel2;
  723.     unsigned static int off;
  724.     krnl_devman_add(0xFFFF, 0x02090000, &id,  &sel1, &sel2, &off);
  725.     devices[128].interfaces[0].devid = id;
  726.    
  727.     // 4- Initialize the root hub device driver:
  728.     unsigned static int packet[32];
  729.     packet[0] = id;     // Device ID.
  730.     packet[1] = 1;      // Initialization Function
  731.     packet[2] = devid;  // The ID of this hc device driver.
  732.     packet[3] = id;     // The ID of the device.
  733.     packet[4] = 128;    // The Device Address of the hub. 128 means this is the root hub.
  734.     packet[5] = 0;      // The ID of the interface.
  735.     krnl_taskman_add_service(1, packet);    // Execute this after returning from this function (uhci_init).
  736.    
  737. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement