2 * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
5 * Short descripton of file: sl811hs-hcdi.c
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * * Neither the name of the FH Augsburg nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 #include <core/core.h>
44 //#include <class/hub.h>
45 #include <usbspec/usb11spec.h>
47 void sl811_roothub_probe();
48 void sl811_roothub_check();
50 void sl811_start_transfer();
52 usb_device * device_on_downstream;
55 /* cuurent transferdescriptor on port a and port b */
56 usb_transfer_descriptor * td_usba;
57 usb_transfer_descriptor * td_usbb;
59 usb_driver sl811_roothub = {
60 .name = "sl811_roothub",
61 .probe = sl811_roothub_probe,
62 .check = sl811_roothub_check,
67 * Find and initial root hub
69 void sl811_roothub_probe()
71 // called on n every new enumeration and at usb_register_driver
72 // der sollte nach dem ersten aufruf igonriert werden
73 // oder diese funktion bleibt einfach leer
75 core.stdout("Probe: SL811 Root Hub\r\n");
81 * This function is called periodical, to notice
82 * port changes after an hub
84 void sl811_roothub_check()
86 /* hier muss man nur dafuer sorgen wenn ein geaert angesteckt
87 * wird, dass der entsprechende port auf reset gesetzt wird
88 * damit das device die adresse 0 annimmt
89 * und dann muss man usb_add_device aufrufen
91 * wenn ein geraet entfernt wird muss man nur usb_remove_device aufrufen
92 * und es muss dabei das richtige geraet angegeben werden.
93 * dieses muss man sich wahrscheinlich intern im treiber
96 // check for new device
97 u16 *port_change = (u16*)sl811_roothub.data;
99 u8 status = sl811_read(SL811_ISR);
100 sl811_write(SL811_ISR,SL811_ISR_DATA | SL811_ISR_SOFTIMER);
102 #define HUB_PORTSTATUS_C_PORT_CONNECTION 1
103 if((status & SL811_ISR_RESET)) { // TODO und bit x von CTRL
104 // remove device if neccessary
105 if(device_on_downstream!=NULL){
107 core.stdout("Remove Device!\r\n");
109 usb_remove_device(device_on_downstream);
110 device_on_downstream=NULL;
113 sl811_write(SL811_ISR,SL811_ISR_RESET);
115 if((port_change[0] & HUB_PORTSTATUS_C_PORT_CONNECTION)){
117 core.stdout("Find new Device!\r\n");
120 /* init sof currently for fullspeed (datasheet page 11)*/
121 sl811_write(SL811_CSOF,0xAE);
122 sl811_write(SL811_DATA,0xE0);
124 /* reset device that function can answer to address 0 */
125 sl811_write(SL811_IER,0x00);
126 sl811_write(SL811_CTRL,SL811_CTRL_ENABLESOF|SL811_CTRL_RESETENGINE);
127 sl811_write(SL811_ISR,0xff);
130 /* start SOF generation */
131 sl811_write(SL811_CTRL,SL811_CTRL_ENABLESOF);
132 sl811_write(SL811_ISR,0xff);
133 sl811_write(SL811_E0BASE,SL811_EPCTRL_ARM);
136 device_on_downstream = usb_add_device();
138 /* set internate port state 1=device is online */
144 if((status & SL811_ISR_INSERT)){
145 port_change[0] |= HUB_PORTSTATUS_C_PORT_CONNECTION;
146 sl811_write(SL811_ISR,SL811_ISR_INSERT);
154 /* find and initial host controller */
156 u8 rev = sl811_read(SL811_REV)>>4;
161 core.stdout("Host: SL811HS v1.2 found\r\n");
166 core.stdout("Host: SL811HS v1.5 found\r\n");
171 core.stdout("Can't find SL811!\r\n");
176 /* Disable interrupt, then wait 40 ms */
177 sl811_write(SL811_IER,0x00);
179 /* Initialize controller */
180 //sl811_write(SL811_CSOF,0xae);
181 sl811_write(SL811_CSOF,SL811_CSOF_MASTER);
183 /* clear interrupt status register with one read operation */
184 sl811_write(SL811_ISR,0xff);
186 /* data = hub flags */
187 u16 *port_change = (u16*)malloc(sizeof(u16));
188 port_change[0] = 0x00;
189 port_change[1] = 0x00;
190 sl811_roothub.data = (void*)port_change;
191 device_on_downstream = NULL;
194 /* register virtual root hub driver */
195 usb_register_driver(&sl811_roothub);
198 /* activate interrupts */
199 sl811_write(SL811_IER,SL811_IER_USBA);
203 * hcdi_enqueue takes usb_irp and split it into
204 * several usb packeges (SETUP,IN,OUT)
205 * In the usbstack they are transported with the
206 * usb_transfer_descriptor data structure.
209 u8 hcdi_enqueue(usb_transfer_descriptor *td)
213 sl811_start_transfer();
219 u8 hcdi_dequeue(usb_transfer_descriptor *td)
228 core.stdout("interrupt\r\n");
230 state = sl811_read(SL811_ISR);
231 if(state & SL811_ISR_USBA) {
232 core.stdout("a done\r\n");
234 if(state & SL811_ISR_USBB) {
235 core.stdout("b done\r\n");
237 if(state & SL811_ISR_RESET) {
238 core.stdout("reset\r\n");
241 if(state & SL811_ISR_INSERT) {
242 core.stdout("insert\r\n");
245 sl811_write(SL811_ISR,0xFF);
250 void sl811_start_transfer()
252 usb_transfer_descriptor * td;
255 /* choose next free port */
257 /* disable a done interrupt */
258 sl811_write(SL811_IER,0x00);
265 sl811_write(SL811_E0CONT,td->devaddress); /* device address */
266 sl811_write(SL811_E0LEN,td->actlen); /* number of bytes to transfer */
267 sl811_write(SL811_E0ADDR,cMemStart); /* set address to buffer in sl811 ram */
271 //core.stdout("*setup\r\n");
272 /* copy data into ram of sl811 */
273 sl811_write_buf(cMemStart,(unsigned char *)td->buffer,td->actlen);
275 sl811_write(SL811_E0STAT,PID_SETUP|td->endpoint); /* set pid and ep */
276 sl811_write(SL811_E0CTRL,DATA0_WR); /* send setup packet with DATA0 */
278 td->state = USB_TRANSFER_DESCR_SEND;
282 while((sl811_read(SL811_ISR)&SL811_ISR_USBA)==0);
289 //core.stdout("*in\r\n");
294 sl811_write(SL811_E0STAT,PID_IN|td->endpoint); /* set pid and ep */
295 sl811_write(SL811_ISR,0xff);
297 /* choose data0 or data1 */
299 sl811_write(SL811_E0CTRL,DATA1_RD); /* send setup packet with DATA0 */
301 sl811_write(SL811_E0CTRL,DATA0_RD); /* send setup packet with DATA0 */
303 td->state = USB_TRANSFER_DESCR_SEND;
307 while((sl811_read(SL811_ISR)&SL811_ISR_USBA)==0);
310 /* copy received data from internal sl811 ram */
311 sl811_read_buf(cMemStart,(unsigned char *)td->buffer,td->actlen);
318 //core.stdout("*out\r\n");
323 /* copy data into ram of sl811 */
325 sl811_write_buf(cMemStart,(unsigned char *)td->buffer,td->actlen);
327 sl811_write(SL811_E0STAT,PID_OUT|td->endpoint); /* set pid and ep */
329 /* choose data0 or data1 */
331 sl811_write(SL811_E0CTRL,DATA1_WR); /* send setup packet with DATA0 */
333 sl811_write(SL811_E0CTRL,DATA0_WR); /* send setup packet with DATA0 */
335 td->state = USB_TRANSFER_DESCR_SEND;
339 while((sl811_read(SL811_ISR)&SL811_ISR_USBA)==0);