original comment: +Wilson03172004,marked due to this pci host does not support MWI
[linux-2.4.git] / drivers / usb / host / hc_sl811_rh.c
1
2 /*-------------------------------------------------------------------------*/
3 /*-------------------------------------------------------------------------*
4  * SL811HS virtual root hub
5  *  
6  * based on usb-ohci.c by R. Weissgaerber et al.
7  *-------------------------------------------------------------------------*
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  *-------------------------------------------------------------------------*/
23
24 #ifdef DEBUG
25 #undef DEBUG
26 #endif
27 static __u32 getPortStatusAndChange (hci_t * hci);
28 static void setPortStatus (hci_t * hci, __u16 bitPos);
29 static void setPortChange (hci_t * hci, __u16 bitPos);
30 static void clrPortStatus (hci_t * hci, __u16 bitPos);
31 static void clrPortChange (hci_t * hci, __u16 bitPos);
32 static int USBReset (hci_t * hci);
33 static int cc_to_error (int cc);
34
35 /*-------------------------------------------------------------------------*
36  * Virtual Root Hub 
37  *-------------------------------------------------------------------------*/
38
39 /* Device descriptor */
40 static __u8 root_hub_dev_des[] = {
41         0x12,                   /*  __u8  bLength; */
42         0x01,                   /*  __u8  bDescriptorType; Device */
43         0x10,                   /*  __u16 bcdUSB; v1.1 */
44         0x01,
45         0x09,                   /*  __u8  bDeviceClass; HUB_CLASSCODE */
46         0x00,                   /*  __u8  bDeviceSubClass; */
47         0x00,                   /*  __u8  bDeviceProtocol; */
48         0x08,                   /*  __u8  bMaxPacketSize0; 8 Bytes */
49         0x00,                   /*  __u16 idVendor; */
50         0x00,
51         0x00,                   /*  __u16 idProduct; */
52         0x00,
53         0x00,                   /*  __u16 bcdDevice; */
54         0x00,
55         0x00,                   /*  __u8  iManufacturer; */
56         0x02,                   /*  __u8  iProduct; */
57         0x01,                   /*  __u8  iSerialNumber; */
58         0x01                    /*  __u8  bNumConfigurations; */
59 };
60
61 /* Configuration descriptor */
62 static __u8 root_hub_config_des[] = {
63         0x09,                   /*  __u8  bLength; */
64         0x02,                   /*  __u8  bDescriptorType; Configuration */
65         0x19,                   /*  __u16 wTotalLength; */
66         0x00,
67         0x01,                   /*  __u8  bNumInterfaces; */
68         0x01,                   /*  __u8  bConfigurationValue; */
69         0x00,                   /*  __u8  iConfiguration; */
70         0x40,                   /*  __u8  bmAttributes; 
71                                    Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 
72                                    4..0: resvd */
73         0x00,                   /*  __u8  MaxPower; */
74
75         /* interface */
76         0x09,                   /*  __u8  if_bLength; */
77         0x04,                   /*  __u8  if_bDescriptorType; Interface */
78         0x00,                   /*  __u8  if_bInterfaceNumber; */
79         0x00,                   /*  __u8  if_bAlternateSetting; */
80         0x01,                   /*  __u8  if_bNumEndpoints; */
81         0x09,                   /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
82         0x00,                   /*  __u8  if_bInterfaceSubClass; */
83         0x00,                   /*  __u8  if_bInterfaceProtocol; */
84         0x00,                   /*  __u8  if_iInterface; */
85
86         /* endpoint */
87         0x07,                   /*  __u8  ep_bLength; */
88         0x05,                   /*  __u8  ep_bDescriptorType; Endpoint */
89         0x81,                   /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
90         0x03,                   /*  __u8  ep_bmAttributes; Interrupt */
91         0x02,                   /*  __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
92         0x00,
93         0xff                    /*  __u8  ep_bInterval; 255 ms */
94 };
95
96 /* [Hub class-specific descriptor is constructed dynamically] */
97 /* copied from "dynamic source". (hne) */
98 static __u8 root_hub_hub_des[] =
99 {
100         0x09,                   /*  __u8  bLength; */
101         0x29,                   /*  __u8  bDescriptorType; Hub-descriptor */
102         0x01,                   /*  __u8  bNbrPorts; */
103         0x00,                   /* __u16  wHubCharacteristics; */
104         0x00,
105         0x50,                   /*  __u8  bPwrOn2pwrGood; 100ms for port reset */
106         0x00,                   /*  __u8  bHubContrCurrent; 0 mA */
107         0xfc, /* ??? HNE */     /*  __u8  DeviceRemovable; *** 7 Ports max *** */ /* which port is attachable (HNE) */
108         0xff                    /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
109 };
110
111
112 /***************************************************************************
113  * Function Name : rh_send_irq
114  * 
115  * This function examine the port change in the virtual root hub.
116  * 
117  * Note: This function assumes only one port exist in the root hub.
118  *
119  * Input:  hci = data structure for the host controller
120  *         rh_data = The pointer to port change data
121  *         rh_len = length of the data in bytes
122  *
123  * Return: length of data  
124  **************************************************************************/
125 static int rh_send_irq (hci_t * hci, void *rh_data, int rh_len)
126 {
127         int num_ports;
128         int i;
129         int ret;
130         int len;
131         __u8 data[8];
132
133         DBGFUNC ("enter rh_send_irq: \n");
134
135         /* Assuming the root hub has one port.  This value need to change if
136          * there are more than one port for the root hub
137          */
138
139         num_ports = 1;
140
141         /* The root hub status is not implemented, it basically has two fields:
142          *     -- Local Power Status
143          *     -- Over Current Indicator
144          *     -- Local Power Change
145          *     -- Over Current Indicator
146          *
147          * Right now, It is assume the power is good and no changes 
148          */
149
150         *(__u8 *) data = 0;
151
152         ret = *(__u8 *) data;
153
154         /* Has the port status change within the root hub: It checks for
155          *      -- Port Connect Status change
156          *      -- Port Enable Change
157          */
158
159         for (i = 0; i < num_ports; i++) {
160                 *(__u8 *) (data + (i + 1) / 8) |=
161                     (((getPortStatusAndChange (hci) >> 16) & (PORT_CONNECT_STAT | PORT_ENABLE_STAT)) ? 1 : 0) << ((i + 1) % 8);
162                 ret += *(__u8 *) (data + (i + 1) / 8);
163
164                 /* After the port change is read, it should be reset so the next time 
165                  * is it doesn't trigger a change again */
166
167         }
168         len = i / 8 + 1;
169
170         if (ret > 0) {
171                 memcpy (rh_data, data, min (len, (int)min (rh_len, (int)sizeof (data))));
172                 return len;
173         }
174         return 0;
175 }
176
177 /***************************************************************************
178  * Function Name : rh_int_timer_do
179  * 
180  * This function is called when the timer expires.  It gets the the port 
181  * change data and pass along to the upper protocol.
182  * 
183  * Note:  The virtual root hub interrupt pipe are polled by the timer
184  *        every "interval" ms
185  *
186  * Input:  ptr = ptr to the urb
187  *
188  * Return: none  
189  **************************************************************************/
190 static void rh_int_timer_do (unsigned long ptr)
191 {
192         int len;
193         struct urb *urb = (struct urb *) ptr;
194         hci_t *hci = urb->dev->bus->hcpriv;
195
196         DBGFUNC ("enter rh_int_timer_do\n");
197
198         if (hci->rh.send) {
199                 len = rh_send_irq (hci, urb->transfer_buffer,
200                                    urb->transfer_buffer_length);
201                 if (len > 0) {
202                         urb->actual_length = len;
203                         if (urb_debug == 2)
204                                 urb_print (urb, "RET-t(rh)",
205                                            usb_pipeout (urb->pipe));
206
207                         if (urb->complete) {
208                                 urb->complete (urb);
209                         }
210                 }
211         }
212
213         /* re-activate the timer */
214         rh_init_int_timer (urb);
215 }
216
217 /***************************************************************************
218  * Function Name : rh_init_int_timer
219  * 
220  * This function creates a timer that act as interrupt pipe in the
221  * virtual hub.   
222  * 
223  * Note:  The virtual root hub's interrupt pipe are polled by the timer
224  *        every "interval" ms
225  *
226  * Input: urb = USB request block 
227  *
228  * Return: 0  
229  **************************************************************************/
230 static int rh_init_int_timer (struct urb * urb)
231 {
232         hci_t *hci = urb->dev->bus->hcpriv;
233         hci->rh.interval = urb->interval;
234
235         init_timer (&hci->rh.rh_int_timer);
236         hci->rh.rh_int_timer.function = rh_int_timer_do;
237         hci->rh.rh_int_timer.data = (unsigned long) urb;
238         hci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
239         add_timer (&hci->rh.rh_int_timer);
240
241         return 0;
242 }
243
244 /*-------------------------------------------------------------------------*/
245
246 /* helper macro */
247 #define OK(x)                   len = (x); break
248
249 /***************************************************************************
250  * Function Name : rh_submit_urb
251  * 
252  * This function handles all USB request to the the virtual root hub
253  * 
254  * Input: urb = USB request block 
255  *
256  * Return: 0  
257  **************************************************************************/
258 static int rh_submit_urb (struct urb * urb)
259 {
260         struct usb_device *usb_dev = urb->dev;
261         hci_t *hci = usb_dev->bus->hcpriv;
262         unsigned int pipe = urb->pipe;
263         struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
264         void *data = urb->transfer_buffer;
265         int leni = urb->transfer_buffer_length;
266         int len = 0;
267         int status = TD_CC_NOERROR;
268         __u32 datab[4];
269         __u8 *data_buf = (__u8 *) datab;
270
271         __u16 bmRType_bReq;
272         __u16 wValue;
273         __u16 wIndex;
274         __u16 wLength;
275
276         DBGFUNC ("enter rh_submit_urb\n");
277         if (usb_pipeint (pipe)) {
278                 hci->rh.urb = urb;
279                 hci->rh.send = 1;
280                 hci->rh.interval = urb->interval;
281                 rh_init_int_timer (urb);
282                 urb->status = cc_to_error (TD_CC_NOERROR);
283
284                 return 0;
285         }
286
287         bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8);
288         wValue = le16_to_cpu (cmd->wValue);
289         wIndex = le16_to_cpu (cmd->wIndex);
290         wLength = le16_to_cpu (cmd->wLength);
291
292         DBG ("rh_submit_urb, req = %d(%x) len=%d",
293              bmRType_bReq, bmRType_bReq, wLength);
294
295         switch (bmRType_bReq) {
296                 /* Request Destination:
297                    without flags: Device, 
298                    RH_INTERFACE: interface, 
299                    RH_ENDPOINT: endpoint,
300                    RH_CLASS means HUB here, 
301                    RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
302                  */
303
304         case RH_GET_STATUS:
305                 *(__u16 *) data_buf = cpu_to_le16 (1);
306                 OK (2);
307
308         case RH_GET_STATUS | RH_INTERFACE:
309                 *(__u16 *) data_buf = cpu_to_le16 (0);
310                 OK (2);
311
312         case RH_GET_STATUS | RH_ENDPOINT:
313                 *(__u16 *) data_buf = cpu_to_le16 (0);
314                 OK (2);
315
316         case RH_GET_STATUS | RH_CLASS:
317                 *(__u32 *) data_buf = cpu_to_le32 (0);
318                 OK (4);
319
320         case RH_GET_STATUS | RH_OTHER | RH_CLASS:
321                 *(__u32 *) data_buf =
322                     cpu_to_le32 (getPortStatusAndChange (hci));
323                 OK (4);
324
325         case RH_CLEAR_FEATURE | RH_ENDPOINT:
326                 switch (wValue) {
327                 case (RH_ENDPOINT_STALL):
328                         OK (0);
329                 }
330                 break;
331
332         case RH_CLEAR_FEATURE | RH_CLASS:
333                 switch (wValue) {
334                 case RH_C_HUB_LOCAL_POWER:
335                         OK (0);
336
337                 case (RH_C_HUB_OVER_CURRENT):
338                         /* Over Current Not Implemented */
339                         OK (0);
340                 }
341                 break;
342
343         case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
344                 switch (wValue) {
345                 case (RH_PORT_ENABLE):
346                         clrPortStatus (hci, PORT_ENABLE_STAT);
347                         OK (0);
348
349                 case (RH_PORT_SUSPEND):
350                         clrPortStatus (hci, PORT_SUSPEND_STAT);
351                         OK (0);
352
353                 case (RH_PORT_POWER):
354                         clrPortStatus (hci, PORT_POWER_STAT);
355                         OK (0);
356
357                 case (RH_C_PORT_CONNECTION):
358                         clrPortChange (hci, PORT_CONNECT_STAT);
359                         OK (0);
360
361                 case (RH_C_PORT_ENABLE):
362                         clrPortChange (hci, PORT_ENABLE_STAT);
363                         OK (0);
364
365                 case (RH_C_PORT_SUSPEND):
366                         clrPortChange (hci, PORT_SUSPEND_STAT);
367                         OK (0);
368
369                 case (RH_C_PORT_OVER_CURRENT):
370                         clrPortChange (hci, PORT_OVER_CURRENT_STAT);
371                         OK (0);
372
373                 case (RH_C_PORT_RESET):
374                         clrPortChange (hci, PORT_RESET_STAT);
375                         OK (0);
376                 }
377                 break;
378
379         case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
380                 switch (wValue) {
381                 case (RH_PORT_SUSPEND):
382                         setPortStatus (hci, PORT_SUSPEND_STAT);
383                         OK (0);
384
385                 case (RH_PORT_RESET):
386                         setPortStatus (hci, PORT_RESET_STAT);
387                         // USBReset(hci);
388                         clrPortChange (hci,
389                                        PORT_CONNECT_CHANGE | PORT_ENABLE_CHANGE
390                                        | PORT_SUSPEND_CHANGE |
391                                        PORT_OVER_CURRENT_CHANGE);
392                         setPortChange (hci, PORT_RESET_CHANGE);
393                         clrPortStatus (hci, PORT_RESET_STAT);
394                         setPortStatus (hci, PORT_ENABLE_STAT);
395
396                         OK (0);
397
398                 case (RH_PORT_POWER):
399                         setPortStatus (hci, PORT_POWER_STAT);
400                         OK (0);
401
402                 case (RH_PORT_ENABLE):
403                         setPortStatus (hci, PORT_ENABLE_STAT);
404                         OK (0);
405                 }
406                 break;
407
408         case RH_SET_ADDRESS:
409                 hci->rh.devnum = wValue;
410                 OK (0);
411
412         case RH_GET_DESCRIPTOR:
413                 DBGVERBOSE ("rh_submit_urb: RH_GET_DESCRIPTOR, wValue = 0x%x\n", wValue);
414                 switch ((wValue & 0xff00) >> 8) {
415                 case (0x01):    /* device descriptor */
416                         len = min (leni, min ((__u16)sizeof (root_hub_dev_des), wLength));
417                         data_buf = root_hub_dev_des;
418                         OK (len);
419
420                 case (0x02):    /* configuration descriptor */
421                         len = min (leni, min ((__u16)sizeof (root_hub_config_des), wLength));
422                         data_buf = root_hub_config_des;
423                         OK (len);
424
425                 case (0x03):    /* string descriptors */
426                         len = usb_root_hub_string (wValue & 0xff, (int) (long) 0,
427                                                    "SL811HS", data, wLength);
428                         if (len > 0) {
429                                 data_buf = data;
430                                 OK (min (leni, len));
431                         }
432
433                 default:
434                         status = SL11H_STATMASK_STALL;
435                 }
436                 break;
437
438         case RH_GET_DESCRIPTOR | RH_CLASS:
439                 len = min_t(unsigned int, leni,
440                           min_t(unsigned int, sizeof (root_hub_hub_des), wLength));
441                 memcpy (data_buf, root_hub_hub_des, len);
442                 OK (len);
443
444         case RH_GET_CONFIGURATION:
445                 *(__u8 *) data_buf = 0x01;
446                 OK (1);
447
448         case RH_SET_CONFIGURATION:
449                 OK (0);
450
451         default:
452                 DBGERR ("unsupported root hub command");
453                 status = SL11H_STATMASK_STALL;
454         }
455
456         len = min (len, leni);
457         if (data != data_buf)
458                 memcpy (data, data_buf, len);
459         urb->actual_length = len;
460         urb->status = cc_to_error (status);
461
462         urb->hcpriv = NULL;
463         urb->dev = NULL;
464         if (urb->complete) {
465                 urb->complete (urb);
466         }
467
468         return 0;
469 }
470
471 /***************************************************************************
472  * Function Name : rh_unlink_urb
473  * 
474  * This function unlinks the URB 
475  * 
476  * Input: urb = USB request block 
477  *
478  * Return: 0  
479  **************************************************************************/
480 static int rh_unlink_urb (struct urb * urb)
481 {
482         hci_t *hci = urb->dev->bus->hcpriv;
483
484         DBGFUNC ("enter rh_unlink_urb\n");
485         if (hci->rh.urb == urb) {
486                 hci->rh.send = 0;
487                 del_timer (&hci->rh.rh_int_timer);
488                 hci->rh.urb = NULL;
489
490                 urb->hcpriv = NULL;
491                 /* ---
492                 usb_put_dev (urb->dev);
493
494                 Can not found this function, copy from old source and other source.
495                 usbnet.c us this to. Its a macro to usb_dec_dev_use. (hne)
496                 --- */
497                 usb_dec_dev_use(urb->dev);
498                 urb->dev = NULL;
499                 if (urb->transfer_flags & USB_ASYNC_UNLINK) {
500                         urb->status = -ECONNRESET;
501                         if (urb->complete) {
502                                 urb->complete (urb);
503                         }
504                 } else
505                         urb->status = -ENOENT;
506         }
507         return 0;
508 }
509
510 /***************************************************************************
511  * Function Name : rh_connect_rh
512  * 
513  * This function connect the virtual root hub to the USB stack 
514  * 
515  * Input: urb = USB request block 
516  *
517  * Return: 0  
518  **************************************************************************/
519 static int rh_connect_rh (hci_t * hci)
520 {
521         struct usb_device *usb_dev;
522
523         hci->rh.devnum = 0;
524         usb_dev = usb_alloc_dev (NULL, hci->bus);
525         if (!usb_dev)
526                 return -ENOMEM;
527
528         hci->bus->root_hub = usb_dev;
529         usb_connect (usb_dev);
530         if (usb_new_device (usb_dev) != 0) {
531                 usb_free_dev (usb_dev);
532                 return -ENODEV;
533         }
534
535         return 0;
536 }