LibXenon
Bare-metal Xbox 360 homebrew library
Loading...
Searching...
No Matches
dev_usb_klsi.c
Go to the documentation of this file.
1/* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * USB Ethernet File: dev_usb_klsi.c
5 *
6 * Driver for USB Ethernet devices using Kawasaki KL5KUSB101B chip.
7 *
8 *********************************************************************
9 *
10 * Copyright 2000,2001,2002,2003,2005
11 * Broadcom Corporation. All rights reserved.
12 *
13 * This software is furnished under license and may be used and
14 * copied only in accordance with the following terms and
15 * conditions. Subject to these conditions, you may download,
16 * copy, install, use, modify and distribute modified or unmodified
17 * copies of this software in source and/or binary form. No title
18 * or ownership is transferred hereby.
19 *
20 * 1) Any source code used, modified or distributed must reproduce
21 * and retain this copyright notice and list of conditions
22 * as they appear in the source file.
23 *
24 * 2) No right is granted to use any trade name, trademark, or
25 * logo of Broadcom Corporation. The "Broadcom Corporation"
26 * name may not be used to endorse or promote products derived
27 * from this software without the prior written permission of
28 * Broadcom Corporation.
29 *
30 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
32 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
33 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
34 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
35 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
36 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
40 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
42 * THE POSSIBILITY OF SUCH DAMAGE.
43 ********************************************************************* */
44
45/* *********************************************************************
46 * Kawasaki KL5KUSB101B USB-Ethernet driver - CFE Network Layer Interfaces
47 ********************************************************************* */
48
49#include "cfe.h"
50
51#include "usbd.h"
52#include "usbeth.h"
53#include "klsi_fw.h"
54
55#if 0
56#define USBETH_TRACE( x, y ... ) xprintf( x, ##y )
57#else
58#define USBETH_TRACE( x, y ... ) ((void)0)
59#endif
60
61#define FAIL -1
62
63#define CACHE_ALIGN 32 /* XXX place holder, big enough to now. */
64#define ALIGN(n,align) (((n)+((align)-1)) & ~((align)-1))
65
66#define usb_dma_alloc(n) (KMALLOC(ALIGN((n),CACHE_ALIGN),CACHE_ALIGN))
67#define usb_dma_free(p) (KFREE(p))
68
69/******************************************************************************
70 Debug functions
71******************************************************************************/
72
73#ifndef USBETH_DEBUG
74#define USBETH_DEBUG 0
75#endif
76
77#if USBETH_DEBUG
78static void hexdump( unsigned char *src, int srclen, int rowlen, int rows )
79{
80 unsigned char *rowptr;
81 unsigned char *srcstp;
82 unsigned char *byteptr;
83
84 srcstp = src + srclen;
85
86 for( rowptr = src; rowptr < src + rowlen * rows; rowptr += rowlen ) {
87 for( byteptr = rowptr; byteptr < rowptr + rowlen && byteptr < srcstp; byteptr++ ) {
88 xprintf( "%2X ", *byteptr );
89 }
90 xprintf( "\n" );
91 }
92 xprintf( "\n" );
93}
94#else
95#define hexdump(src,srclen,rowlen,rows) ((void)0)
96#endif
97
98
99/* *********************************************************************
100 * Interface functions for USB-Ethernet adapters
101 ********************************************************************* */
102
103enum { VEN_NONE, ADS };
104static const char *VENDOR_NAMES[] = {
105 "?", "ADS", "Yikes!"
106};
107
108static const int ID_TBL[] = {
109 0x06E1, 0x0008, ADS,
110 -1
111};
112
113typedef struct klsi_softc_s {
120 uint8_t rxbuf[1600]; /* arbitrary but enough for ethernet packet */
122
123
124/* **************************************
125 * KAWASAKI LSI KL5KUSB101B I/F Functions.
126 ************************************** */
127
128static int klsi_send_eth_frame( void *ctx, hsaddr_t buf, int len );
129static int klsi_get_eth_frame( void *ctx, hsaddr_t buf );
130static int klsi_data_rx( void *ctx );
131static int klsi_get_dev_addr( void *ctx, hsaddr_t mac_addr );
132
133static usbeth_disp_t usbeth_klsi = {
134 klsi_get_eth_frame,
135 klsi_data_rx,
136 klsi_send_eth_frame,
137 klsi_get_dev_addr
138};
139
140
141static int klsi_load( klsi_softc_t *softc )
142{
143 usbdev_t *dev = softc->dev;
144
146 KLSI_SEND_SCAN, 0, 0,
147 (uint8_t *)kue_code_seg, sizeof(kue_code_seg) );
149 KLSI_SEND_SCAN, 0, 0,
150 (uint8_t *)kue_fix_seg, sizeof(kue_fix_seg) );
152 KLSI_SEND_SCAN, 0, 0,
153 (uint8_t *)kue_trig_seg, sizeof(kue_trig_seg) );
154
155 cfe_sleep(CFE_HZ/10);
156
157 return 0;
158}
159
160static int klsi_init_device( klsi_softc_t *softc )
161{
162 usb_device_descr_t dev_desc;
163 uint16_t vendor_id, device_id;
164 usbdev_t *dev = softc->dev;
165 uint16_t bcd_dev;
166 klsi_ether_desc_t *desc;
167 const int *ptr=ID_TBL;
168
169 /* find out which device is connected */
170 usb_get_device_descriptor( softc->dev, &dev_desc, 0 );
171 vendor_id = (dev_desc.idVendorHigh << 8) + dev_desc.idVendorLow;
172 device_id = (dev_desc.idProductHigh << 8) + dev_desc.idProductLow;
173
174 while( *ptr != -1 ) {
175 if( (vendor_id == ptr[0]) && (device_id == ptr[1]) ) {
176 softc->ven_code = ptr[2];
177 break;
178 }
179 ptr += 3;
180 }
181 if( *ptr == -1 ) {
182 xprintf( "Unknown Kawasaki USB-Ethernet device\n" );
183 return -1;
184 }
185
186 /* load the on-chip firmware, if necessary */
187 bcd_dev = ((dev->ud_devdescr.bcdDeviceHigh << 8) +
189 if ((bcd_dev & 0x0200) == 0) {
190 klsi_load(softc);
191 /* Should reload device descriptor here. */
193 cfe_sleep(CFE_HZ/10);
194 }
195 desc = usb_dma_alloc(sizeof(klsi_ether_desc_t));
197 KLSI_GET_ETH_DESC, 0, 0,
198 (uint8_t *)desc, sizeof(klsi_ether_desc_t));
199
200 if (USBETH_DEBUG) {
201 int i;
202 printf("klsi [dev %04x] ether descriptor\n", bcd_dev);
203 for (i = 0; i < sizeof(klsi_ether_desc_t); i++) {
204 printf(" %02x", ((uint8_t *)desc)[i]);
205 }
206 printf("\n");
207 }
208
209 memcpy( softc->mac_addr, desc->klsi_macaddr, 6);
210 usb_dma_free(desc);
211
213 KLSI_SET_URB_SIZE, 64, 0);
214
215 /* display adapter info */
216 xprintf( "%s USB-Ethernet Adapter (%a)\n",
217 VENDOR_NAMES[softc->ven_code], softc->mac_addr);
218
219 return 0;
220}
221
222static int klsi_get_dev_addr( void *ctx, hsaddr_t mac_addr )
223{
224 klsi_softc_t *softc = (klsi_softc_t *) ctx;
225 hs_memcpy_to_hs( mac_addr, softc->mac_addr, 6 );
226 return 0;
227}
228
229static void klsi_queue_rx( klsi_softc_t *softc )
230{
231 softc->rx_ur = usb_make_request(softc->dev, softc->bulk_inpipe,
232 softc->rxbuf, sizeof(softc->rxbuf),
234 usb_queue_request(softc->rx_ur);
235}
236
237static int klsi_data_rx( void *ctx )
238{
239 klsi_softc_t *softc = (klsi_softc_t *) ctx;
240 usb_poll(softc->dev->ud_bus);
241 return( !softc->rx_ur->ur_inprogress );
242}
243
244static int klsi_get_eth_frame( void *ctx, hsaddr_t buf )
245{
246 int len = 0;
247 klsi_softc_t *softc = (klsi_softc_t *) ctx;
248 uint8_t *rxbuf;
249
250 if( !softc->rx_ur->ur_inprogress ) {
251 rxbuf = softc->rxbuf;
252 len = softc->rx_ur->ur_xferred;
253
254 /* The klsi chip evidently completes the request with a
255 single zero byte when there is no packet available. */
256 if (len >= 2)
257 len = rxbuf[0] + (rxbuf[1] << 8);
258 else
259 len = 0;
260 rxbuf += 2;
261
262 if (len > 0) {
263#if USBETH_DEBUG
264 xprintf( "Incoming packet :\n" );
265 hexdump( rxbuf, len, 16, len / 16 + 1 );
266#endif
267 hs_memcpy_to_hs( buf, rxbuf, len );
268 }
269 usb_free_request(softc->rx_ur);
270 klsi_queue_rx( softc );
271 }
272 else
273 xprintf( "Bulk data is not available yet!\n" );
274
275 return( len );
276}
277
278static int klsi_send_eth_frame( void *ctx, hsaddr_t buf, int len )
279{
280 klsi_softc_t *softc = (klsi_softc_t *) ctx;
281 usbreq_t *ur;
282 int txlen = len;
283 unsigned char *txbuf;
284
285 txbuf = usb_dma_alloc(len+2);
286 txbuf[0] = txlen & 0xFF;
287 txbuf[1] = (txlen >> 8) & 0xFF; /* 1st two bytes...little endian */
288 hs_memcpy_from_hs( &txbuf[2], buf, txlen );
289 txlen += 2;
290
291 /* The klsi chip evidently needs at least one extra byte and a
292 length that is a multiple of 64. */
293 txlen += 64 - (txlen % 64);
294
295#if USBETH_DEBUG
296 xprintf( "Outgoing packet :\n" );
297 hexdump( txbuf, txlen, 16, txlen / 16 + 1 );
298#endif
299 ur = usb_make_request(softc->dev, softc->bulk_outpipe,
300 txbuf, txlen, UR_FLAG_OUT);
303 usb_dma_free(txbuf);
304
305 return( len );
306}
307
308static void klsi_open_device( klsi_softc_t *softc )
309{
310 /* Accept broadcast and own packets */
314
315 /* kick start the receive */
316 klsi_queue_rx( softc );
317}
318
319static void klsi_close_device( klsi_softc_t *softc )
320{
321 usbdev_t *dev = softc->dev;
322
324 KLSI_SET_PKT_FILTER, 0, 0);
325}
326
327
328/* *********************************************************************
329 * CFE-USB interfaces
330 ********************************************************************* */
331
332/* *********************************************************************
333 * klsi_attach(dev,drv)
334 *
335 * This routine is called when the bus scan stuff finds a usb-ethernet
336 * device. We finish up the initialization by configuring the
337 * device and allocating our softc here.
338 *
339 * Input parameters:
340 * dev - usb device, in the "addressed" state.
341 * drv - the driver table entry that matched
342 *
343 * Return value:
344 * 0
345 ********************************************************************* */
346
347const cfe_driver_t usbklsidrv; /* forward declaration */
348
349static int klsi_attach(usbdev_t *dev, usb_driver_t *drv)
350{
351 usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
352 usb_endpoint_descr_t *epdscr;
353 usb_endpoint_descr_t *indscr = NULL;
354 usb_endpoint_descr_t *outdscr = NULL;
355 usb_interface_descr_t *ifdscr;
356 klsi_softc_t *softc;
357 int idx;
358
359 dev->ud_drv = drv;
360
361 softc = (klsi_softc_t *) KMALLOC( sizeof(klsi_softc_t), 0 );
362 if( softc == NULL ) {
363 xprintf( "Failed to allocate softc memory.\n" );
364 return -1;
365 }
366 memset( softc, 0, sizeof(klsi_softc_t) );
367 dev->ud_private = softc;
368 softc->dev = dev;
369
371 if (ifdscr == NULL) {
372 xprintf("USBETH: ERROR...no interace descriptor\n");
373 return -1;
374 }
375
376 for (idx = 0; idx < 2; idx++) {
379 outdscr = epdscr;
380 else
381 indscr = epdscr;
382 }
383
384 if (!indscr || !outdscr) {
385 /*
386 * Could not get descriptors, something is very wrong.
387 * Leave device addressed but not configured.
388 */
389 xprintf("USBETH: ERROR...no endpoint descriptors\n");
390 return -1;
391 }
392
393 /* Choose the standard configuration. */
395
396 /* Quit if not able to initialize the device */
397 if (klsi_init_device(softc) < 0)
398 return -1;
399
400 /* Open the pipes. */
401 softc->bulk_inpipe = usb_open_pipe(dev,indscr);
402 softc->bulk_outpipe = usb_open_pipe(dev,outdscr);
403
404 /* Register the device */
405 usbeth_register(&usbeth_klsi,softc);
406
407 /* Open the device */
408 klsi_open_device( softc );
409
410 return 0;
411}
412
413/* *********************************************************************
414 * klsi_detach(dev)
415 *
416 * This routine is called when the bus scanner notices that
417 * this device has been removed from the system. We should
418 * do any cleanup that is required. The pending requests
419 * will be cancelled automagically.
420 *
421 * Input parameters:
422 * dev - usb device
423 *
424 * Return value:
425 * 0
426 ********************************************************************* */
427
428static int klsi_detach(usbdev_t *dev)
429{
430 klsi_softc_t *softc = (klsi_softc_t *) dev->ud_private;
431
432 if (softc != NULL) {
433 usbeth_unregister( softc );
434 klsi_close_device ( softc );
435 dev->ud_private = NULL;
436 softc->dev = NULL;
437 KFREE(softc);
438 }
439
440 return 0;
441}
442
443/* CFE USB device interface structure */
445{
446 "Ethernet Device",
447 klsi_attach,
448 klsi_detach
449};
450
451
452
void * hsaddr_t
Definition: cfe.h:11
#define NULL
Definition: def.h:47
usb_driver_t usbklsi_driver
Definition: dev_usb_klsi.c:444
#define hexdump(src, srclen, rowlen, rows)
Definition: dev_usb_klsi.c:95
#define USBETH_DEBUG
Definition: dev_usb_klsi.c:74
#define usb_dma_free(p)
Definition: dev_usb_klsi.c:67
#define usb_dma_alloc(n)
Definition: dev_usb_klsi.c:66
const cfe_driver_t usbklsidrv
Definition: dev_usb_klsi.c:347
struct klsi_softc_s klsi_softc_t
@ ADS
Definition: dev_usb_klsi.c:103
@ VEN_NONE
Definition: dev_usb_klsi.c:103
u32 ptr
Definition: iso9660.c:536
#define KMALLOC(size, align)
Definition: lib_malloc.h:92
#define KFREE(ptr)
Definition: lib_malloc.h:93
u16 uint16_t
Definition: libfdt_env.h:10
u8 uint8_t
Definition: libfdt_env.h:9
usbreq_t * rx_ur
Definition: dev_usb_klsi.c:119
usbdev_t * dev
Definition: dev_usb_klsi.c:114
uint8_t rxbuf[1600]
Definition: dev_usb_klsi.c:120
uint8_t mac_addr[6]
Definition: dev_usb_klsi.c:118
uint8_t bConfigurationValue
Definition: usbchap9.h:216
uint8_t idVendorLow
Definition: usbchap9.h:184
uint8_t bcdDeviceLow
Definition: usbchap9.h:186
uint8_t idProductLow
Definition: usbchap9.h:185
uint8_t idProductHigh
Definition: usbchap9.h:185
uint8_t bcdDeviceHigh
Definition: usbchap9.h:186
uint8_t idVendorHigh
Definition: usbchap9.h:184
uint8_t bEndpointAddress
Definition: usbchap9.h:196
Definition: usbd.h:141
usb_config_descr_t * ud_cfgdescr
Definition: usbd.h:150
usbbus_t * ud_bus
Definition: usbd.h:143
void * ud_private
Definition: usbd.h:148
usb_device_descr_t ud_devdescr
Definition: usbd.h:149
usb_driver_t * ud_drv
Definition: usbd.h:142
Definition: usbd.h:171
int ur_inprogress
Definition: usbd.h:195
int ur_xferred
Definition: usbd.h:187
#define USBREQ_TYPE_VENDOR
Definition: usbchap9.h:366
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usbchap9.h:66
#define USB_ENDPOINT_DIR_OUT(addr)
Definition: usbchap9.h:107
#define USBREQ_DIR_OUT
Definition: usbchap9.h:363
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usbchap9.h:65
#define USBREQ_DIR_IN
Definition: usbchap9.h:362
void * usb_find_cfg_descr(usbdev_t *dev, int dtype, int idx)
Definition: usbd.c:1237
int usb_simple_request(usbdev_t *dev, uint8_t reqtype, int bRequest, int wValue, int wIndex)
Definition: usbd.c:600
int usb_std_request(usbdev_t *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *buffer, int length)
Definition: usbd.c:796
int usb_sync_request(usbreq_t *ur)
Definition: usbd.c:550
usbreq_t * usb_make_request(usbdev_t *dev, int epaddr, uint8_t *buf, int length, int flags)
Definition: usbd.c:353
void usb_free_request(usbreq_t *ur)
Definition: usbd.c:457
void usb_poll(usbbus_t *bus)
Definition: usbd.c:392
int usb_queue_request(usbreq_t *ur)
Definition: usbd.c:502
int usb_get_device_descriptor(usbdev_t *dev, usb_device_descr_t *dscr, int smallflg)
Definition: usbd.c:1006
int usb_set_configuration(usbdev_t *dev, int config)
Definition: usbd.c:619
int usb_open_pipe(usbdev_t *dev, usb_endpoint_descr_t *epdesc)
Definition: usbd.c:165
#define UR_FLAG_OUT
Definition: usbd.h:165
#define UR_FLAG_IN
Definition: usbd.h:164
#define UR_FLAG_SHORTOK
Definition: usbd.h:168
int usbeth_register(usbeth_disp_t *disp, void *softc)
Definition: usbeth.c:78
void usbeth_unregister(void *softc)
Definition: usbeth.c:97
#define KLSI_SET_PKT_FILTER
Definition: usbeth.h:147
#define KLSI_RX_UNICAST
Definition: usbeth.h:168
#define KLSI_SET_URB_SIZE
Definition: usbeth.h:150
#define KLSI_SEND_SCAN
Definition: usbeth.h:142
struct klsi_ether_desc_s klsi_ether_desc_t
#define KLSI_RX_BROADCAST
Definition: usbeth.h:169
#define KLSI_GET_ETH_DESC
Definition: usbeth.h:145
int xprintf(char *str)
Definition: usbhack.c:404