Rev 846 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
846 | giacomo | 1 | /* |
2 | * Universal Host Controller Interface driver for USB. |
||
3 | * |
||
4 | * Maintainer: Johannes Erdfelt <johannes@erdfelt.com> |
||
5 | * |
||
6 | * (C) Copyright 1999 Linus Torvalds |
||
7 | * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com |
||
8 | * (C) Copyright 1999 Randy Dunlap |
||
9 | * (C) Copyright 1999 Georg Acher, acher@in.tum.de |
||
10 | * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de |
||
11 | * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch |
||
12 | */ |
||
13 | |||
14 | static __u8 root_hub_hub_des[] = |
||
15 | { |
||
16 | 0x09, /* __u8 bLength; */ |
||
17 | 0x29, /* __u8 bDescriptorType; Hub-descriptor */ |
||
18 | 0x02, /* __u8 bNbrPorts; */ |
||
19 | 0x00, /* __u16 wHubCharacteristics; */ |
||
20 | 0x00, |
||
21 | 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ |
||
22 | 0x00, /* __u8 bHubContrCurrent; 0 mA */ |
||
23 | 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ |
||
24 | 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ |
||
25 | }; |
||
26 | |||
27 | static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) |
||
28 | { |
||
29 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
||
30 | unsigned int io_addr = uhci->io_addr; |
||
31 | int i, len = 1; |
||
32 | |||
33 | *buf = 0; |
||
34 | for (i = 0; i < uhci->rh_numports; i++) { |
||
35 | *buf |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); |
||
36 | len = (i + 1) / 8 + 1; |
||
37 | } |
||
38 | |||
39 | return !!*buf; |
||
40 | } |
||
41 | |||
42 | #define OK(x) len = (x); break |
||
43 | |||
44 | #define CLR_RH_PORTSTAT(x) \ |
||
45 | status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ |
||
46 | status = (status & 0xfff5) & ~(x); \ |
||
47 | outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) |
||
48 | |||
49 | #define SET_RH_PORTSTAT(x) \ |
||
50 | status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ |
||
51 | status = (status & 0xfff5) | (x); \ |
||
52 | outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) |
||
53 | |||
54 | |||
55 | /* size of returned buffer is part of USB spec */ |
||
56 | static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, |
||
57 | u16 wIndex, char *buf, u16 wLength) |
||
58 | { |
||
59 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
||
60 | int i, status, retval = 0, len = 0; |
||
61 | unsigned int io_addr = uhci->io_addr; |
||
62 | __u16 cstatus; |
||
63 | char c_p_r[8]; |
||
64 | |||
65 | for (i = 0; i < 8; i++) |
||
66 | c_p_r[i] = 0; |
||
67 | |||
68 | switch (typeReq) { |
||
69 | /* Request Destination: |
||
70 | without flags: Device, |
||
71 | RH_INTERFACE: interface, |
||
72 | RH_ENDPOINT: endpoint, |
||
73 | RH_CLASS means HUB here, |
||
74 | RH_OTHER | RH_CLASS almost ever means HUB_PORT here |
||
75 | */ |
||
76 | |||
77 | case GetHubStatus: |
||
78 | *(__u32 *)buf = cpu_to_le32(0); |
||
79 | OK(4); /* hub power */ |
||
80 | case GetPortStatus: |
||
81 | status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1)); |
||
82 | cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | |
||
83 | ((status & USBPORTSC_PEC) >> (3 - 1)) | |
||
84 | (c_p_r[wIndex - 1] << (0 + 4)); |
||
85 | status = (status & USBPORTSC_CCS) | |
||
86 | ((status & USBPORTSC_PE) >> (2 - 1)) | |
||
87 | ((status & USBPORTSC_SUSP) >> (12 - 2)) | |
||
88 | ((status & USBPORTSC_PR) >> (9 - 4)) | |
||
89 | (1 << 8) | /* power on */ |
||
90 | ((status & USBPORTSC_LSDA) << (-8 + 9)); |
||
91 | |||
92 | *(__u16 *)buf = cpu_to_le16(status); |
||
93 | *(__u16 *)(buf + 2) = cpu_to_le16(cstatus); |
||
94 | OK(4); |
||
95 | case SetHubFeature: |
||
96 | switch (wValue) { |
||
97 | case C_HUB_OVER_CURRENT: |
||
98 | case C_HUB_LOCAL_POWER: |
||
99 | break; |
||
100 | default: |
||
101 | goto err; |
||
102 | } |
||
103 | break; |
||
104 | case ClearHubFeature: |
||
105 | switch (wValue) { |
||
106 | case C_HUB_OVER_CURRENT: |
||
107 | OK(0); /* hub power over current */ |
||
108 | default: |
||
109 | goto err; |
||
110 | } |
||
111 | break; |
||
112 | case SetPortFeature: |
||
113 | if (!wIndex || wIndex > uhci->rh_numports) |
||
114 | goto err; |
||
115 | |||
116 | switch (wValue) { |
||
117 | case USB_PORT_FEAT_SUSPEND: |
||
118 | SET_RH_PORTSTAT(USBPORTSC_SUSP); |
||
119 | OK(0); |
||
120 | case USB_PORT_FEAT_RESET: |
||
121 | SET_RH_PORTSTAT(USBPORTSC_PR); |
||
122 | mdelay(50); /* USB v1.1 7.1.7.3 */ |
||
123 | c_p_r[wIndex - 1] = 1; |
||
124 | CLR_RH_PORTSTAT(USBPORTSC_PR); |
||
125 | udelay(10); |
||
126 | SET_RH_PORTSTAT(USBPORTSC_PE); |
||
127 | mdelay(10); |
||
128 | SET_RH_PORTSTAT(0xa); |
||
129 | OK(0); |
||
130 | case USB_PORT_FEAT_POWER: |
||
131 | OK(0); /* port power ** */ |
||
132 | case USB_PORT_FEAT_ENABLE: |
||
133 | SET_RH_PORTSTAT(USBPORTSC_PE); |
||
134 | OK(0); |
||
135 | default: |
||
136 | goto err; |
||
137 | } |
||
138 | break; |
||
139 | case ClearPortFeature: |
||
140 | if (!wIndex || wIndex > uhci->rh_numports) |
||
141 | goto err; |
||
142 | |||
143 | switch (wValue) { |
||
144 | case USB_PORT_FEAT_ENABLE: |
||
145 | CLR_RH_PORTSTAT(USBPORTSC_PE); |
||
146 | OK(0); |
||
147 | case USB_PORT_FEAT_C_ENABLE: |
||
148 | SET_RH_PORTSTAT(USBPORTSC_PEC); |
||
149 | OK(0); |
||
150 | case USB_PORT_FEAT_SUSPEND: |
||
151 | CLR_RH_PORTSTAT(USBPORTSC_SUSP); |
||
152 | OK(0); |
||
153 | case USB_PORT_FEAT_C_SUSPEND: |
||
154 | /*** WR_RH_PORTSTAT(RH_PS_PSSC); */ |
||
155 | OK(0); |
||
156 | case USB_PORT_FEAT_POWER: |
||
157 | OK(0); /* port power */ |
||
158 | case USB_PORT_FEAT_C_CONNECTION: |
||
159 | SET_RH_PORTSTAT(USBPORTSC_CSC); |
||
160 | OK(0); |
||
161 | case USB_PORT_FEAT_C_OVER_CURRENT: |
||
162 | OK(0); /* port power over current */ |
||
163 | case USB_PORT_FEAT_C_RESET: |
||
164 | c_p_r[wIndex - 1] = 0; |
||
165 | OK(0); |
||
166 | default: |
||
167 | goto err; |
||
168 | } |
||
169 | break; |
||
170 | case GetHubDescriptor: |
||
171 | len = min_t(unsigned int, wLength, |
||
172 | min_t(unsigned int, sizeof(root_hub_hub_des), wLength)); |
||
173 | memcpy(buf, root_hub_hub_des, len); |
||
174 | if (len > 2) |
||
175 | buf[2] = uhci->rh_numports; |
||
176 | OK(len); |
||
177 | default: |
||
178 | err: |
||
179 | retval = -EPIPE; |
||
180 | } |
||
181 | |||
182 | return retval; |
||
183 | } |
||
184 |