Import 2.3.18pre1
[davej-history.git] / drivers / usb / ohci-root-hub.c
blob4d7e139ba9b1d4981c66d6f4829c40bb03b5b9c6
1 /*
2 * HCD (OHCI) Virtual Root Hub for USB.
4 * (C) Copyright 1999 Roman Weissgaerber (weissg@vienna.at)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * The Root Hub is build into the HC (UHCI or OHCI) hardware.
22 * This piece of code lets it look like it resides on the usb
23 * like the other hubs.
24 * (for anyone who wants to do a control operation on the root hub)
26 * v4.0 1999/08/18
27 * v2.1 1999/05/09
28 * v2.0 1999/05/04
29 * v1.0 1999/04/27
30 * ohci-root-hub.c
35 #include <linux/kernel.h>
36 #include <linux/delay.h>
37 #include <linux/ioport.h>
38 #include <linux/sched.h>
39 #include <linux/malloc.h>
40 #include <linux/string.h>
42 #include "usb.h"
43 #include "ohci-hcd.h"
45 #ifdef VROOTHUB
47 #include "ohci-root-hub.h"
49 static __u8 root_hub_dev_des[] =
51 0x12, /* __u8 bLength; */
52 0x01, /* __u8 bDescriptorType; Device */
53 0x00, /* __u16 bcdUSB; v1.0 */
54 0x01,
55 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
56 0x00, /* __u8 bDeviceSubClass; */
57 0x00, /* __u8 bDeviceProtocol; */
58 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
59 0x00, /* __u16 idVendor; */
60 0x00,
61 0x00, /* __u16 idProduct; */
62 0x00,
63 0x00, /* __u16 bcdDevice; */
64 0x00,
65 0x00, /* __u8 iManufacturer; */
66 0x00, /* __u8 iProduct; */
67 0x00, /* __u8 iSerialNumber; */
68 0x01 /* __u8 bNumConfigurations; */
72 /* Configuration descriptor */
73 static __u8 root_hub_config_des[] =
75 0x09, /* __u8 bLength; */
76 0x02, /* __u8 bDescriptorType; Configuration */
77 0x19, /* __u16 wTotalLength; */
78 0x00,
79 0x01, /* __u8 bNumInterfaces; */
80 0x01, /* __u8 bConfigurationValue; */
81 0x00, /* __u8 iConfiguration; */
82 0x40, /* __u8 bmAttributes;
83 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
84 0x00, /* __u8 MaxPower; */
86 /* interface */
87 0x09, /* __u8 if_bLength; */
88 0x04, /* __u8 if_bDescriptorType; Interface */
89 0x00, /* __u8 if_bInterfaceNumber; */
90 0x00, /* __u8 if_bAlternateSetting; */
91 0x01, /* __u8 if_bNumEndpoints; */
92 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
93 0x00, /* __u8 if_bInterfaceSubClass; */
94 0x00, /* __u8 if_bInterfaceProtocol; */
95 0x00, /* __u8 if_iInterface; */
97 /* endpoint */
98 0x07, /* __u8 ep_bLength; */
99 0x05, /* __u8 ep_bDescriptorType; Endpoint */
100 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
101 0x03, /* __u8 ep_bmAttributes; Interrupt */
102 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
103 0x00,
104 0xff /* __u8 ep_bInterval; 255 ms */
108 For OHCI we need just the 2nd Byte, so we
109 don't need this constant byte-array
111 static __u8 root_hub_hub_des[] =
113 0x00, * __u8 bLength; *
114 0x29, * __u8 bDescriptorType; Hub-descriptor *
115 0x02, * __u8 bNbrPorts; *
116 0x00, * __u16 wHubCharacteristics; *
117 0x00,
118 0x01, * __u8 bPwrOn2pwrGood; 2ms *
119 0x00, * __u8 bHubContrCurrent; 0 mA *
120 0x00, * __u8 DeviceRemovable; *** 8 Ports max *** *
121 0xff * __u8 PortPwrCtrlMask; *** 8 ports max *** *
125 #define OK(x) len = (x); req_reply = 0; break
126 #define WR_RH_STAT(x) writel((x), &ohci->regs->roothub.status)
127 #define WR_RH_PORTSTAT(x) writel((x), &ohci->regs->roothub.portstatus[wIndex-1])
128 #define RD_RH_STAT readl(&ohci->regs->roothub.status)
129 #define RD_RH_PORTSTAT readl(&ohci->regs->roothub.portstatus[wIndex-1])
131 int root_hub_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest * cmd, void *data, int leni)
133 struct ohci * ohci = usb_dev->bus->hcpriv;
134 __u8 data_buf[16];
135 int req_reply=4;
137 int len =leni;
139 __u16 bmRType_bReq = cmd->requesttype | (cmd->request << 8);
140 __u16 wValue = cpu_to_le16(cmd->value);
141 __u16 wIndex = cpu_to_le16(cmd->index);
142 __u16 wLength = cpu_to_le16(cmd->length);
144 OHCI_DEBUG(printk("USB root hub: adr: %2x cmd(%1x): ", ohci->rh.devnum, 8);)
145 OHCI_DEBUG({ int i; for(i=0;i<8;i++) printk(" %02x", ((unsigned char *)cmd)[i]);})
146 OHCI_DEBUG(printk(" ; \n");)
148 switch (bmRType_bReq) {
149 /* Request Destination:
150 without flags: Device,
151 RH_INTERFACE: interface,
152 RH_ENDPOINT: endpoint,
153 RH_CLASS means HUB here,
154 RH_OTHER | RH_CLASS almost ever means HUB_PORT here
157 case RH_GET_STATUS: *(__u16 *)data = cpu_to_le16(1); OK(2);
158 case RH_GET_STATUS | RH_INTERFACE: *(__u16 *)data = cpu_to_le16(0); OK(2);
159 case RH_GET_STATUS | RH_ENDPOINT: *(__u16 *)data = cpu_to_le16(0); OK(2);
160 case RH_GET_STATUS | RH_CLASS: *(__u32 *)data = cpu_to_le32(RD_RH_STAT & 0x7fff7fff); OK(4);
161 case RH_GET_STATUS | RH_OTHER | RH_CLASS: *(__u32 *)data = cpu_to_le32(RD_RH_PORTSTAT); OK(4);
163 case RH_CLEAR_FEATURE | RH_ENDPOINT:
164 switch (wValue) {
165 case (RH_ENDPOINT_STALL): OK(0);
167 break;
169 case RH_CLEAR_FEATURE | RH_CLASS:
170 switch (wValue) {
171 case (RH_C_HUB_OVER_CURRENT): WR_RH_STAT(RH_PS_OCIC); OK(0);
173 break;
175 case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
176 switch (wValue) {
177 case (RH_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_CCS ); OK(0);
178 case (RH_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_POCI); OK(0);
179 case (RH_PORT_POWER): WR_RH_PORTSTAT(RH_PS_LSDA); OK(0);
180 case (RH_C_PORT_CONNECTION): WR_RH_PORTSTAT(RH_PS_CSC ); OK(0);
181 case (RH_C_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_PESC); OK(0);
182 case (RH_C_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_PSSC); OK(0);
183 case (RH_C_PORT_OVER_CURRENT): WR_RH_PORTSTAT(RH_PS_OCIC); OK(0);
184 case (RH_C_PORT_RESET): WR_RH_PORTSTAT(RH_PS_PRSC); OK(0);
186 break;
188 case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
189 switch (wValue) {
190 case (RH_PORT_SUSPEND): WR_RH_PORTSTAT(RH_PS_PSS ); OK(0);
191 case (RH_PORT_RESET): if((RD_RH_PORTSTAT &1) != 0) WR_RH_PORTSTAT(RH_PS_PRS ); /* BUG IN HUP CODE *********/ OK(0);
192 case (RH_PORT_POWER): WR_RH_PORTSTAT(RH_PS_PPS ); OK(0);
193 case (RH_PORT_ENABLE): WR_RH_PORTSTAT(RH_PS_PES ); OK(0);
195 break;
197 case RH_SET_ADDRESS: ohci->rh.devnum = wValue; OK(0);
199 case RH_GET_DESCRIPTOR:
200 switch ((wValue & 0xff00) >> 8) {
201 case (0x01): /* device descriptor */
202 len = min(leni, min(sizeof(root_hub_dev_des), wLength));
203 memcpy(data, root_hub_dev_des, len); OK(len);
204 case (0x02): /* configuration descriptor */
205 len = min(leni, min(sizeof(root_hub_config_des), wLength));
206 memcpy(data, root_hub_config_des, len); OK(len);
207 case (0x03): /* string descriptors */
208 default:
210 break;
212 case RH_GET_DESCRIPTOR | RH_CLASS:
213 *(__u8 *)(data_buf+1) = 0x29;
214 *(__u32 *)(data_buf+2) = cpu_to_le32(readl(&ohci->regs->roothub.a));
215 *(__u8 *)data_buf = (*(__u8 *)(data_buf+2) / 8) * 2 + 9; /* length of descriptor */
217 len = min(leni, min(*(__u8 *)data_buf, wLength));
218 *(__u8 *)(data_buf+6) = 0; /* Root Hub needs no current from bus */
219 if(*(__u8 *)(data_buf+2) < 8) { /* less than 8 Ports */
220 *(__u8 *) (data_buf+7) = readl(&ohci->regs->roothub.b) & 0xff;
221 *(__u8 *) (data_buf+8) = (readl(&ohci->regs->roothub.b) & 0xff0000) >> 16;
223 else {
224 *(__u32 *) (data_buf+7) = cpu_to_le32(readl(&ohci->regs->roothub.b));
226 memcpy(data, data_buf, len);
227 OK(len);
229 case RH_GET_CONFIGURATION: *(__u8 *)data = 0x01; OK(1);
231 case RH_SET_CONFIGURATION: WR_RH_STAT( 0x10000); OK(0);
234 OHCI_DEBUG(printk("USB HC roothubstat1: %x \n", readl( &(ohci->regs->roothub.portstatus[0]) ));)
235 OHCI_DEBUG(printk("USB HC roothubstat2: %x \n", readl( &(ohci->regs->roothub.portstatus[1]) ));)
238 return req_reply;
241 /* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
242 static int root_hub_send_irq(struct ohci * ohci, void * rh_data, int rh_len ) {
244 int num_ports;
245 int i;
246 int ret;
247 int len;
249 __u8 * data = rh_data;
251 num_ports = readl(&ohci->regs->roothub.a) & 0xff;
252 *(__u8 *)data = (readl(&ohci->regs->roothub.status) & 0x00030000)>0?1:0;
253 ret = *(__u8 *)data;
255 for(i=0; i < num_ports; i++) {
256 *(__u8 *)(data+i/8) |= ((readl(&ohci->regs->roothub.portstatus[i]) & 0x001f0000)>0?1:0) << ((i+1) % 8);
257 ret += *(__u8 *)(data+i/8);
259 len = i/8 + 1;
261 if (ret > 0) return len;
263 return RH_NACK;
267 static int ohci_init_rh_int_timer(struct usb_device * usb_dev, int interval);
269 /* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
270 static void rh_int_timer_do(unsigned long ptr) {
271 int len;
272 int interval;
273 int ret;
275 struct usb_device * usb_dev = (struct usb_device *) ptr;
276 struct ohci * ohci = usb_dev->bus->hcpriv;
277 struct ohci_device * dev = usb_to_ohci(usb_dev);
280 if(ohci->rh.send) {
281 len = root_hub_send_irq(ohci, dev->data, 1 );
283 if(len > 0) {
285 ret = ohci->rh.handler(0, dev->data, len, ohci->rh.dev_id);
286 if(ret <= 0)ohci->rh.send = 0; /* 0 .. do not requeue */
289 interval = ohci->rh.interval;
290 ohci_init_rh_int_timer(usb_dev, interval);
293 /* Root Hub INTs are polled by this timer */
294 static int ohci_init_rh_int_timer(struct usb_device * usb_dev, int interval) {
295 struct ohci * ohci = usb_dev->bus->hcpriv;
297 ohci->rh.interval = interval;
298 init_timer(& ohci->rh.rh_int_timer);
299 ohci->rh.rh_int_timer.function = rh_int_timer_do;
300 ohci->rh.rh_int_timer.data = (unsigned long) usb_dev;
301 ohci->rh.rh_int_timer.expires = jiffies + (HZ * (interval<30?30: interval)) /1000;
302 add_timer(&ohci->rh.rh_int_timer);
304 return 0;
307 static int ohci_del_rh_int_timer(struct ohci * ohci) {
308 del_timer(&ohci->rh.rh_int_timer);
309 return 0;
312 void * root_hub_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
314 struct ohci * ohci = usb_dev->bus->hcpriv;
316 OHCI_DEBUG( printk("USB HC-RH IRQ>>>: RH every %d ms\n", period);)
317 ohci->rh.handler = handler;
318 ohci->rh.dev_id = dev_id;
319 ohci->rh.send = 1;
320 ohci->rh.interval = period;
321 ohci_init_rh_int_timer(usb_dev, period);
322 return ohci->rh.int_addr = usb_to_ohci(usb_dev);
325 int root_hub_release_irq(struct usb_device *usb_dev, void * ed)
327 // struct usb_device *usb_dev = ((struct ohci_device *) ((unsigned int)ed & 0xfffff000))->usb;
328 struct ohci * ohci = usb_dev->bus->hcpriv;
330 OHCI_DEBUG( printk("USB HC-RH RM_IRQ>>>:\n");)
331 ohci->rh.send = 0;
332 ohci_del_rh_int_timer(ohci);
333 return 0;
338 #endif