LibXenon
Bare-metal Xbox 360 homebrew library
Loading...
Searching...
No Matches
dev_usb_pegasus.c
Go to the documentation of this file.
1/* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * USB Ethernet File: dev_usb_pegasus.c
5 *
6 * Driver for USB Ethernet devices using ADMTEK Pegasus 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 * USB-Ethernet driver - CFE Network Layer Interfaces
47 ********************************************************************* */
48
49#include "cfe.h"
50
51#include "usbd.h"
52#include "usbeth.h"
53
54#if 0
55#define USBETH_TRACE( x, y ... ) xprintf( x, ##y )
56#else
57#define USBETH_TRACE( x, y ... ) ((void)0)
58#endif
59
60#define FAIL -1
61
62#define CACHE_ALIGN 32 /* XXX place holder, big enough to now. */
63#define ALIGN(n,align) (((n)+((align)-1)) & ~((align)-1))
64
65#define usb_dma_alloc(n) (KMALLOC(ALIGN((n),CACHE_ALIGN),CACHE_ALIGN))
66#define usb_dma_free(p) (KFREE(p))
67
68/******************************************************************************
69 Debug functions
70******************************************************************************/
71
72#ifndef USBETH_DEBUG
73#define USBETH_DEBUG 0
74#endif
75
76#if USBETH_DEBUG
77static void hexdump( unsigned char * src, int srclen, int rowlen, int rows )
78{
79 unsigned char *rowptr;
80 unsigned char *srcstp;
81 unsigned char *byteptr;
82
83 srcstp = src + srclen;
84
85 for( rowptr = src; rowptr < src + rowlen * rows; rowptr += rowlen ) {
86 for( byteptr = rowptr; byteptr < rowptr + rowlen && byteptr < srcstp; byteptr++ ) {
87 xprintf( "%2X ", *byteptr );
88 }
89 xprintf( "\n" );
90 }
91 xprintf( "\n" );
92}
93#else
94#define hexdump(src,srclen,rowlen,rows) ((void)0)
95#endif
96
97
98/* *********************************************************************
99 * Interface functions for USB-Ethernet adapters
100 ********************************************************************* */
101
104static const char *VENDOR_NAMES[] = {
105 "?", "3-COM", "LinkSys", "LinkSys-10TX", "LinkSys-100TX", "Yikes!"
106};
107
108static const int ID_TBL[] = {
109 0x0506, 0x4601, PEGASUS_II, _3_COM, /* 3-Com */
110 0x066b, 0x2202, PEGASUS_II, LINKSYS_10, /* LinkSys */
111 0x066b, 0x2203, PEGASUS, LINKSYS_100,
112 0x066b, 0x2204, PEGASUS, LINKSYS_100,
113 0x066b, 0x2206, PEGASUS, LINKSYS,
114 0x066b, 0x400b, PEGASUS_II, LINKSYS_10,
115 0x066b, 0x200c, PEGASUS_II, LINKSYS_10,
116 -1
117};
118
119typedef struct peg_softc_s {
127 uint8_t rxbuf[1600]; /* arbitrary but enough for ethernet packet */
129
130
131/* **************************************
132 * ADMTEK PEGASUS I/F Functions
133 ************************************** */
134
135static int peg_send_eth_frame( void *ctx, hsaddr_t buf, int len );
136static int peg_get_eth_frame( void *ctx, hsaddr_t buf );
137static int peg_data_rx( void *ctx );
138static int peg_get_dev_addr( void *ctx, hsaddr_t mac_addr );
139
140static usbeth_disp_t usbeth_peg = {
141 peg_get_eth_frame,
142 peg_data_rx,
143 peg_send_eth_frame,
144 peg_get_dev_addr
145};
146
147
148static int peg_get_reg( usbdev_t *dev, int16_t reg, uint8_t *val, int16_t len )
149{
151 PEG_GET_REG, 0, reg, val, len );
152}
153
154static int peg_set_reg( usbdev_t *dev, int16_t reg, int16_t val )
155{
156 unsigned char data = (uint8_t) val & 0xff;
157
159 PEG_SET_REG, val, reg, &data, 1 );
160}
161
162static int peg_set_regs( usbdev_t *dev, int16_t reg, int8_t *vals, int16_t len )
163{
165 PEG_SET_REG, 0, reg, (uint8_t *)vals, len );
166}
167
168static int peg_get_eep_word( usbdev_t *dev, int16_t ofs, uint8_t *val )
169{
170 int status=0, tries=20;
171 uint8_t data[2];
172
173 if( peg_set_reg( dev, R_PEG_EEPROM_CTL, 0 ) == FAIL )
174 return FAIL;
175 if( peg_set_reg( dev, R_PEG_EEPROM_OFS, ofs ) == FAIL )
176 return FAIL;
177 if( peg_set_reg( dev, R_PEG_EEPROM_CTL, 0x02 ) == FAIL ) /* read */
178 return FAIL;
179 while( --tries ) {
180 if( peg_get_reg( dev, R_PEG_EEPROM_CTL, data, 1 ) == FAIL )
181 return FAIL;
182 if( data[0] & 0x04 )
183 break; /* eeprom data ready */
184 }
185 if( !tries ) {
186 xprintf( "Pegasus Eeprom read failed!\n" );
187 return FAIL;
188 }
189 if( peg_get_reg( dev, R_PEG_EEPROM_DATA, data, 2 ) == FAIL )
190 return FAIL;
191 val[0] = data[0];
192 val[1] = data[1];
193
194 return( status );
195}
196
197static int peg_get_mac_addr( usbdev_t *dev, uint8_t *mac_addr )
198{
199 int i, status;
200
201 for( i = 0; i < 3; ++i ) {
202 status = peg_get_eep_word( dev, i, &mac_addr[i*2] );
203 }
204 return( status );
205}
206
207static void peg_init_phy( usbdev_t *dev )
208{
209 /* needed for earlier versions (before Rev B) of the USB-100TX adapters */
210 static uint8_t phy_magic_wr[] = { 0, 4, 0, 0x1b };
211 static uint8_t read_status[] = { 0, 0, 0, 1 };
212 uint8_t data[4];
213
214 /* reset the MAC and set up GPIOs */
215 peg_set_reg( dev, R_PEG_ETH_CTL1, 0x08 );
216 peg_get_reg( dev, R_PEG_ETH_CTL1, data, 1 );
217
218 /* do following steps to enable link activitiy LED */
219 peg_set_reg( dev, R_PEG_GPIO1, 0x26 );
220 peg_set_reg( dev, R_PEG_GPIO0, 0x24 );
221 peg_set_reg( dev, R_PEG_GPIO0, 0x26 );
222
223 /* do following set of steps to enable LINK LED */
224 memcpy( data, phy_magic_wr, 4 );
225 peg_set_regs( dev, R_PEG_PHY_ADDR, (int8_t *)data, 4); /* magic word */
226 peg_set_reg( dev, R_PEG_PHY_CTRL, (0x1b | PEG_PHY_WRITE) );
227 peg_get_reg( dev, R_PEG_PHY_CTRL, data, 1 ); /* status of write */
228 memcpy( data, read_status, 4 );
229 peg_set_regs( dev, R_PEG_PHY_ADDR, (int8_t *)data, 4); /* phy status reg */
230 peg_set_reg( dev, R_PEG_PHY_CTRL, (1 | PEG_PHY_READ) );
231 peg_get_reg( dev, R_PEG_PHY_CTRL, data, 1 ); /* status of read */
232 peg_get_reg( dev, R_PEG_PHY_DATA, data, 2 ); /* read status regs */
233}
234
235static int peg_init_device( peg_softc_t * softc )
236{
237 usb_device_descr_t dev_desc;
238 uint16_t vendor_id, product_id;
239 const int *ptr=ID_TBL;
240 usbdev_t *dev = softc->dev;
241
242 /* find out which device is connected */
243 usb_get_device_descriptor( softc->dev, &dev_desc, 0 );
244 vendor_id = (dev_desc.idVendorHigh << 8) + dev_desc.idVendorLow;
245 product_id = (dev_desc.idProductHigh << 8) + dev_desc.idProductLow;
246
247 while( *ptr != -1 ) {
248 if( (vendor_id == ptr[0]) && (product_id == ptr[1]) ) {
249 softc->dev_id = ptr[2];
250 softc->ven_code = ptr[3];
251 break;
252 }
253 ptr += 4;
254 }
255 if( *ptr == -1 ) {
256 xprintf( "Unrecognized ADMTEK USB-Ethernet device\n" );
257 return -1;
258 }
259
260 /* init the adapter */
261 if( softc->dev_id == PEGASUS_II )
262 peg_set_reg( dev, R_PEG_INT_PHY, 0x02 ); /* enable internal PHY */
263 else
264 peg_init_phy( dev );
265
266 /* Read the adapter's MAC addr */
267 peg_get_mac_addr( dev, softc->mac_addr );
268
269 /* display adapter info */
270 xprintf( "%s USB-Ethernet Adapter (%a)\n",
271 VENDOR_NAMES[softc->ven_code], softc->mac_addr);
272
273 return 0;
274}
275
276static int peg_get_dev_addr( void *ctx, hsaddr_t mac_addr )
277{
278 peg_softc_t *softc = (peg_softc_t *) ctx;
279 hs_memcpy_to_hs( mac_addr, softc->mac_addr, 6 );
280 return 0;
281}
282
283static void peg_queue_rx( peg_softc_t *softc )
284{
285 softc->rx_ur = usb_make_request(softc->dev, softc->bulk_inpipe,
286 softc->rxbuf, sizeof(softc->rxbuf),
288 usb_queue_request(softc->rx_ur);
289}
290
291static int peg_data_rx( void *ctx )
292{
293 peg_softc_t *softc = (peg_softc_t *) ctx;
294 usb_poll(softc->dev->ud_bus);
295 return( !softc->rx_ur->ur_inprogress );
296}
297
298static int peg_get_eth_frame( void *ctx, hsaddr_t buf )
299{
300 int len = 0;
301 peg_softc_t *softc = (peg_softc_t *) ctx;
302 uint8_t *rxbuf;
303
304 if( !softc->rx_ur->ur_inprogress ) {
305 rxbuf = softc->rxbuf;
306 len = softc->rx_ur->ur_xferred;
307 if (len > 0) {
308#if USBETH_DEBUG
309 xprintf( "Incoming packet :\n" );
310 hexdump( rxbuf, len, 16, len / 16 + 1 );
311#endif
312 hs_memcpy_to_hs( buf, rxbuf, len );
313 }
314 usb_free_request(softc->rx_ur);
315 peg_queue_rx( softc );
316 }
317 else
318 xprintf( "Bulk data is not available yet!\n" );
319
320 return( len );
321}
322
323static int peg_send_eth_frame( void *ctx, hsaddr_t buf, int len )
324{
325 peg_softc_t *softc = (peg_softc_t *) ctx;
326 usbreq_t *ur;
327 int txlen = len;
328 unsigned char *txbuf;
329
330 txbuf = usb_dma_alloc(len+2);
331 txbuf[0] = txlen & 0xff;
332 txbuf[1] = (txlen >> 8) & 0xff; /* 1st two bytes...little endian */
333 hs_memcpy_from_hs( &txbuf[2], buf, txlen );
334 txlen += 2;
335#if USBETH_DEBUG
336 xprintf( "Outgoing packet :\n" );
337 hexdump( txbuf, txlen, 16, txlen / 16 + 1 );
338#endif
339 ur = usb_make_request(softc->dev, softc->bulk_outpipe,
340 txbuf, txlen, UR_FLAG_OUT);
343 usb_dma_free(txbuf);
344
345 return( len );
346}
347
348
349static void peg_open_device( peg_softc_t *softc )
350{
351 usbdev_t *dev = softc->dev;
352
353 /* setup adapter's receiver with MAC address */
354 peg_set_regs( dev, R_PEG_MAC_ADDR_0, (int8_t *)softc->mac_addr, 6 );
355
356 /* enable adapter to receive and transmit packets */
357 peg_set_reg( dev, R_PEG_ETH_CTL0, 0xc1 );
358 peg_set_reg( dev, R_PEG_ETH_CTL1, 0x30 );
359
360 /* kick start the receive */
361 peg_queue_rx( softc );
362}
363
364static void peg_close_device( peg_softc_t *softc )
365{
366 usbdev_t *dev = softc->dev;
367
368 /* Disable adapter from receiving or transmitting packets */
369 peg_set_reg( dev, R_PEG_ETH_CTL1, 0 );
370}
371
372
373/* *********************************************************************
374 * CFE-USB interfaces
375 ********************************************************************* */
376
377/* *********************************************************************
378 * peg_attach(dev,drv)
379 *
380 * This routine is called when the bus scan stuff finds a usb-ethernet
381 * device. We finish up the initialization by configuring the
382 * device and allocating our softc here.
383 *
384 * Input parameters:
385 * dev - usb device, in the "addressed" state.
386 * drv - the driver table entry that matched
387 *
388 * Return value:
389 * 0
390 ********************************************************************* */
391
392const cfe_driver_t usbpegdrv; /* forward declaration */
393
394static int peg_attach(usbdev_t *dev, usb_driver_t *drv)
395{
396 usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
397 usb_endpoint_descr_t *epdscr;
398 usb_endpoint_descr_t *indscr = NULL;
399 usb_endpoint_descr_t *outdscr = NULL;
400 usb_interface_descr_t *ifdscr;
401 peg_softc_t *softc;
402 int idx;
403
404 dev->ud_drv = drv;
405
406 softc = (peg_softc_t *) KMALLOC( sizeof(peg_softc_t), 0 );
407 if( softc == NULL ) {
408 xprintf( "Failed to allocate softc memory.\n" );
409 return -1;
410 }
411 memset( softc, 0, sizeof(peg_softc_t) );
412 dev->ud_private = softc;
413 softc->dev = dev;
414
416 if (ifdscr == NULL) {
417 xprintf("USBETH: ERROR...no interace descriptor\n");
418 return -1;
419 }
420
421 for (idx = 0; idx < 2; idx++) {
424 outdscr = epdscr;
425 else
426 indscr = epdscr;
427 }
428
429 if (!indscr || !outdscr) {
430 /*
431 * Could not get descriptors, something is very wrong.
432 * Leave device addressed but not configured.
433 */
434 xprintf("USBETH: ERROR...no endpoint descriptors\n");
435 return -1;
436 }
437
438 /* Choose the standard configuration. */
440
441 /* Quit if not able to initialize the device */
442 if (peg_init_device(softc) < 0)
443 return -1;
444
445 /* Open the pipes. */
446 softc->bulk_inpipe = usb_open_pipe(dev,indscr);
447 softc->bulk_outpipe = usb_open_pipe(dev,outdscr);
448
449 /* Register the device */
450 usbeth_register(&usbeth_peg,softc);
451
452 /* Open the device */
453 peg_open_device( softc );
454
455 return 0;
456}
457
458/* *********************************************************************
459 * peg_detach(dev)
460 *
461 * This routine is called when the bus scanner notices that
462 * this device has been removed from the system. We should
463 * do any cleanup that is required. The pending requests
464 * will be cancelled automagically.
465 *
466 * Input parameters:
467 * dev - usb device
468 *
469 * Return value:
470 * 0
471 ********************************************************************* */
472
473static int peg_detach(usbdev_t *dev)
474{
475 peg_softc_t *softc = (peg_softc_t *) dev->ud_private;
476
477 if (softc != NULL) {
478 usbeth_unregister( softc );
479 peg_close_device ( softc );
480 dev->ud_private = NULL;
481 softc->dev = NULL;
482 KFREE(softc);
483 }
484
485 return 0;
486}
487
488/* CFE USB device interface structure */
490{
491 "Ethernet Device",
492 peg_attach,
493 peg_detach
494};
495
496
void * hsaddr_t
Definition: cfe.h:11
#define NULL
Definition: def.h:47
const cfe_driver_t usbpegdrv
@ PEGASUS_II
@ PEGASUS
#define hexdump(src, srclen, rowlen, rows)
#define usb_dma_free(p)
#define usb_dma_alloc(n)
usb_driver_t usbpeg_driver
#define FAIL
@ LINKSYS
@ LINKSYS_100M
@ LINKSYS_10
@ LINKSYS_100
@ _3_COM
@ VEN_NONE
struct peg_softc_s peg_softc_t
u32 status
Definition: ehci_defs.h:15
static uint32_t val
Definition: io.h:17
u32 ptr
Definition: iso9660.c:536
#define KMALLOC(size, align)
Definition: lib_malloc.h:92
#define KFREE(ptr)
Definition: lib_malloc.h:93
s8 int8_t
Definition: libfdt_env.h:14
s16 int16_t
Definition: libfdt_env.h:15
u16 uint16_t
Definition: libfdt_env.h:10
u8 uint8_t
Definition: libfdt_env.h:9
usbreq_t * rx_ur
uint8_t mac_addr[6]
usbdev_t * dev
uint8_t rxbuf[1600]
uint8_t bConfigurationValue
Definition: usbchap9.h:216
uint8_t idVendorLow
Definition: usbchap9.h:184
uint8_t idProductLow
Definition: usbchap9.h:185
uint8_t idProductHigh
Definition: usbchap9.h:185
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_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_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 R_PEG_PHY_DATA
Definition: usbeth.h:95
#define R_PEG_GPIO0
Definition: usbeth.h:98
#define R_PEG_PHY_CTRL
Definition: usbeth.h:96
#define R_PEG_GPIO1
Definition: usbeth.h:99
#define R_PEG_EEPROM_DATA
Definition: usbeth.h:92
#define R_PEG_ETH_CTL0
Definition: usbeth.h:86
#define PEG_SET_REG
Definition: usbeth.h:83
#define R_PEG_PHY_ADDR
Definition: usbeth.h:94
#define R_PEG_INT_PHY
Definition: usbeth.h:97
#define PEG_PHY_READ
Definition: usbeth.h:103
#define R_PEG_MAC_ADDR_0
Definition: usbeth.h:90
#define PEG_GET_REG
Definition: usbeth.h:84
#define PEG_PHY_WRITE
Definition: usbeth.h:102
#define R_PEG_ETH_CTL1
Definition: usbeth.h:87
#define R_PEG_EEPROM_CTL
Definition: usbeth.h:93
#define R_PEG_EEPROM_OFS
Definition: usbeth.h:91
int xprintf(char *str)
Definition: usbhack.c:404
union @15 data