Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1.  
  2. #define UHCI_USBLEGSUP          0x00c0  /* legacy support */
  3. #define UHCI_USBCMD                  0  /* command register */
  4. #define UHCI_USBINTR                 4  /* interrupt register */
  5. #define UHCI_USBLEGSUP_RWC      0x8f00  /* the R/WC bits */
  6. #define UHCI_USBLEGSUP_RO       0x5040  /* R/O and reserved bits */
  7. #define UHCI_USBCMD_RUN         0x0001  /* RUN/STOP bit */
  8. #define UHCI_USBCMD_HCRESET     0x0002  /* Host Controller reset */
  9. #define UHCI_USBCMD_EGSM        0x0008  /* Global Suspend Mode */
  10. #define UHCI_USBCMD_CONFIGURE   0x0040  /* Config Flag */
  11. #define UHCI_USBINTR_RESUME     0x0002  /* Resume interrupt enable */
  12.  
  13.  
  14. #define USBCMD                       0
  15. #define  USBCMD_RS              0x0001  /* Run/Stop */
  16. #define  USBCMD_HCRESET         0x0002  /* Host reset */
  17. #define  USBCMD_GRESET          0x0004  /* Global reset */
  18. #define  USBCMD_EGSM            0x0008  /* Global Suspend Mode */
  19. #define  USBCMD_FGR             0x0010  /* Force Global Resume */
  20. #define  USBCMD_SWDBG           0x0020  /* SW Debug mode */
  21. #define  USBCMD_CF              0x0040  /* Config Flag (sw only) */
  22. #define  USBCMD_MAXP            0x0080  /* Max Packet (0 = 32, 1 = 64) */
  23.  
  24. #define  USBSTS                      2
  25. #define   USBSTS_USBINT         0x0001  /* Interrupt due to IOC */
  26. #define   USBSTS_ERROR          0x0002  /* Interrupt due to error */
  27. #define   USBSTS_RD             0x0004  /* Resume Detect */
  28. #define   USBSTS_HSE            0x0008  /* Host System Error: PCI problems */
  29. #define   USBSTS_HCPE           0x0010  /* Host Controller Process Error:
  30.                                          * the schedule is buggy */
  31. #define   USBSTS_HCH            0x0020  /* HC Halted */
  32.  
  33.  
  34. #define  USBFRNUM                    6
  35. #define  USBFLBASEADD                8
  36. #define  USBSOF                     12
  37. #define  USBSOF_DEFAULT             64  /* Frame length is exactly 1 ms */
  38.  
  39. #define  USBPORTSC1                 16
  40. #define  USBPORTSC2                 18
  41.  
  42. #define  UHCI_RH_MAXCHILD            7
  43.  
  44.  
  45. /*
  46.  * Make sure the controller is completely inactive, unable to
  47.  * generate interrupts or do DMA.
  48.  */
  49. void uhci_reset_hc(hc_t *hc)
  50. {
  51.         /* Turn off PIRQ enable and SMI enable.  (This also turns off the
  52.          * BIOS's USB Legacy Support.)  Turn off all the R/WC bits too.
  53.          */
  54.    pciWriteWord(hc->PciTag, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC);
  55.  
  56.         /* Reset the HC - this will force us to get a
  57.          * new notification of any already connected
  58.          * ports due to the virtual disconnect that it
  59.          * implies.
  60.          */
  61.    out16(hc->iobase + UHCI_USBCMD, UHCI_USBCMD_HCRESET);
  62.    __asm__ __volatile__ ("":::"memory");
  63.  
  64.    delay(20/10);
  65.  
  66.    if (in16(hc->iobase + UHCI_USBCMD) & UHCI_USBCMD_HCRESET)
  67.        dbgprintf("HCRESET not completed yet!\n");
  68.  
  69.         /* Just to be safe, disable interrupt requests and
  70.          * make sure the controller is stopped.
  71.          */
  72.    out16(hc->iobase + UHCI_USBINTR, 0);
  73.    out16(hc->iobase + UHCI_USBCMD, 0);
  74. };
  75.  
  76. int uhci_check_and_reset_hc(hc_t *hc)
  77. {
  78.    u16_t legsup;
  79.         unsigned int cmd, intr;
  80.  
  81.         /*
  82.          * When restarting a suspended controller, we expect all the
  83.          * settings to be the same as we left them:
  84.          *
  85.          *      PIRQ and SMI disabled, no R/W bits set in USBLEGSUP;
  86.          *      Controller is stopped and configured with EGSM set;
  87.          *      No interrupts enabled except possibly Resume Detect.
  88.          *
  89.          * If any of these conditions are violated we do a complete reset.
  90.          */
  91.    legsup = pciReadWord(hc->PciTag, UHCI_USBLEGSUP);
  92.         if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) {
  93.        dbgprintf("%s: legsup = 0x%04x\n",__FUNCTION__, legsup);
  94.                 goto reset_needed;
  95.         }
  96.  
  97.    cmd = in16(hc->iobase + UHCI_USBCMD);
  98.    if ( (cmd & UHCI_USBCMD_RUN) ||
  99.        !(cmd & UHCI_USBCMD_CONFIGURE) ||
  100.        !(cmd & UHCI_USBCMD_EGSM))
  101.    {
  102.        dbgprintf("%s: cmd = 0x%04x\n", __FUNCTION__, cmd);
  103.                 goto reset_needed;
  104.         }
  105.  
  106.    intr = in16(hc->iobase + UHCI_USBINTR);
  107.    if (intr & (~UHCI_USBINTR_RESUME))
  108.    {
  109.        dbgprintf("%s: intr = 0x%04x\n", __FUNCTION__, intr);
  110.                 goto reset_needed;
  111.         }
  112.         return 0;
  113.  
  114. reset_needed:
  115.    dbgprintf("Performing full reset\n");
  116.    uhci_reset_hc(hc);
  117.         return 1;
  118. }
  119.  
  120.  
  121. Bool init_hc(hc_t *hc)
  122. {
  123.         int port;
  124.    u32_t ifl;
  125.    u16_t dev_status;
  126.    int i;
  127.  
  128.    dbgprintf("\n\ninit uhci %x\n\n", hc->pciId);
  129.  
  130.    for(i=0;i<6;i++)
  131.    {
  132.        if(hc->ioBase[i]){
  133.           hc->iobase = hc->ioBase[i];
  134.       //    dbgprintf("Io base_%d 0x%x\n", i,hc->ioBase[i]);
  135.           break;
  136.        };
  137.    };
  138.  
  139.         /* The UHCI spec says devices must have 2 ports, and goes on to say
  140.          * they may have more but gives no way to determine how many there
  141.          * are.  However according to the UHCI spec, Bit 7 of the port
  142.          * status and control register is always set to 1.  So we try to
  143.          * use this to our advantage.  Another common failure mode when
  144.          * a nonexistent register is addressed is to return all ones, so
  145.          * we test for that also.
  146.          */
  147.    for (port = 0; port < 2; port++)
  148.    {
  149.        u32_t status;
  150.  
  151.        status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  152.        dbgprintf("port%d status %x\n", port, status);
  153.        if (!(status & 0x0080) || status == 0xffff)
  154.                         break;
  155.         }
  156.    dbgprintf("detected %d ports\n\n", port);
  157.  
  158.    hc->numports = port;
  159.  
  160.         /* Kick BIOS off this hardware and reset if the controller
  161.          * isn't already safely quiescent.
  162.          */
  163.     uhci_check_and_reset_hc(hc);
  164.  
  165.     hc->frame_base   = (u32_t*)KernelAlloc(4096);
  166.     hc->frame_dma    = GetPgAddr(hc->frame_base);
  167.     hc->frame_number = 0;
  168.  
  169.     qh_t *qh = alloc_qh();
  170.  
  171.     qh->qlink = 1;
  172.     qh->qelem = 1;
  173.  
  174.     hc->qh1 = qh;
  175.  
  176.  //   dbgprintf("alloc qh %x dma %x\n", qh, qh->dma);
  177.  
  178.     for(i=0; i<1024; i++)
  179.         hc->frame_base[i] = qh->dma | 2;
  180.  
  181.  
  182.     /* Set the frame length to the default: 1 ms exactly */
  183.     out8(hc->iobase + USBSOF, USBSOF_DEFAULT);
  184.  
  185.         /* Store the frame list base address */
  186.     out32(hc->iobase + USBFLBASEADD, hc->frame_dma);
  187.  
  188.         /* Set the current frame number */
  189.     out16(hc->iobase + USBFRNUM, 0);
  190.  
  191.     out16(hc->iobase + USBSTS, 0x3F);
  192.     out16(hc->iobase + USBCMD, USBCMD_RS | USBCMD_CF |
  193.                                USBCMD_MAXP);
  194.  
  195.     for (port = 0; port < hc->numports; ++port)
  196.         out16(hc->iobase + USBPORTSC1 + (port * 2), 0x200);
  197.     delay(100/10);
  198.  
  199.     for (port = 0; port < 2; ++port)
  200.     {
  201.         time_t timeout;
  202.  
  203.         u32_t status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  204.         dbgprintf("port%d status %x\n", port, status);
  205.  
  206.         out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
  207.  
  208.         timeout = 100/10;
  209.         while(timeout--)
  210.         {
  211.             delay(10/10);
  212.             status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  213.             if(status & 1)
  214.             {
  215.                 udev_t *dev = malloc(sizeof(udev_t));
  216.  
  217.                 out16(hc->iobase + USBPORTSC1 + (port * 2), 0x0E);
  218.  
  219.                 delay(20/10);
  220.  
  221.                 dbgprintf("enable port\n");
  222.                 status = in16(hc->iobase + USBPORTSC1 + (port * 2));
  223.                 dbgprintf("port%d status %x\n", port, status);
  224.  
  225.                 link_initialize(&dev->link);
  226.                 dev->id       = 0;
  227.                 dev->host     = hc;
  228.                 dev->addr     = 0;
  229.                 dev->port     = port;
  230.                 dev->ep0_size = 8;
  231.                 dev->status   = status;
  232.  
  233.                 dbgprintf("port%d connected", port);
  234.                 if(status & 4)
  235.                     dbgprintf(" enabled");
  236.                 else
  237.                     dbgprintf(" disabled");
  238.                 if(status & 0x100){
  239.                     dev->speed = 0x4000000;
  240.                     dbgprintf(" low speed\n");
  241.                 } else {
  242.                     dev->speed = 0;
  243.                     dbgprintf(" full speed\n");
  244.                 };
  245.  
  246.                 if(set_address(dev)) {
  247.                     list_prepend(&dev->link, &newdev_list);
  248.                     hc->port_map |= 1<<port;
  249.                 }
  250.                 else {
  251.                     free(dev);
  252.                     out16(hc->iobase + USBPORTSC1 + (port * 2), 0);
  253.                 }
  254.                 break;
  255.             };
  256.         };
  257.     };
  258.     return TRUE;
  259. };
  260.  
  261. u16_t __attribute__((aligned(16)))
  262.       req_descr[4]  = {0x0680,0x0100,0x0000,8};
  263.  
  264. /*
  265. IN(69) OUT(E1) SETUP(2D)
  266. SETUP(0) IN(1)
  267. SETUP(0) OUT(1) OUT(0) OUT(1)...IN(1)
  268. SETUP(0) IN(1) IN(0) IN(1)...OUT(0)
  269. */
  270.  
  271.  
  272. Bool set_address(udev_t *dev)
  273. {
  274.     static  udev_id   = 0;
  275.     static  udev_addr = 0;
  276.     static  u16_t __attribute__((aligned(16)))
  277.             req_addr[4] = {0x0500,0x0001,0x0000,0x0000};
  278.  
  279.     static  u16_t __attribute__((aligned(16)))
  280.             req_descr[4]  = {0x0680,0x0100,0x0000,8};
  281.  
  282.     static  u32_t   data[2] __attribute__((aligned(16)));
  283.  
  284.     qh_t  *qh;
  285.     td_t  *td0, *td1, *td2;
  286.     u32_t   dev_status;
  287.     count_t timeout;
  288.     int address;
  289.  
  290.     address   = ++udev_addr;
  291.  
  292.     req_addr[1] = address;
  293.  
  294.     if( !ctrl_request(dev, &req_addr, DOUT, NULL, 0))
  295.         return FALSE;
  296.  
  297.     dev->addr = address;
  298.     dev->id   = (++udev_id << 8) | address;
  299.  
  300.     dbgprintf("set address %d\n", address);
  301.  
  302.     data[0] = 0;
  303.     data[1] = 0;
  304.  
  305.     if( !ctrl_request(dev, &req_descr, DIN, data, 8))
  306.         return FALSE;
  307.  
  308.     dev_descr_t *descr = (dev_descr_t*)&data;
  309.     dev->ep0_size = descr->bMaxPacketSize0;
  310.  
  311.     return TRUE;
  312. }
  313.  
  314. request_t *create_request(udev_t *dev, endp_t *enp, u32_t dir,
  315.                           void *data, size_t req_size)
  316. {
  317.     td_t  *td, *td_prev;
  318.     addr_t data_dma;
  319.  
  320.     request_t *rq = (request_t*)malloc(sizeof(request_t));
  321.  
  322.     link_initialize(&rq->link);
  323.  
  324.     rq->td_head = 0;
  325.     rq->td_tail = 0;
  326.  
  327.     rq->data = (addr_t)data;
  328.     rq->size = req_size;
  329.     rq->dev = dev;
  330.  
  331.     if(data)
  332.         data_dma = DMA(data);
  333.  
  334.     td_prev = NULL;
  335.  
  336.     while(req_size >= enp->size)
  337.     {
  338.         td = alloc_td();
  339.         td->link   = 1;
  340.  
  341.         if(rq->td_head == NULL)
  342.             rq->td_head = td;
  343.  
  344.         if( td_prev )
  345.             td_prev->link   = td->dma | 4;
  346.         td->status = 0x00800000 | dev->speed;
  347.         td->token  = TOKEN(enp->size,enp->toggle,enp->address,
  348.                            dev->addr,dir);
  349.         td->buffer = data_dma;
  350.         td->bk     = td_prev;
  351.  
  352.         td_prev = td;
  353.  
  354.         data_dma+= enp->size;
  355.         req_size-= enp->size;
  356.         enp->toggle ^= DATA1;
  357.     }
  358.     if(req_size)
  359.     {
  360.         td = alloc_td();
  361.         td->link   = 1;
  362.  
  363.         if(rq->td_head == NULL)
  364.             rq->td_head = td;
  365.  
  366.         if( td_prev )
  367.             td_prev->link   = td->dma | 4;
  368.  
  369.         td->status = 0x00800000 | dev->speed;
  370.         td->token  = TOKEN( req_size, enp->toggle, enp->address,
  371.                             dev->addr, dir);
  372.         td->buffer = data_dma;
  373.         td->bk     = td_prev;
  374.  
  375.         enp->toggle ^= DATA1;
  376.     }
  377.     rq->td_tail = td;
  378. /*
  379.     dbgprintf("create request %x\n"
  380.               "head           %x\n"
  381.               "tail           %x\n"
  382.               "data           %x\n"
  383.               "size           %x\n",
  384.               rq, rq->td_head, rq->td_tail,
  385.               rq->data, rq->size);
  386. */
  387.     return rq;
  388. }
  389.  
  390. Bool ctrl_request(udev_t *dev, void *req, u32_t pid,
  391.                   void *data, size_t req_size)
  392. {
  393.     size_t  packet_size = dev->ep0_size;
  394.     size_t  size = req_size;
  395.     u32_t   toggle = DATA1;
  396.  
  397.     td_t   *td0, *td, *td_prev;
  398.     qh_t   *qh;
  399.     addr_t  data_dma = 0;
  400.     Bool    retval;
  401.  
  402.     td0 = alloc_td();
  403.  
  404.     td0->status = 0x00800000 | dev->speed;
  405.     td0->token  = TOKEN( 8, DATA0, 0, dev->addr, 0x2D);
  406.     td0->buffer = DMA(req);
  407.     td0->bk     = NULL;
  408.  
  409.     if(data)
  410.         data_dma = DMA(data);
  411.  
  412.     td_prev = td0;
  413.  
  414.     while(size >= packet_size)
  415.     {
  416.         td = alloc_td();
  417.         td_prev->link   = td->dma | 4;
  418.         td->status = 0x00800000 | dev->speed;
  419.         td->token  = TOKEN(packet_size, toggle, 0,dev->addr, pid);
  420.         td->buffer = data_dma;
  421.         td->bk     = td_prev;
  422.  
  423.         td_prev = td;
  424.  
  425.         data_dma+= packet_size;
  426.         size-= packet_size;
  427.         toggle ^= DATA1;
  428.     }
  429.     if(size)
  430.     {
  431.         td = alloc_td();
  432.         td_prev->link   = td->dma | 4;
  433.         td->status = 0x00800000 | dev->speed;
  434.         td->token  = ((size-1)<<21)|toggle|(dev->addr<<8)|pid;
  435.         td->buffer = data_dma;
  436.         td->bk     = td_prev;
  437.  
  438.         td_prev = td;
  439.  
  440.         data_dma+= packet_size;
  441.         size-= packet_size;
  442.         toggle ^= DATA1;
  443.     }
  444.  
  445.     td = alloc_td();
  446.     td_prev->link   = td->dma | 4;
  447.  
  448.     pid = (pid == DIN) ? DOUT : DIN;
  449.  
  450.     td->link = 1;
  451.     td->status = 0x00800000 | dev->speed;
  452.     td->token  = (0x7FF<<21)|DATA1|(dev->addr<<8)|pid;
  453.     td->buffer = 0;
  454.     td->bk     = td_prev;
  455.  
  456.     qh = dev->host->qh1;
  457.  
  458.     qh->qelem = td0->dma;
  459.     __asm__ __volatile__ ("":::"memory");
  460.  
  461.     count_t timeout  = 25;
  462.     while(timeout--){
  463.         delay(10/10);
  464.         if( !(td->status & TD_CTRL_ACTIVE))
  465.             break;
  466.     }
  467.  
  468.     if( (td0->status & TD_ANY_ERROR) ||
  469.         (td_prev->status & TD_ANY_ERROR) ||
  470.         (td->status & TD_ANY_ERROR))
  471.     {
  472.         u32_t dev_status = in16(dev->host->iobase + USBSTS);
  473.  
  474.         dbgprintf("\nframe %x, cmd %x status %x\n",
  475.                    in16(dev->host->iobase + USBFRNUM),
  476.                    in16(dev->host->iobase + USBCMD),
  477.                     dev_status);
  478.         dbgprintf("td0 status %x\n",td0->status);
  479.         dbgprintf("td_prev status %x\n",td_prev->status);
  480.         dbgprintf("td status %x\n",td->status);
  481.         dbgprintf("qh %x \n", qh->qelem);
  482.  
  483.         retval = FALSE;
  484.     } else retval = TRUE;
  485.  
  486.     do
  487.     {
  488.         td_prev = td->bk;
  489.         free_td(td);
  490.         td = td_prev;
  491.     }while( td != NULL);
  492.  
  493.     return retval;
  494. };
  495.  
  496.  
  497. Bool init_device(udev_t *dev)
  498. {
  499.     static  u16_t __attribute__((aligned(16)))
  500.             req_descr[4]  = {0x0680,0x0100,0x0000,18};
  501.  
  502.     static  u16_t __attribute__((aligned(16)))
  503.             req_conf[4]  = {0x0680,0x0200,0x0000,9};
  504.  
  505.     static dev_descr_t __attribute__((aligned(16))) descr;
  506.  
  507.     interface_descr_t *interface;
  508.  
  509.     u32_t  data[8];
  510.  
  511.     u8_t *dptr;
  512.     conf_descr_t      *conf;
  513.  
  514.     dbgprintf("\ninit device %x, host %x, port %d\n\n",
  515.                dev->id, dev->host->pciId, dev->port);
  516.  
  517.     if( !ctrl_request(dev, req_descr, DIN, &descr, 18))
  518.         return;
  519.  
  520.     dev->dev_descr = descr;
  521.  
  522.     dbgprintf("device descriptor:\n\n"
  523.               "bLength             %d\n"
  524.               "bDescriptorType     %d\n"
  525.               "bcdUSB              %x\n"
  526.               "bDeviceClass        %x\n"
  527.               "bDeviceSubClass     %x\n"
  528.               "bDeviceProtocol     %x\n"
  529.               "bMaxPacketSize0     %d\n"
  530.               "idVendor            %x\n"
  531.               "idProduct           %x\n"
  532.               "bcdDevice           %x\n"
  533.               "iManufacturer       %x\n"
  534.               "iProduct            %x\n"
  535.               "iSerialNumber       %x\n"
  536.               "bNumConfigurations  %d\n\n",
  537.               descr.bLength, descr.bDescriptorType,
  538.               descr.bcdUSB,  descr.bDeviceClass,
  539.               descr.bDeviceSubClass, descr.bDeviceProtocol,
  540.               descr.bMaxPacketSize0, descr.idVendor,
  541.               descr.idProduct, descr.bcdDevice,
  542.               descr.iManufacturer, descr.iProduct,
  543.               descr.iSerialNumber, descr.bNumConfigurations);
  544.  
  545.     req_conf[3] = 8;
  546.     if( !ctrl_request(dev, req_conf, DIN, &data, 8))
  547.         return;
  548.  
  549.     conf = (conf_descr_t*)&data;
  550.  
  551.     size_t conf_size = conf->wTotalLength;
  552.  
  553.     req_conf[3] = conf_size;
  554.     conf = malloc(conf_size);
  555.  
  556.     if( !ctrl_request(dev, req_conf, DIN, conf, conf_size))
  557.         return;
  558.  
  559.     dptr = (u8_t*)conf;
  560.     dptr+= conf->bLength;
  561.  
  562.     dbgprintf("configuration descriptor\n\n"
  563.               "bLength             %d\n"
  564.               "bDescriptorType     %d\n"
  565.               "wTotalLength        %d\n"
  566.               "bNumInterfaces      %d\n"
  567.               "bConfigurationValue %x\n"
  568.               "iConfiguration      %d\n"
  569.               "bmAttributes        %x\n"
  570.               "bMaxPower           %dmA\n\n",
  571.               conf->bLength,
  572.               conf->bDescriptorType,
  573.               conf->wTotalLength,
  574.               conf->bNumInterfaces,
  575.               conf->bConfigurationValue,
  576.               conf->iConfiguration,
  577.               conf->bmAttributes,
  578.               conf->bMaxPower*2);
  579.  
  580.         interface = (interface_descr_t*)dptr;
  581.  
  582.         switch(interface->bInterfaceClass)
  583.         {
  584.             case USB_CLASS_AUDIO:
  585.                 dbgprintf( "audio device\n");
  586.                 break;
  587.             case USB_CLASS_HID:
  588.                 dev->conf = conf;
  589.                 list_remove(&dev->link);
  590.                 return init_hid(dev);
  591.  
  592.             case USB_CLASS_PRINTER:
  593.                 dbgprintf("printer\n");
  594.                 break;
  595.             case USB_CLASS_MASS_STORAGE:
  596.                 dbgprintf("mass storage device\n");
  597.                 break;
  598.             case USB_CLASS_HUB:
  599.                 dbgprintf("hub device\n");
  600.                 break;
  601.             default:
  602.                 dbgprintf("unknown device\n");
  603.         };
  604. };
  605.