diff --git a/ehci-mem.c b/ehci-mem.c deleted file mode 100644 index c7e4764..0000000 --- a/ehci-mem.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Original Copyright (c) 2001 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci.c */ - - -static inline void ehci_qtd_init(struct ehci_qtd *qtd - ) -{ - dma_addr_t dma = ehci_virt_to_dma(qtd); - memset (qtd, 0, sizeof *qtd); - qtd->qtd_dma = dma; - qtd->hw_token = (QTD_STS_HALT); - qtd->hw_next = EHCI_LIST_END(); - qtd->hw_alt_next = EHCI_LIST_END(); -} -static inline struct ehci_qtd * ehci_qtd_alloc(void) -{ - struct ehci_qtd *qtd ; - //debug_printf("ehci_qtd used=%x\n",ehci->qtd_used); - BUG_ON(ehci->qtd_used>=EHCI_MAX_QTD); - qtd = ehci->qtds[ehci->qtd_used++]; - ehci_qtd_init(qtd); - return qtd; -} - -int ehci_mem_init (void) -{ - int i; - u32 ptr = 0x1800000 - DEFAULT_I_TDPS * sizeof(__le32); - - ehci->periodic = (u32*)ptr; - ehci->periodic_dma = ehci_virt_to_dma(ehci->periodic); - - for (i = 0; i < DEFAULT_I_TDPS; i++) - ehci->periodic[i] = EHCI_LIST_END(); - - ehci_writel( ehci->periodic_dma, &ehci->regs->frame_list ); - - for(i=0;iqtds[i] = (struct ehci_qtd*)(ptr); - } - - ehci->qtd_used = 0; - - ptr -= sizeof(struct ehci_qh); - ehci->asyncqh = (struct ehci_qh*)ptr; - - ehci->asyncqh->ehci = ehci; - ehci->asyncqh->qh_dma = ehci_virt_to_dma(ehci->asyncqh); - ehci->asyncqh->qtd_head = NULL; - - ptr -= sizeof(struct ehci_qh); - ehci->async = (struct ehci_qh*)ptr; - - ehci->async->ehci = ehci; - ehci->async->qh_dma = ehci_virt_to_dma(ehci->async); - ehci->async->qtd_head = NULL; - - return 0; -} diff --git a/ehci.c b/ehci.c deleted file mode 100644 index 1bde0a4..0000000 --- a/ehci.c +++ /dev/null @@ -1,830 +0,0 @@ -/* simplest usb-ehci driver which features: - - control and bulk transfers only - only one transfer pending - driver is synchronous (waiting for the end of the transfer) - endianess independant - no uncached memory allocation needed - - this driver is originally based on the GPL linux ehci-hcd driver - - * Original Copyright (c) 2001 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* magic numbers that can affect system performance */ - -u32 IsInit = 0; - -#undef DEBUG - -#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ -#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ -#define EHCI_TUNE_RL_TT 0 -#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ -#define EHCI_TUNE_MULT_TT 1 -#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ -extern int verbose; -static void -dbg_qtd (const char *label, struct ehci_qtd *qtd) -{ - //ehci_dbg( "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, - // hc32_to_cpup( &qtd->hw_next), - // hc32_to_cpup( &qtd->hw_alt_next), - // hc32_to_cpup( &qtd->hw_token), - // hc32_to_cpup( &qtd->hw_buf [0])); - //if (qtd->hw_buf [1]) - // ehci_dbg( " p1=%08x p2=%08x p3=%08x p4=%08x\n", - // hc32_to_cpup( &qtd->hw_buf[1]), - // hc32_to_cpup( &qtd->hw_buf[2]), - // hc32_to_cpup( &qtd->hw_buf[3]), - // hc32_to_cpup( &qtd->hw_buf[4])); -} - -static void -dbg_qh (const char *label, struct ehci_qh *qh) -{ - //ehci_dbg ( "%s qh %p n%08x info %x %x qtd %x\n", label, - // qh, - // hc32_to_cpu(qh->hw_next), - // hc32_to_cpu(qh->hw_info1), - // hc32_to_cpu(qh->hw_info2), - // hc32_to_cpu(qh->hw_current)); - //dbg_qtd ("overlay", (struct ehci_qtd *) &qh->hw_qtd_next); -} - -static void -dbg_command (void) -{ -#ifdef DEBUG - u32 command=ehci_readl( &ehci->regs->command); - u32 async=ehci_readl( &ehci->regs->async_next); - - ehci_dbg ("async_next: %08x\n",async); - ehci_dbg ( - "command %06x %s=%d ithresh=%d%s%s%s%s %s %s\n", - command, - (command & CMD_PARK) ? "park" : "(park)", - CMD_PARK_CNT (command), - (command >> 16) & 0x3f, - (command & CMD_LRESET) ? " LReset" : "", - (command & CMD_IAAD) ? " IAAD" : "", - (command & CMD_ASE) ? " Async" : "", - (command & CMD_PSE) ? " Periodic" : "", - (command & CMD_RESET) ? " Reset" : "", - (command & CMD_RUN) ? "RUN" : "HALT" - ); -#endif -} -static void -dbg_status (void) -{ -#ifdef DEBUG - u32 status=ehci_readl( &ehci->regs->status); - ehci_dbg ( - "status %04x%s%s%s%s%s%s%s%s%s%s\n", - status, - (status & STS_ASS) ? " Async" : "", - (status & STS_PSS) ? " Periodic" : "", - (status & STS_RECL) ? " Recl" : "", - (status & STS_HALT) ? " Halt" : "", - (status & STS_IAA) ? " IAA" : "", - (status & STS_FATAL) ? " FATAL" : "", - (status & STS_FLR) ? " FLR" : "", - (status & STS_PCD) ? " PCD" : "", - (status & STS_ERR) ? " ERR" : "", - (status & STS_INT) ? " INT" : "" - ); -#endif -} - -void debug_qtds(void) -{ - //struct ehci_qh *qh = ehci->async; - //struct ehci_qtd *qtd; - //dbg_qh ("qh",qh); - //dbg_command (); - //dbg_status (); - //for(qtd = qh->qtd_head; qtd; qtd = qtd->next) - //{ - // ehci_dma_unmap_bidir(qtd->qtd_dma,sizeof(struct ehci_qtd)); - // dbg_qtd("qtd",qtd); - // ehci_dma_map_bidir(qtd,sizeof(struct ehci_qtd)); - //} - -} -void dump_qh(struct ehci_qh *qh) -{ - //struct ehci_qtd *qtd; - //dbg_command (); - //dbg_status (); - //ehci_dma_unmap_bidir(qh->qh_dma,sizeof(struct ehci_qh)); - //dbg_qh("qh",qh); - //print_hex_dump_bytes("qh:",DUMP_PREFIX_OFFSET,(void*)qh,12*4); - //for(qtd = qh->qtd_head; qtd; qtd = qtd->next){ - // u32 *buf; - // ehci_dma_unmap_bidir(qtd->qtd_dma,sizeof(struct ehci_qtd)); - // dbg_qtd("qtd",qtd); - // print_hex_dump_bytes("qtd:",DUMP_PREFIX_OFFSET,(void*)qtd,8*4); - // buf = (u32*)hc32_to_cpu(qtd->hw_buf[0]); - // if(buf) - // print_hex_dump_bytes("qtd buf:",DUMP_PREFIX_OFFSET,(void*)(buf),8*4); - - //} -} - -/*-------------------------------------------------------------------------*/ - -/* - * handshake - spin reading hc until handshake completes or fails - * @ptr: address of hc register to be read - * @mask: bits to look at in result of read - * @done: value of those bits when handshake succeeds - * @usec: timeout in microseconds - * - * Returns negative errno, or zero on success - * - * Success happens when the "mask" bits have the specified value (hardware - * handshake done). There are two failure modes: "usec" have passed (major - * hardware flakeout), or the register reads as all-ones (hardware removed). - * - * That last failure should_only happen in cases like physical cardbus eject - * before driver shutdown. But it also seems to be caused by bugs in cardbus - * bridge shutdown: shutting down the bridge before the devices using it. - */ -static int handshake (void __iomem *ptr, - u32 mask, u32 done, int usec) -{ - u32 result; - do { - result = ehci_readl( ptr); - if (result == ~(u32)0) /* card removed */ - return -ENODEV; - result &= mask; - if (result == done) - return 0; - udelay(1); - usec--; - } while (usec > 0); - - ehci_dbg("EHCI:handshake timeout!!\n"); - dump_qh(ehci->async); - dump_qh(ehci->asyncqh); - //BUG(); - return -ETIMEDOUT; -} - -#include "ehci-mem.c" -/* one-time init, only for memory state */ -static int ehci_init(void) -{ - int retval; - if( (retval = ehci_mem_init()) < 0 ) - return retval; - /* - * dedicate a qh for the async ring head, since we couldn't unlink - * a 'real' qh without stopping the async schedule [4.8]. use it - * as the 'reclamation list head' too. - * its dummy is used in hw_alt_next of many tds, to prevent the qh - * from automatically advancing to the next td after short reads. - */ - ehci->async->hw_next = QH_NEXT( ehci->async->qh_dma); - ehci->async->hw_info1 = cpu_to_hc32( QH_HEAD); - ehci->async->hw_token = cpu_to_hc32( QTD_STS_HALT); - ehci->async->hw_qtd_next = EHCI_LIST_END(); - ehci->async->hw_alt_next = EHCI_LIST_END();//QTD_NEXT( ehci->async->dummy->qtd_dma); - - if( ehci->ctrl_buffer != NULL ) - USB_Free( ehci->ctrl_buffer ); - - ehci->ctrl_buffer = USB_Alloc(sizeof(usbctrlrequest)); - - ehci->command = 0; - ehci_writel( 0x00800002, &ehci->regs->command); - ehci_writel( ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel( ehci->async->qh_dma, &ehci->regs->async_next); - ehci_writel( 0x00010009, &ehci->regs->command); - ehci_writel( 1, &ehci->regs->configured_flag); - ehci_writel( 0x00010029, &ehci->regs->command); - - return 0; -} - -/* fill a qtd, returning how much of the buffer we were able to queue up */ -static int qtd_fill( struct ehci_qtd *qtd, dma_addr_t buf, size_t len, int token, int maxpacket) -{ - int i, count; - u64 addr = buf; - //ehci_dbg("fill qtd with dma %X len %X\n",buf,len); - /* one buffer entry per 4K ... first might be short or unaligned */ - qtd->hw_buf[0] = cpu_to_hc32( (u32)addr); - qtd->hw_buf_hi[0] = 0; - count = 0x1000 - (buf & 0x0fff); /* rest of that page */ - if (likely (len < count)) /* ... iff needed */ - count = len; - else { - buf += 0x1000; - buf &= ~0x0fff; - - /* per-qtd limit: from 16K to 20K (best alignment) */ - for (i = 1; count < len && i < 5; i++) { - addr = buf; - qtd->hw_buf[i] = cpu_to_hc32( (u32)addr); - qtd->hw_buf_hi[i] = cpu_to_hc32( - (u32)(addr >> 32)); - buf += 0x1000; - if ((count + 0x1000) < len) - count += 0x1000; - else - count = len; - } - - /* short packets may only terminate transfers */ - if (count != len) - count -= (count % maxpacket); - } - qtd->hw_token = cpu_to_hc32( (count << 16) | token); - qtd->length = count; - - return count; -} - -// high bandwidth multiplier, as encoded in highspeed endpoint descriptors -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -// ... and packet size, for any kind of endpoint descriptor -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) - -/* - * reverse of qh_urb_transaction: free a list of TDs. - * also count the actual transfer length. - * - */ -static void qh_end_transfer (void) -{ - struct ehci_qtd *qtd; - struct ehci_qh *qh = ehci->asyncqh; - u32 token; - int error = 0; - for(qtd = qh->qtd_head; qtd; qtd = qtd->next) - { - token = hc32_to_cpu( qtd->hw_token); - if (likely (QTD_PID (token) != 2)) - qtd->urb->actual_length += qtd->length - QTD_LENGTH (token); - - if (!(qtd->length ==0 && ((token & 0xff)==QTD_STS_HALT)) && (token & QTD_STS_HALT)) - { - ehci_dbg("EHCI:qtd error!:"); - if (token & QTD_STS_BABBLE) - { - /* FIXME "must" disable babbling device's port too */ - ehci_dbg(" BABBLE"); - } - if (token & QTD_STS_MMF) - { - /* fs/ls interrupt xfer missed the complete-split */ - ehci_dbg(" missed micro frame"); - } - if (token & QTD_STS_DBE) - { - ehci_dbg(" databuffer error"); - } - if (token & QTD_STS_XACT) - { - ehci_dbg(" wrong ack"); - } - if (QTD_CERR (token)==0) - ehci_dbg(" toomany errors"); - - ehci_dbg("\n"); - error = -1; - } - } - if(error) - { - dump_qh(ehci->asyncqh); - qtd->urb->actual_length = error; - } - ehci->qtd_used = 0; -} - -/* - * create a list of filled qtds for this URB; won't link into qh. - */ -struct ehci_qtd *qh_urb_transaction ( - struct ehci_urb *urb -) { - struct ehci_qtd *qtd, *qtd_prev; - struct ehci_qtd *head; - dma_addr_t buf; - int len, maxpacket; - int is_input; - u32 token; - - /* - * URBs map to sequences of QTDs: one logical transaction - */ - head = qtd = ehci_qtd_alloc (); - qtd->urb = urb; - - urb->actual_length = 0; - token = QTD_STS_ACTIVE; - token |= (EHCI_TUNE_CERR << 10); - /* for split transactions, SplitXState initialized to zero */ - - len = urb->transfer_buffer_length; - is_input = urb->input; - if (urb->ep==0) {/* is control */ - /* SETUP pid */ - qtd_fill( qtd, urb->setup_dma, sizeof (usbctrlrequest), token | (2 /* "setup" */ << 8), 8); - - /* ... and always at least one more pid */ - token ^= QTD_TOGGLE; - qtd_prev = qtd; - qtd = ehci_qtd_alloc (); - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT( qtd->qtd_dma); - qtd_prev->next = qtd; - - /* for zero length DATA stages, STATUS is always IN */ - if (len == 0) - token |= (1 /* "in" */ << 8); - } - - /* - * data transfer stage: buffer setup - */ - buf = urb->transfer_dma; - - if (is_input) - token |= (1 /* "in" */ << 8); - /* else it's already initted to "out" pid (0 << 8) */ - - maxpacket = max_packet(urb->maxpacket); - - /* - * buffer gets wrapped in one or more qtds; - * last one may be "short" (including zero len) - * and may serve as a control status ack - */ - for (;;) { - int this_qtd_len; - - this_qtd_len = qtd_fill( qtd, buf, len, token, maxpacket); - len -= this_qtd_len; - buf += this_qtd_len; - - /* - * short reads advance to a "magic" dummy instead of the next - * qtd ... that forces the queue to stop, for manual cleanup. - * (this will usually be overridden later.) - */ - if (is_input) - qtd->hw_alt_next = ehci->asyncqh->hw_alt_next; - - /* qh makes control packets use qtd toggle; maybe switch it */ - if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) - token ^= QTD_TOGGLE; - - if (likely (len <= 0)) - break; - - qtd_prev = qtd; - qtd = ehci_qtd_alloc (); - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT( qtd->qtd_dma); - qtd_prev->next = qtd; - } - - qtd->hw_alt_next = EHCI_LIST_END(); - - /* - * control requests may need a terminating data "status" ack; - * bulk ones may need a terminating short packet (zero length). - */ - if (likely (urb->transfer_buffer_length != 0)) { - int one_more = 0; - - if (urb->ep==0) { - one_more = 1; - token ^= 0x0100; /* "in" <--> "out" */ - token |= QTD_TOGGLE; /* force DATA1 */ - } else if(!(urb->transfer_buffer_length % maxpacket)) { - //one_more = 1; - } - if (one_more) { - qtd_prev = qtd; - qtd = ehci_qtd_alloc (); - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT( qtd->qtd_dma); - qtd_prev->next = qtd; - - /* never any data in such packets */ - qtd_fill( qtd, 0, 0, token, 0); - } - } - - /* by default, enable interrupt on urb completion */ - qtd->hw_token |= cpu_to_hc32( QTD_IOC); - return head; -} -int ehci_do_urb ( struct ehci_device *dev, struct ehci_urb *urb) -{ - struct ehci_qh *qh; - struct ehci_qtd *qtd; - u32 info1 = 0, info2 = 0; - int is_input; - int maxp = 0; - int retval; - - //ehci_dbg ("do urb %X %X ep %X\n",urb->setup_buffer,urb->transfer_buffer,urb->ep); - if(urb->ep==0) //control message - urb->setup_dma = ehci_dma_map_to(urb->setup_buffer,sizeof (usbctrlrequest)); - - if( urb->transfer_buffer_length ) - { - if(urb->input) - urb->transfer_dma = ehci_dma_map_to( urb->transfer_buffer, urb->transfer_buffer_length ); - else - urb->transfer_dma = ehci_dma_map_from( urb->transfer_buffer, urb->transfer_buffer_length ); - } - - qh = ehci->asyncqh; - memset(qh,0,12*4); - qtd = qh_urb_transaction( urb ); - qh->qtd_head = qtd; - - info1 |= ((urb->ep)&0xf)<<8; - info1 |= dev->id; - is_input = urb->input; - maxp = urb->maxpacket; - - info1 |= (2 << 12); /* EPS "high" */ - if(urb->ep==0)// control - { - info1 |= (EHCI_TUNE_RL_HS << 28); - info1 |= 64 << 16; /* usb2 fixed maxpacket */ - info1 |= 1 << 14; /* toggle from qtd */ - info2 |= (EHCI_TUNE_MULT_HS << 30); - } else {//bulk - - info1 |= (EHCI_TUNE_RL_HS << 28); - /* The USB spec says that high speed bulk endpoints - * always use 512 byte maxpacket. But some device - * vendors decided to ignore that, and MSFT is happy - * to help them do so. So now people expect to use - * such nonconformant devices with Linux too; sigh. - */ - info1 |= max_packet(maxp) << 16; - info2 |= (EHCI_TUNE_MULT_HS << 30); - } - - //ehci_dbg("HW info: %08X\n",info1); - qh->hw_info1 = cpu_to_hc32( info1); - qh->hw_info2 = cpu_to_hc32( info2); - - qh->hw_next = QH_NEXT( qh->qh_dma ); - qh->hw_qtd_next = QTD_NEXT( qtd->qtd_dma ); - qh->hw_alt_next = EHCI_LIST_END(); - - if( urb->ep != 0 ) - { - if( get_toggle( dev, urb->ep ) ) - qh->hw_token |= cpu_to_hc32(QTD_TOGGLE); - else - qh->hw_token &= ~cpu_to_hc32(QTD_TOGGLE); - - //ehci_dbg("toggle for ep %x: %d %x\n", urb->ep, get_toggle(dev,urb->ep), qh->hw_token ); - } - - qh->hw_token &= cpu_to_hc32( QTD_TOGGLE | QTD_STS_PING); - - qh->hw_next = QH_NEXT(ehci->async->qh_dma); - - - ehci_dma_map_bidir(qh,sizeof(struct ehci_qh)); - for(qtd = qh->qtd_head; qtd; qtd = qtd->next) - ehci_dma_map_bidir(qtd,sizeof(struct ehci_qtd)); - - // start (link qh) - ehci->async->hw_next = QH_NEXT(qh->qh_dma); - ehci_dma_map_bidir(ehci->async,sizeof(struct ehci_qh)); - - retval = handshake(&ehci->regs->status,STS_INT,STS_INT,1000*1000); - - //print_hex_dump_bytes ("qh mem",0,(void*)qh,17*4); - //retval = poll_transfer_end(1000*1000); - ehci_dma_unmap_bidir(ehci->async->qh_dma,sizeof(struct ehci_qh)); - ehci_dma_unmap_bidir(qh->qh_dma,sizeof(struct ehci_qh)); - - for(qtd = qh->qtd_head; qtd; qtd = qtd->next) - ehci_dma_unmap_bidir(qtd->qtd_dma,sizeof(struct ehci_qtd)); - - // stop (unlink qh) - ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma); - ehci_dma_map_bidir(ehci->async,sizeof(struct ehci_qh)); - ehci_dma_unmap_bidir(ehci->async->qh_dma,sizeof(struct ehci_qh)); - - // ack - ehci_writel( STS_RECL|STS_IAA|STS_INT, &ehci->regs->status); - - if(urb->ep!=0) - { - set_toggle(dev,urb->ep,(qh->hw_token & cpu_to_hc32(QTD_TOGGLE))?1:0); - //ehci_dbg("toggle for ep %x: %d %d %x %X\n",urb->ep,get_toggle(dev,urb->ep),(qh->hw_token & cpu_to_hc32(QTD_TOGGLE)),qh->hw_token,dev->toggles); - } - - if( retval >= 0 ) - // wait hc really stopped - retval = handshake(&ehci->regs->async_next,~0,ehci->async->qh_dma,1*1000); - //release memory, and actualise urb->actual_length - qh_end_transfer(); - - if(urb->transfer_buffer_length) - { - if(urb->input) - ehci_dma_unmap_to(urb->transfer_dma,urb->transfer_buffer_length); - else - ehci_dma_unmap_from(urb->transfer_dma,urb->transfer_buffer_length); - } - - if( urb->ep == 0 ) //control message - ehci_dma_unmap_to(urb->setup_dma,sizeof (usbctrlrequest)); - - if(retval==0) - { - return urb->actual_length; - } - ehci_dbg ( "EHCI:unsuccessfull urb %d!!\n", retval); - return retval; -} - -s32 ehci_control_message(struct ehci_device *dev,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *buf) -{ - struct ehci_urb urb; - int ret; - usbctrlrequest *req = (void*)0x17C0; - - if( verbose ) - ehci_dbg("control msg: rt%02X r%02X v%04X i%04X s%04x %p\n", bmRequestType, bmRequest, wValue, wIndex, wLength, buf ); - - u32 *_req = (u32*)req; - - _req[0] = (bmRequestType<<24) | (bmRequest<<16) | swab16(wValue); - _req[1] = (swab16(wIndex) << 16) | swab16(wLength); - - urb.setup_buffer = req; - urb.ep = 0; - urb.input = (bmRequestType&USB_CTRLTYPE_DIR_DEVICE2HOST)!=0; - urb.maxpacket = 64; - urb.transfer_buffer_length = wLength; - - if( urb.transfer_buffer_length ) - { - if( ((u32)buf >> 28 ) == 0xF ) - { - urb.transfer_buffer = USB_Alloc( wLength ); - - //dbgprintf("memcpy(%p,%p,%u)\n", urb.transfer_buffer, buf, wLength ); - memcpy( urb.transfer_buffer, buf, wLength ); - - ret = ehci_do_urb( dev, &urb ); - - memcpy( buf, urb.transfer_buffer, wLength ); - USB_Free( urb.transfer_buffer ); - - } else { - urb.transfer_buffer = buf; - ret = ehci_do_urb( dev, &urb ); - } - - //hexdump( buf, wLength > 0x20 ? 0x20 : wLength ); - - } else { - - urb.transfer_buffer = NULL; - ret = ehci_do_urb( dev, &urb ); - } - - return ret; -} -s32 ehci_bulk_message(struct ehci_device *dev,u8 bEndpoint,u16 wLength,void *rpData) -{ - struct ehci_urb urb; - s32 ret; - urb.setup_buffer = NULL; - urb.ep = bEndpoint; - urb.input = (bEndpoint&0x80)!=0; - urb.maxpacket = 512; - urb.transfer_buffer_length = wLength; - urb.transfer_buffer = rpData; - - if (verbose) - ehci_dbg ( "bulk msg: ep:%02X size:%02X addr:%04X\n", bEndpoint, wLength, urb.transfer_buffer ); - -// hexdump( urb.transfer_buffer, urb.transfer_buffer_length ); - if( ((u32)rpData >> 28) == 0xF ) - { - memcpy( (void*)0xFE0, rpData, wLength ); - - urb.transfer_buffer = (u8*)0xFE0; - - ret = ehci_do_urb( dev, &urb ); - - memcpy( rpData, (void*)0xFE0, wLength ); - - } else { - ret = ehci_do_urb( dev, &urb ); - } - -// hexdump( urb.transfer_buffer, urb.transfer_buffer_length ); - - if (verbose) - ehci_dbg ( "==>%d\n", ret); - - return ret; -} - - -int ehci_reset_port(int port) -{ - u32 __iomem *status_reg = &ehci->regs->port_status[port]; - struct ehci_device *dev = &ehci->devices[port]; - u32 status = ehci_readl(status_reg); - int retval = 0; - - dev->id = 0; - - if ((PORT_OWNER&status) || !(PORT_CONNECT&status)) - { - int retries = 10; - while (!(PORT_CONNECT&status) && retries > 0) - { - msleep(1000); // sleep 1 second - status = ehci_readl(status_reg); - ehci_dbg ( "EHCI:port %d status at retry %d %X \n", port,retries,status); - retries--; - } - - if( retries <= 0 ) - { - ehci_writel( PORT_OWNER, status_reg); - ehci_dbg ( "EHCI:port %d had no usb2 device connected at startup %X \n", port,ehci_readl(status_reg) ); - return -ENODEV;// no USB2 device connected - } - } - - ehci_dbg ( "EHCI:port %d has usb2 device connected! reset it...\n", port); - ehci_writel( 0x1803,status_reg); - - while ((ehci_readl(status_reg) & 0x1801) != 0x1801) - { - ehci_dbg ( "EHCI:Waiting for port %d to settle...(%04x)\n", port, ehci_readl(status_reg)); - ehci_writel( 0x1803,status_reg); - msleep(500); - } - - ehci_writel( 0x1903,status_reg); - //ehci_writel( PORT_OWNER|PORT_POWER|PORT_RESET,status_reg); - msleep(50);// wait 50ms for the reset sequence - ehci_writel( 0x1001,status_reg); - retval = handshake( status_reg, PORT_RESET, 0, 2000); - - if (retval != 0) - { - ehci_dbg ( "EHCI:port %d reset error %d\n", port, retval); - return retval; - } - ehci_dbg ( "EHCI:port %d reseted status:%04x...\n", port,ehci_readl(status_reg)); - msleep(50); - // now the device has the default device id - retval = ehci_control_message( dev, USB_CTRLTYPE_DIR_DEVICE2HOST, USB_REQ_GETDESCRIPTOR, USB_DT_DEVICE<<8, 0, sizeof(dev->desc), &dev->desc ); - - if (retval < 0) - { - ehci_dbg("EHCI:unable to get device desc...\n"); - return retval; - } - - retval = ehci_control_message( dev, USB_CTRLTYPE_DIR_HOST2DEVICE, USB_REQ_SETADDRESS,port+1,0,0,0); - if (retval < 0) - { - ehci_dbg("EHCI:unable to set device addr...\n"); - return retval; - } - dev->toggles = 0; - - dev->id = port+1; - ehci_dbg ( "EHCI:device %d: %X %X...\n", dev->id,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct)); - return retval; -} -int ehci_reset_device(struct ehci_device *dev) -{ - return ehci_reset_port(dev->port); -} -#include "usbstorage.h" -int ehci_discover(void) -{ - int i; - int ret = 0 ; - // precondition: the ehci should be halted - for(i = 0;inum_port; i++) - { - struct ehci_device *dev = &ehci->devices[i]; - dev->port = i; - ret = ehci_reset_port(i); - - if( ret != -ENODEV ) - break; - } - return ret; -} -/* wii: quickly release non ehci or not connected ports, - as we can't kick OHCI drivers laters if we discover a device for them. -*/ -int ehci_release_ports(void) -{ - int i; - u32 __iomem *status_reg = &ehci->regs->port_status[2]; - while(ehci_readl(&ehci->regs->port_status[2]) == 0x1000);// wait port 2 to init - msleep(1);// wait another msec.. - for(i = 0;inum_port; i++){ - status_reg = &ehci->regs->port_status[i]; - u32 status = ehci_readl(status_reg); - if (i==2 || !(PORT_CONNECT&status) || PORT_USB11(status)) - ehci_writel( PORT_OWNER,status_reg); // release port. - } - return 0; -} - -int ehci_open_device(int vid,int pid,int fd) -{ - int i; - for(i=0;inum_port;i++) - { - ehci_dbg("try device: %d\n",i); - if(ehci->devices[i].fd == 0 && - le16_to_cpu(ehci->devices[i].desc.idVendor) == vid && - le16_to_cpu(ehci->devices[i].desc.idProduct) == pid) - { - ehci_dbg("found device: %x %x\n",vid,pid); - ehci->devices[i].fd = fd; - return fd; - } - } - return -6; -} -int ehci_close_device(struct ehci_device *dev) -{ - if (dev) - dev->fd = 0; - return 0; -} - void * ehci_fd_to_dev(int fd) -{ - int i; - for(i=0;inum_port;i++) - { - struct ehci_device *dev = &ehci->devices[i]; - ehci_dbg ( "EHCI:device %d:fd:%d %X %X...\n", dev->id,dev->fd,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct)); - if(dev->fd == fd){ - return dev; - } - } - ehci_dbg("unkown fd! %d\n",fd); - return 0; -} -#define g_ehci #error -int ehci_get_device_list(u8 maxdev,u8 b0,u8*num,u16*buf) -{ - int i,j = 0; - for(i=0;inum_port && jdevices[i]; - if(dev->id != 0){ - ehci_dbg ( "EHCI:device %d: %X %X...\n", dev->id,le16_to_cpu(dev->desc.idVendor),le16_to_cpu(dev->desc.idProduct)); - buf[j*4] = 0; - buf[j*4+1] = 0; - buf[j*4+2] = le16_to_cpu(dev->desc.idVendor); - buf[j*4+3] = le16_to_cpu(dev->desc.idProduct); - j++; - } - } - ehci_dbg("EHCI:found %d devices\n",j); - *num = j; - return 0; -} -#include "usb.c" -#include "usbstorage.c" diff --git a/ehci.h b/ehci.h deleted file mode 100644 index c3ab9ed..0000000 --- a/ehci.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2009 Kwiirk - * Original Copyright (c) 2001-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "ehci_types.h" - -#ifndef __LINUX_EHCI_HCD_H -#define __LINUX_EHCI_HCD_H -/* definitions used for the EHCI driver */ - -/* - * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to - * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on - * the host controller implementation. - * - * To facilitate the strongest possible byte-order checking from "sparse" - * and so on, we use __leXX unless that's not practical. - */ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC -typedef __u32 __bitwise __hc32; -typedef __u16 __bitwise __hc16; -#else -#define __hc32 __le32 -#define __hc16 __le16 -#endif - - -#define EHCI_MAX_ROOT_PORTS 4 /* see HCS_N_PORTS */ -#define EHCI_MAX_QTD 8 -#include "usb.h" - -struct ehci_device{ - usb_devdesc desc; - int id; - int port; - int fd; - u32 toggles; -}; -#define ep_bit(ep) (((ep)&0xf)+(((ep)>>7)?16:0)) -#define get_toggle(dev,ep) (((dev)->toggles>>ep_bit(ep))&1) -#define set_toggle(dev,ep,v) (dev)->toggles = ((dev)->toggles &(~(1<>16) & 0x7fff) -#define QTD_IOC (1 << 15) /* interrupt on complete */ -#define QTD_CERR(tok) (((tok)>>10) & 0x3) -#define QTD_PID(tok) (((tok)>>8) & 0x3) -#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define QTD_STS_HALT (1 << 6) /* halted on error */ -#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ -#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ -#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define QTD_STS_STS (1 << 1) /* split transaction state */ -#define QTD_STS_PING (1 << 0) /* issue PING? */ - -#define ACTIVE_BIT(ehci) cpu_to_hc32( QTD_STS_ACTIVE) -#define HALT_BIT(ehci) cpu_to_hc32( QTD_STS_HALT) -#define STATUS_BIT(ehci) cpu_to_hc32( QTD_STS_STS) - - __hc32 hw_buf [5]; /* see EHCI 3.5.4 */ - __hc32 hw_buf_hi [5]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t qtd_dma; /* qtd address */ - struct ehci_qtd *next; /* sw qtd list */ - struct ehci_urb *urb; /* qtd's urb */ - size_t length; /* length of buffer */ -} __attribute__ ((aligned (32))); - -/* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK(ehci) cpu_to_hc32 ( ~0x1f) - -#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) - -/*-------------------------------------------------------------------------*/ - -/* type tag from {qh,itd,sitd,fstn}->hw_next */ -#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_hc32( 3 << 1)) - -/* - * Now the following defines are not converted using the - * __constant_cpu_to_le32() macro anymore, since we have to support - * "dynamic" switching between be and le support, so that the driver - * can be used on one system with SoC EHCI controller using big-endian - * descriptors as well as a normal little-endian PCI EHCI controller. - */ -/* values for that type tag */ -#define Q_TYPE_ITD (0 << 1) -#define Q_TYPE_QH (1 << 1) -#define Q_TYPE_SITD (2 << 1) -#define Q_TYPE_FSTN (3 << 1) - -/* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(dma) (cpu_to_hc32( (((u32)dma)&~0x01f)|Q_TYPE_QH)) - -/* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END() cpu_to_hc32( 1) /* "null pointer" to hw */ - -/* - * Entries in periodic shadow table are pointers to one of four kinds - * of data structure. That's dictated by the hardware; a type tag is - * encoded in the low bits of the hardware's periodic schedule. Use - * Q_NEXT_TYPE to get the tag. - * - * For entries in the async schedule, the type tag always says "qh". - */ -union ehci_shadow { - struct ehci_qh *qh; /* Q_TYPE_QH */ - struct ehci_itd *itd; /* Q_TYPE_ITD */ - struct ehci_sitd *sitd; /* Q_TYPE_SITD */ - struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ - __hc32 *hw_next; /* (all types) */ - void *ptr; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.6 - * QH: describes control/bulk/interrupt endpoints - * See Fig 3-7 "Queue Head Structure Layout". - * - * These appear in both the async and (for interrupt) periodic schedules. - */ - -struct ehci_qh { - /* first part defined by EHCI spec */ - __hc32 hw_next; /* see EHCI 3.6.1 */ - __hc32 hw_info1; /* see EHCI 3.6.2 */ -#define QH_HEAD 0x00008000 - __hc32 hw_info2; /* see EHCI 3.6.2 */ -#define QH_SMASK 0x000000ff -#define QH_CMASK 0x0000ff00 -#define QH_HUBADDR 0x007f0000 -#define QH_HUBPORT 0x3f800000 -#define QH_MULT 0xc0000000 - __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ - - /* qtd overlay (hardware parts of a struct ehci_qtd) */ - __hc32 hw_qtd_next; - __hc32 hw_alt_next; - __hc32 hw_token; - __hc32 hw_buf [5]; - __hc32 hw_buf_hi [5]; - - /* the rest is HCD-private */ - dma_addr_t qh_dma; /* address of qh */ - struct ehci_qtd *qtd_head; /* sw qtd list */ - - struct ehci_hcd *ehci; - -#define NO_FRAME ((unsigned short)~0) /* pick new start */ -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - - - -/*-------------------------------------------------------------------------*/ - -/* cpu to ehci */ -#define cpu_to_hc32(b) cpu_to_le32(b) -#define hc32_to_cpu(b) le32_to_cpu(b) -#define hc32_to_cpup(b) le32_to_cpu(*(b)) - -/*-------------------------------------------------------------------------*/ - -/* os specific functions */ -void*ehci_maligned(int size,int alignement,int crossing); -dma_addr_t ehci_virt_to_dma(void *); -dma_addr_t ehci_dma_map_to(void *buf,size_t len); -dma_addr_t ehci_dma_map_from(void *buf,size_t len); -dma_addr_t ehci_dma_map_bidir(void *buf,size_t len); -void ehci_dma_unmap_to(dma_addr_t buf,size_t len); -void ehci_dma_unmap_from(dma_addr_t buf,size_t len); -void ehci_dma_unmap_bidir(dma_addr_t buf,size_t len); - - -/* extern API */ - -s32 ehci_control_message(struct ehci_device *dev,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *buf); -s32 ehci_bulk_message(struct ehci_device *dev,u8 bEndpoint,u16 wLength,void *rpData); -int ehci_discover(void); -int ehci_get_device_list(u8 maxdev,u8 b0,u8*num,u16*buf); - -extern struct ehci_hcd *ehci; /* @todo put ehci as a static global and remove ehci from APIs.. */ -extern int ehci_open_device(int vid,int pid,int fd); -extern int ehci_close_device(struct ehci_device *dev); -extern void * ehci_fd_to_dev(int fd); -extern int ehci_release_ports(void); - -/* UMS API */ - -s32 USBStorage_Init(void); -s32 USBStorage_Get_Capacity(u32*sector_size); -s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer); -s32 USBStorage_Read_Stress(u32 sector, u32 numSectors, void *buffer); -s32 USBStorage_Write_Sectors(u32 sector, u32 numSectors, const void *buffer); - -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------*/ - -#endif /* __LINUX_EHCI_HCD_H */ diff --git a/ehci_defs.h b/ehci_defs.h deleted file mode 100644 index d1c1969..0000000 --- a/ehci_defs.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __LINUX_USB_EHCI_DEF_H -#define __LINUX_USB_EHCI_DEF_H - -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -struct ehci_caps { - /* these fields are specified as 8 and 16 bit registers, - * but some hosts can't perform 8 or 16 bit PCI accesses. - */ - u32 hc_capbase; -#define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ -#define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ - u32 hcs_params; /* HCSPARAMS - offset 0x4 */ -#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ -#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ -#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ -#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ -#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ -#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - - u32 hcc_params; /* HCCPARAMS - offset 0x8 */ -#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ -#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ -#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ -#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ -#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ - u8 portroute [8]; /* nibbles for routing - offset 0xC */ -} __attribute__ ((packed)); - - -/* Section 2.3 Host Controller Operational Registers */ -struct ehci_regs { - - /* USBCMD: offset 0x00 */ - u32 command; -/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ -#define CMD_PARK (1<<11) /* enable "park" on async qh */ -#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ -#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ -#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ -#define CMD_ASE (1<<5) /* async schedule enable */ -#define CMD_PSE (1<<4) /* periodic schedule enable */ -/* 3:2 is periodic frame list size */ -#define CMD_RESET (1<<1) /* reset HC not bus */ -#define CMD_RUN (1<<0) /* start/stop HC */ - - /* USBSTS: offset 0x04 */ - u32 status; -#define STS_ASS (1<<15) /* Async Schedule Status */ -#define STS_PSS (1<<14) /* Periodic Schedule Status */ -#define STS_RECL (1<<13) /* Reclamation */ -#define STS_HALT (1<<12) /* Not running (any reason) */ -/* some bits reserved */ - /* these STS_* flags are also intr_enable bits (USBINTR) */ -#define STS_IAA (1<<5) /* Interrupted on async advance */ -#define STS_FATAL (1<<4) /* such as some PCI access errors */ -#define STS_FLR (1<<3) /* frame list rolled over */ -#define STS_PCD (1<<2) /* port change detect */ -#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ -#define STS_INT (1<<0) /* "normal" completion (short, ...) */ - - /* USBINTR: offset 0x08 */ - u32 intr_enable; - - /* FRINDEX: offset 0x0C */ - u32 frame_index; /* current microframe number */ - /* CTRLDSSEGMENT: offset 0x10 */ - u32 segment; /* address bits 63:32 if needed */ - /* PERIODICLISTBASE: offset 0x14 */ - u32 frame_list; /* points to periodic list */ - /* ASYNCLISTADDR: offset 0x18 */ - u32 async_next; /* address of next async queue head */ - - u32 reserved [9]; - - /* CONFIGFLAG: offset 0x40 */ - u32 configured_flag; -#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ - - /* PORTSC: offset 0x44 */ - u32 port_status [0]; /* up to N_PORTS */ -/* 31:23 reserved */ -#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ -#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ -#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ -/* 19:16 for port testing */ -#define PORT_LED_OFF (0<<14) -#define PORT_LED_AMBER (1<<14) -#define PORT_LED_GREEN (2<<14) -#define PORT_LED_MASK (3<<14) -#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ -#define PORT_POWER (1<<12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ -/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ -/* 9 reserved */ -#define PORT_RESET (1<<8) /* reset port */ -#define PORT_SUSPEND (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_OCC (1<<5) /* over current change */ -#define PORT_OC (1<<4) /* over current active */ -#define PORT_PEC (1<<3) /* port enable change */ -#define PORT_PE (1<<2) /* port enable */ -#define PORT_CSC (1<<1) /* connect status change */ -#define PORT_CONNECT (1<<0) /* device connected */ -#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) -} __attribute__ ((packed)); - -#define USBMODE 0x68 /* USB Device mode */ -#define USBMODE_SDIS (1<<3) /* Stream disable */ -#define USBMODE_BE (1<<2) /* BE/LE endianness select */ -#define USBMODE_CM_HC (3<<0) /* host controller mode */ -#define USBMODE_CM_IDLE (0<<0) /* idle state */ - -/* Appendix C, Debug port ... intended for use with special "debug devices" - * that can help if there's no serial console. (nonstandard enumeration.) - */ -struct ehci_dbg_port { - u32 control; -#define DBGP_OWNER (1<<30) -#define DBGP_ENABLED (1<<28) -#define DBGP_DONE (1<<16) -#define DBGP_INUSE (1<<10) -#define DBGP_ERRCODE(x) (((x)>>7)&0x07) -# define DBGP_ERR_BAD 1 -# define DBGP_ERR_SIGNAL 2 -#define DBGP_ERROR (1<<6) -#define DBGP_GO (1<<5) -#define DBGP_OUT (1<<4) -#define DBGP_LEN(x) (((x)>>0)&0x0f) - u32 pids; -#define DBGP_PID_GET(x) (((x)>>16)&0xff) -#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) - u32 data03; - u32 data47; - u32 address; -#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) -} __attribute__ ((packed)); - -#endif /* __LINUX_USB_EHCI_DEF_H */ diff --git a/ehci_types.h b/ehci_types.h deleted file mode 100644 index 051b640..0000000 --- a/ehci_types.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __EHCI_TYPES_H__ -#define __EHCI_TYPES_H__ - -#include "global.h" - -/* linux kernel types needed by our code */ -#define __iomem - -typedef unsigned long uint32_t; - -#if 0 -typedef unsigned long u32; -typedef signed long s32; -typedef unsigned short u16; -typedef unsigned char u8; -typedef char s8; -typedef unsigned long long u64; -#endif - -#define __u32 u32 -#define __le32 u32 -#define dma_addr_t u32 -#define __GNUG__ -typedef u32 spinlock_t; -typedef enum -{ - GFP_KERNEL=1 -}gfp_t; -struct timer_list -{ - int time; -}; -enum{ - ENODEV =1, - ETIMEDOUT, - EINVAL, - ENOMEM, - -}; -#define jiffies 0 -#define likely(x) (x) -#define unlikely(x) (x) -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -#undef offsetof -#ifdef __compiler_offsetof -#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) -#else -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - - -#endif diff --git a/iosmodule.ld b/iosmodule.ld deleted file mode 100644 index 32026a6..0000000 --- a/iosmodule.ld +++ /dev/null @@ -1,81 +0,0 @@ -OUTPUT_FORMAT("elf32-bigarm") -OUTPUT_ARCH(arm) -ENTRY(_start) - -__stack_size = 0x4000; - -MEMORY -{ - sram : ORIGIN = 0xFFFF0000, LENGTH = 0x10000 - stack : ORIGIN = 0xFFFE0000, LENGTH = 0x4000 -} - -PHDRS -{ - sram PT_LOAD AT ( 0xFFFF0000 ) ; - stack PT_LOAD AT ( 0xFFFE0000 ) ; -} - -SECTIONS -{ - .init : - { - *(.init) - . = ALIGN(4); - } >sram :sram - - .text : - { - *(.text*) - *(.text.*) - *(.gnu.warning) - *(.gnu.linkonce.t*) - *(.glue_7) - *(.glue_7t) - . = ALIGN(4); - } >sram :sram - - .rodata : - { - *(.rodata) - *all.rodata*(*) - *(.roda) - *(.rodata.*) - *(.gnu.linkonce.r*) - . = ALIGN(4); - } >sram :sram - - .data : - { - *(.data) - *(.data.*) - *(.gnu.linkonce.d*) - . = ALIGN(4); - } >sram :sram - - .bss : - { - __bss_start = . ; - *(.dynbss) - *(.gnu.linkonce.b*) - *(.bss*) - *(COMMON) - . = ALIGN(4); - __bss_end = . ; - } >sram :sram - - - .stack : - { - __stack_end = .; - . = . +__stack_size; - . = ALIGN(4); - __stack_addr = .; - } >stack :stack - - /DISCARD/ : - { - *(.ARM.exidx*) - *(.ARM.extab*) - } -} diff --git a/tiny_ehci_glue.c b/tiny_ehci_glue.c deleted file mode 100644 index 8dfb21f..0000000 --- a/tiny_ehci_glue.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - EHCI glue. A bit hacky for the moment. needs cleaning.. - - Copyright (C) 2008 kwiirk. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "tiny_ehci_glue.h" - -#define static -#define inline extern - -int verbose=0; - -void BUG(void) -{ - dbgprintf("bug\n"); - while(1); -} -#define BUG_ON(a) if(a)BUG() - -void msleep(int msec) -{ - udelay(2048*msec); -} -extern u32 __exe_start_virt__; -extern u32 __ram_start_virt__; - -extern u32 ios_thread_stack; - -void print_hex_dump_bytes(char *header,int prefix,u8 *buf,int len) -{ - int i; - if (len>0x100)len=0x100; - dbgprintf("%s %08X\n",header,(u32)buf); - for (i=0;icaps = (void*)0x0D040000; - ehci->regs = (void*)(0x0D040000 + HC_LENGTH(ehci_readl(&ehci->caps->hc_capbase))); - - ehci->num_port = 4; - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl( &ehci->caps->hcs_params ); - - /* data structure init */ - retval = ehci_init(); - if (retval) - return retval; - - ehci_release_ports(); //quickly release none usb2 port - - return 0; -} diff --git a/tiny_ehci_glue.h b/tiny_ehci_glue.h deleted file mode 100644 index 880c7d1..0000000 --- a/tiny_ehci_glue.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _TEGLUE_ -#define _TEGLUE_ - -#include "string.h" - -#include "ehci_types.h" -#include "utils.h" -#include "vsprintf.h" - -int tiny_ehci_init(void); - -#define readl(a) (*((volatile u32*)(a))) -#define writel(v,a) do{*((volatile u32*)(a))=(v);}while(0) -#define ehci_dbg(a...) dbgprintf(a) -#define printk(a...) dbgprintf(a) -#define get_timer() (*(((volatile u32*)0x0D800010))) - -#define cpu_to_le32(a) swab32(a) -#define le32_to_cpu(a) swab32(a) -#define cpu_to_le16(a) swab16(a) -#define le16_to_cpu(a) swab16(a) -#define cpu_to_be32(a) (a) -#define be32_to_cpu(a) (a) - -#endif \ No newline at end of file diff --git a/usb.c b/usb.c deleted file mode 100644 index aad58bc..0000000 --- a/usb.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - This file implements libogc usb API, but with ehci direct call - - most of the file credit goes to libogc devs -*/ - -#define __usb_control_message(fd, b, c,d, e, f, g, h, i) ehci_control_message(fd,b,c,d,e,f,g) - -static s32 __usb_getdesc(struct ehci_device * fd, u8 *buffer, u8 type, u8 index, u8 size) -{ - //printk("usb_get desc %X %X %p\n",type,index,buffer); - return __usb_control_message(fd, USB_ENDPOINT_IN ,USB_REQ_GETDESCRIPTOR, (type << 8) | index, 0, size, buffer, NULL, NULL); -} - -s32 USB_GetDescriptors(struct ehci_device * fd, usb_devdesc *udd) -{ - u8 *buffer = NULL; - u8 *ptr = NULL; - usb_configurationdesc *ucd = NULL; - usb_interfacedesc *uid = NULL; - usb_endpointdesc *ued = NULL; - s32 retval = 0; - u32 iConf, iInterface, iEndpoint; - - buffer = USB_Alloc(sizeof(*udd)); - if(buffer == NULL) - { - retval = -ENOMEM; - goto free_and_error; - } - - retval = __usb_getdesc(fd, buffer, USB_DT_DEVICE, 0, USB_DT_DEVICE_SIZE); - if(retval < 0) - { - dbgprintf("USB:__usb_getdesc():%d failed\n", retval ); - goto free_and_error; - } - - memcpy( udd, buffer, USB_DT_DEVICE_SIZE ); - USB_Free(buffer); - - u32 *_udd = (u32*)udd; - - _udd[1] = ( udd->bLength << 24 ) | ( udd->bDescriptorType << 16 ) | cpu_to_le16(udd->bcdUSB); - _udd[2] = ( cpu_to_le16(udd->idVendor) << 16 ) | cpu_to_le16(udd->idProduct); - _udd[3] = ( cpu_to_le16(udd->bcdDevice) << 16 ) | (udd->iManufacturer<<8) | udd->iProduct; - - u32 _ptr = (u32)USB_Alloc( udd->bNumConfigurations * sizeof(*udd->configurations) ); - - //udd->configurations = USB_Alloc(udd->bNumConfigurations* sizeof(*udd->configurations)); - if( _ptr == 0) - { - dbgprintf("USB:USB_Alloc():failed:%u\n", __LINE__ ); - retval = -ENOMEM; - goto free_and_error; - } - - _udd[4] = ( udd->iSerialNumber << 24 ) | ( udd->bNumConfigurations << 16 ) | (_ptr>>16); - _udd[5] = ((_ptr & 0xFFFF) << 16) | (_udd[5]&0xFFFF); - - memset( udd->configurations, 0, udd->bNumConfigurations * sizeof(*udd->configurations) ); - - for( iConf = 0; iConf < udd->bNumConfigurations; iConf++) - { - buffer = USB_Alloc( USB_DT_CONFIG_SIZE ); - if(buffer == NULL) - { - retval = -ENOMEM; - goto free_and_error; - } - - retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, USB_DT_CONFIG_SIZE); - ucd = &udd->configurations[iConf]; - memcpy( ucd, buffer, USB_DT_CONFIG_SIZE ); - USB_Free( buffer ); - - u32 *_ucd = (u32*)ucd; - - _ucd[0] = ( ucd->bLength << 24 ) | ( ucd->bDescriptorType << 16 ) | cpu_to_le16(ucd->wTotalLength); - - //ucd->wTotalLength = cpu_to_le16(ucd->wTotalLength); - - buffer = USB_Alloc( ucd->wTotalLength); - if(buffer == NULL) - { - retval = -ENOMEM; - goto free_and_error; - } - - retval = __usb_getdesc(fd, buffer, USB_DT_CONFIG, iConf, ucd->wTotalLength); - if(retval < 0) - goto free_and_error; - - ptr = buffer; - ptr += ucd->bLength; - - retval = -ENOMEM; - //ucd->interfaces = USB_Alloc(ucd->bNumInterfaces* sizeof(*ucd->interfaces)); - //if(ucd->interfaces == NULL) - // goto free_and_error; - - - - u32 _ptrB = (u32)USB_Alloc(ucd->bNumInterfaces* sizeof(*ucd->interfaces)); - if( _ptrB == 0 ) - goto free_and_error; - - _ucd[2] = ( ucd->bMaxPower << 24 ) | (_ptrB>>8); - _ucd[3] = ((_ptrB & 0xFF) << 24) | (_ucd[3]&0xFFFFFF); - - //dbgprintf("ucd->interfaces:%p\n", ucd->interfaces ); - memset( ucd->interfaces, 0, ucd->bNumInterfaces * sizeof(*ucd->interfaces) ); - - for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) - { - uid = &ucd->interfaces[iInterface]; - memcpy(uid, ptr, USB_DT_INTERFACE_SIZE); - ptr += uid->bLength; - - //uid->endpoints = USB_Alloc(uid->bNumEndpoints* sizeof(*uid->endpoints)); - //if(uid->endpoints == NULL) - // goto free_and_error; - - u32 *_uid = (u32*)uid; - u32 _ptrC = (u32)USB_Alloc(uid->bNumEndpoints* sizeof(*uid->endpoints)); - - _uid[2] = (uid->iInterface<<24) | (_ptrC >> 8); - _uid[3] = (_ptrC<<24) | (_uid[3]&0xFFFFFF); - - memset( uid->endpoints, 0, uid->bNumEndpoints * sizeof(*uid->endpoints) ); - - for( iEndpoint = 0; iEndpoint < uid->bNumEndpoints; iEndpoint++) - { - ued = &uid->endpoints[iEndpoint]; - memcpy( ued, ptr, USB_DT_ENDPOINT_SIZE ); - ptr += ued->bLength; - - //ued->wMaxPacketSize = cpu_to_le16(ued->wMaxPacketSize); - u32 *_ued = (u32*)ued; - _ued[1] = (cpu_to_le16(ued->wMaxPacketSize) << 16 ) | (_ued[1] & 0xFFFF); - } - - USB_Free((void*)_ptrC); - } - - USB_Free((void*)_ptrB); - - USB_Free( buffer); - buffer = (u8*)NULL; - } - retval = 0; - -free_and_error: - if( _ptr != 0 ) - USB_Free((void*)_ptr); - - if(buffer != NULL) - USB_Free(buffer); - - if(retval < 0) - USB_FreeDescriptors(udd); - - return retval; -} - -void USB_FreeDescriptors(usb_devdesc *udd) -{ - int iConf, iInterface; - usb_configurationdesc *ucd; - usb_interfacedesc *uid; - if(udd->configurations != NULL) - { - for(iConf = 0; iConf < udd->bNumConfigurations; iConf++) - { - ucd = &udd->configurations[iConf]; - if(ucd->interfaces != NULL) - { - for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) - { - uid = &ucd->interfaces[iInterface]; - if(uid->endpoints != NULL) - USB_Free(uid->endpoints); - } - USB_Free(ucd->interfaces); - } - } - USB_Free(udd->configurations); - } -} - - -void USB_SuspendDevice(struct ehci_device *fd) -{ - return ; -} -void USB_ResumeDevice(struct ehci_device *fd) -{ - return ; -} - - -s32 USB_WriteBlkMsg(struct ehci_device *fd,u8 bEndpoint,u16 wLength,void *rpData) -{ - return ehci_bulk_message(fd,bEndpoint,wLength,rpData); -} - -s32 USB_WriteCtrlMsg(struct ehci_device *fd,u8 bmRequestType,u8 bmRequest,u16 wValue,u16 wIndex,u16 wLength,void *rpData) -{ - return __usb_control_message(fd,bmRequestType,bmRequest,wValue,wIndex,wLength,rpData,NULL,NULL); -} - -s32 USB_GetConfiguration(struct ehci_device *fd, u8 *configuration) -{ - u8 *_configuration; - s32 retval; - - _configuration = USB_Alloc(1); - if(_configuration == NULL) - return -ENOMEM; - - retval = __usb_control_message(fd, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_DEVICE), USB_REQ_GETCONFIG, 0, 0, 1, _configuration, NULL, NULL); - if(retval >= 0) - *configuration = *_configuration; - USB_Free( _configuration); - - return retval; -} -s32 USB_SetConfiguration(struct ehci_device *fd, u8 configuration) -{ - return __usb_control_message(fd, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_DEVICE), USB_REQ_SETCONFIG, configuration, 0, 0, NULL, NULL, NULL); -} -s32 USB_SetAlternativeInterface(struct ehci_device *fd, u8 interface, u8 alternateSetting) -{ - if(alternateSetting == 0) - return -EINVAL; - return __usb_control_message(fd, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_INTERFACE), - USB_REQ_SETINTERFACE, alternateSetting, interface, 0, NULL, NULL, NULL); - -} -s32 USB_ClearHalt(struct ehci_device *fd, u8 endpoint) -{ - return __usb_control_message(fd, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_STANDARD | USB_CTRLTYPE_REC_ENDPOINT), - USB_REQ_CLEARFEATURE, USB_FEATURE_ENDPOINT_HALT, endpoint, 0, NULL, NULL, NULL); -} diff --git a/usb_os.c b/usb_os.c deleted file mode 100644 index 60b8e27..0000000 --- a/usb_os.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include "ehci_types.h" -#include "usb.h" -#include "ehci.h" -#include "alloc.h" - -void *VirtualToPhysical( void *address ) -{ - if( ((u32)address & 0xFFFF0000) == 0xFFFF0000 ) - return (void*)address; - - return (void*)((u32)address & 0x7FFFFFFF); -} -void sync_after_write( void *a, u32 v ) -{ - dc_flushrange( a, v ); -} -void sync_before_read( void *a, u32 v ) -{ - dc_invalidaterange( a, v ); -} - - -int usb_os_init(void) -{ - return 0; -} -void *ehci_maligned(int size,int alignement,int crossing) -{ - return (void*)malloca( size, alignement ); -} -dma_addr_t ehci_virt_to_dma(void *a) -{ - return (dma_addr_t)VirtualToPhysical(a); -} -dma_addr_t ehci_dma_map_to(void *buf,size_t len) -{ - sync_after_write(buf, len); - return (dma_addr_t)VirtualToPhysical(buf); -} -dma_addr_t ehci_dma_map_from(void *buf,size_t len) -{ - sync_after_write(buf, len); - return (dma_addr_t)VirtualToPhysical(buf); -} -dma_addr_t ehci_dma_map_bidir(void *buf,size_t len) -{ - sync_after_write(buf, len); - return (dma_addr_t)VirtualToPhysical(buf); -} -void ehci_dma_unmap_to(dma_addr_t buf,size_t len) -{ - sync_before_read((void*)buf, len); -} -void ehci_dma_unmap_from(dma_addr_t buf,size_t len) -{ - sync_before_read((void*)buf, len); -} -void ehci_dma_unmap_bidir(dma_addr_t buf,size_t len) -{ - sync_before_read((void*)buf, len); -} -void *USB_Alloc(int size) -{ - //u32 val; - //__asm("mov %0,lr": "=r" (val) ); - //dbgprintf("USB_Alloc(%u) LR:%08x\n", size, val ); - - //void *ptr = malloc(size); - //memset( ptr, 0, size ); - //return ptr; - - return malloc(size); -} -void USB_Free(void *ptr) -{ - return free(ptr); -} diff --git a/usbstorage.c b/usbstorage.c deleted file mode 100644 index 2952d3a..0000000 --- a/usbstorage.c +++ /dev/null @@ -1,755 +0,0 @@ -/*------------------------------------------------------------- - -usbstorage.c -- Bulk-only USB mass storage support - -Copyright (C) 2008 -Sven Peter (svpe) - -quick port to ehci/ios: Kwiirk - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you -must not claim that you wrote the original software. If you use -this software in a product, an acknowledgment in the product -documentation would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. - --------------------------------------------------------------*/ - -#define ROUNDDOWN32(v) (((u32)(v)-0x1f)&~0x1f) - -#define HEAP_SIZE (32*1024) -#define TAG_START 0x1//BADC0DE - -#define CBW_SIZE 31 -#define CBW_SIGNATURE 0x43425355 -#define CBW_IN (1 << 7) -#define CBW_OUT 0 - -#define CSW_SIZE 13 -#define CSW_SIGNATURE 0x53425355 - -#define SCSI_TEST_UNIT_READY 0x00 -#define SCSI_INQUIRY 0x12 -#define SCSI_REQUEST_SENSE 0x03 -#define SCSI_READ_CAPACITY 0x25 -#define SCSI_READ_10 0x28 -#define SCSI_WRITE_10 0x2A - -#define SCSI_SENSE_REPLY_SIZE 18 -#define SCSI_SENSE_NOT_READY 0x02 -#define SCSI_SENSE_MEDIUM_ERROR 0x03 -#define SCSI_SENSE_HARDWARE_ERROR 0x04 - -#define USB_CLASS_MASS_STORAGE 0x08 -#define MASS_STORAGE_SCSI_COMMANDS 0x06 -#define MASS_STORAGE_BULK_ONLY 0x50 - -#define USBSTORAGE_GET_MAX_LUN 0xFE -#define USBSTORAGE_RESET 0xFF - -#define USB_ENDPOINT_BULK 0x02 - -#define USBSTORAGE_CYCLE_RETRIES 3 - -#define MAX_TRANSFER_SIZE 4096 - -#define DEVLIST_MAXSIZE 8 - -static s32 __usbstorage_reset(usbstorage_handle *dev); -static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun); - -// ehci driver has its own timeout. -static s32 __USB_BlkMsgTimeout(usbstorage_handle *dev, u8 bEndpoint, u16 wLength, void *rpData) -{ - return USB_WriteBlkMsg(dev->usb_fd, bEndpoint, wLength, rpData); -} - -static s32 __USB_CtrlMsgTimeout(usbstorage_handle *dev, u8 bmRequestType, u8 bmRequest, u16 wValue, u16 wIndex, u16 wLength, void *rpData) -{ - return USB_WriteCtrlMsg(dev->usb_fd, bmRequestType, bmRequest, wValue, wIndex, wLength, rpData); -} -static s32 __send_cbw(usbstorage_handle *dev, u8 lun, u32 len, u8 flags, const u8 *cb, u8 cbLen) -{ - s32 retval = USBSTORAGE_OK; - - if(cbLen == 0 || cbLen > 16) - return -EINVAL; - - memset(dev->buffer, 0, CBW_SIZE); - - ((u32*)dev->buffer)[0]=cpu_to_le32(CBW_SIGNATURE); - ((u32*)dev->buffer)[1]=cpu_to_le32(dev->tag); - ((u32*)dev->buffer)[2]=cpu_to_le32(len); - dev->buffer[12] = flags; - dev->buffer[13] = lun; - dev->buffer[14] = (cbLen > 6 ? 0x10 : 6); - - memcpy(dev->buffer + 15, (void*)cb, cbLen); - - retval = __USB_BlkMsgTimeout(dev, dev->ep_out, CBW_SIZE, (void *)dev->buffer); - - if(retval == CBW_SIZE) return USBSTORAGE_OK; - else if(retval >= 0) return USBSTORAGE_ESHORTWRITE; - - return retval; -} - -static s32 __read_csw(usbstorage_handle *dev, u8 *status, u32 *dataResidue) -{ - s32 retval = USBSTORAGE_OK; - u32 signature, tag, _dataResidue, _status; - - memset(dev->buffer, 0xff, CSW_SIZE); - - retval = __USB_BlkMsgTimeout(dev, dev->ep_in, CSW_SIZE, dev->buffer); - //print_hex_dump_bytes("csv resp:",DUMP_PREFIX_OFFSET,dev->buffer,CSW_SIZE); - - if(retval >= 0 && retval != CSW_SIZE) return USBSTORAGE_ESHORTREAD; - else if(retval < 0) return retval; - - signature = le32_to_cpu(((u32*)dev->buffer)[0]); - tag = le32_to_cpu(((u32*)dev->buffer)[1]); - _dataResidue = le32_to_cpu(((u32*)dev->buffer)[2]); - _status = dev->buffer[12]; - - if(signature != CSW_SIGNATURE) { - BUG(); - return USBSTORAGE_ESIGNATURE; - } - - if(dataResidue != NULL) - *dataResidue = _dataResidue; - if(status != NULL) - *status = _status; - - if(tag != dev->tag) return USBSTORAGE_ETAG; - dev->tag++; - - return USBSTORAGE_OK; -} -static s32 __cycle(usbstorage_handle *dev, u8 lun, u8 *buffer, u32 len, u8 *cb, u8 cbLen, u8 write, u8 *_status, u32 *_dataResidue) -{ - s32 retval = USBSTORAGE_OK; - - u8 status = 0; - u32 dataResidue = 0; - u32 thisLen; - - s8 retries = USBSTORAGE_CYCLE_RETRIES + 1; - - do - { - retries--; - if(retval == USBSTORAGE_ETIMEDOUT) - break; - - if(write) - { - retval = __send_cbw(dev, lun, len, CBW_OUT, cb, cbLen); - if(retval == USBSTORAGE_ETIMEDOUT) - break; - if(retval < 0) - { - if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT) - retval = USBSTORAGE_ETIMEDOUT; - continue; - } - while(len > 0) - { - thisLen=len; - retval = __USB_BlkMsgTimeout(dev, dev->ep_out, thisLen, buffer); - - if(retval == USBSTORAGE_ETIMEDOUT) - break; - - if(retval < 0) - { - retval = USBSTORAGE_EDATARESIDUE; - break; - } - - - if(retval != thisLen && len > 0) - { - retval = USBSTORAGE_EDATARESIDUE; - break; - } - len -= retval; - buffer += retval; - } - - if(retval < 0) - { - if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT) - retval = USBSTORAGE_ETIMEDOUT; - continue; - } - } - else - { - retval = __send_cbw(dev, lun, len, CBW_IN, cb, cbLen); - - if(retval == USBSTORAGE_ETIMEDOUT) - break; - - if(retval < 0) - { - if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT) - retval = USBSTORAGE_ETIMEDOUT; - continue; - } - while(len > 0) - { - thisLen=len; - retval = __USB_BlkMsgTimeout(dev, dev->ep_in, thisLen, buffer); - //print_hex_dump_bytes("usbs in:",DUMP_PREFIX_OFFSET,dev->buffer,36); - if(retval < 0) - break; - - len -= retval; - buffer += retval; - - if(retval != thisLen) - break; - } - - if(retval < 0) - { - if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT) - retval = USBSTORAGE_ETIMEDOUT; - continue; - } - } - - retval = __read_csw(dev, &status, &dataResidue); - - if(retval == USBSTORAGE_ETIMEDOUT) - break; - - if(retval < 0) - { - if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT) - retval = USBSTORAGE_ETIMEDOUT; - continue; - } - - retval = USBSTORAGE_OK; - } while(retval < 0 && retries > 0); - - if(retval < 0 && retval != USBSTORAGE_ETIMEDOUT) - { - if(__usbstorage_reset(dev) == USBSTORAGE_ETIMEDOUT) - retval = USBSTORAGE_ETIMEDOUT; - } - - - if(_status != NULL) - *_status = status; - if(_dataResidue != NULL) - *_dataResidue = dataResidue; - - return retval; -} - -static s32 __usbstorage_clearerrors(usbstorage_handle *dev, u8 lun) -{ - s32 retval; - u8 cmd[16]; - u8 *sense= USB_Alloc(SCSI_SENSE_REPLY_SIZE); - u8 status = 0; - memset(cmd, 0, sizeof(cmd)); - cmd[0] = SCSI_TEST_UNIT_READY; - - retval = __cycle(dev, lun, NULL, 0, cmd, 1, 1, &status, NULL); - if(retval < 0) return retval; - - if(status != 0) - { - cmd[0] = SCSI_REQUEST_SENSE; - cmd[1] = lun << 5; - cmd[4] = SCSI_SENSE_REPLY_SIZE; - cmd[5] = 0; - memset(sense, 0, SCSI_SENSE_REPLY_SIZE); - retval = __cycle(dev, lun, sense, SCSI_SENSE_REPLY_SIZE, cmd, 6, 0, NULL, NULL); - if(retval < 0) goto error; - - status = sense[2] & 0x0F; - if(status == SCSI_SENSE_NOT_READY || status == SCSI_SENSE_MEDIUM_ERROR || status == SCSI_SENSE_HARDWARE_ERROR) - retval = USBSTORAGE_ESENSE; - } -error: - USB_Free(sense); - return retval; -} - -static s32 __usbstorage_reset(usbstorage_handle *dev) -{ - s32 retval; - - if(dev->suspended == 1) - { - USB_ResumeDevice(dev->usb_fd); - dev->suspended = 0; - } -/* - retval = ehci_reset_device(dev->usb_fd); - if(retval < 0 && retval != -7004) - goto end; - */ - //debug_printf("usbstorage reset..\n"); - retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_HOST2DEVICE | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_RESET, 0, dev->interface, 0, NULL); - - /* FIXME?: some devices return -7004 here which definitely violates the usb ms protocol but they still seem to be working... */ - if(retval < 0 && retval != -7004) - goto end; - - /* gives device enough time to process the reset */ - msleep(10); - - //debug_printf("cleat halt on bulk ep..\n"); - retval = USB_ClearHalt(dev->usb_fd, dev->ep_in); - if(retval < 0) - goto end; - retval = USB_ClearHalt(dev->usb_fd, dev->ep_out); - -end: - return retval; -} - -s32 USBStorage_Open(usbstorage_handle *dev, struct ehci_device *fd) -{ - s32 retval = -1; - u8 conf,*max_lun = NULL; - u32 iConf, iInterface, iEp; - usb_devdesc udd; - usb_configurationdesc *ucd; - usb_interfacedesc *uid; - usb_endpointdesc *ued; - - max_lun = USB_Alloc(1); - if(max_lun==NULL) return -ENOMEM; - - memset(dev, 0, sizeof(*dev)); - - dev->tag = TAG_START; - dev->usb_fd = fd; - - retval = USB_GetDescriptors(dev->usb_fd, &udd); - if(retval < 0) - { - dbgprintf("USB_GetDescriptors():%d\n", retval ); - goto free_and_return; - } - - dbgprintf("udd.bNumConfigurations:%u\n", udd.bNumConfigurations ); - - for(iConf = 0; iConf < udd.bNumConfigurations; iConf++) - { - ucd = &udd.configurations[iConf]; - for(iInterface = 0; iInterface < ucd->bNumInterfaces; iInterface++) - { - uid = &ucd->interfaces[iInterface]; - if(uid->bInterfaceClass == USB_CLASS_MASS_STORAGE && - uid->bInterfaceSubClass == MASS_STORAGE_SCSI_COMMANDS && - uid->bInterfaceProtocol == MASS_STORAGE_BULK_ONLY) - { - if(uid->bNumEndpoints < 2) - continue; - - dev->ep_in = dev->ep_out = 0; - for(iEp = 0; iEp < uid->bNumEndpoints; iEp++) - { - ued = &uid->endpoints[iEp]; - if(ued->bmAttributes != USB_ENDPOINT_BULK) - continue; - - if(ued->bEndpointAddress & USB_ENDPOINT_IN) - { - dev->ep_in = ued->bEndpointAddress; - dbgprintf("%08X:%08X\n", dev->ep_in, ued->bEndpointAddress ); - } else { - dev->ep_out = ued->bEndpointAddress; - dbgprintf("%08X:%08X\n", dev->ep_out, ued->bEndpointAddress ); - } - } - - if(dev->ep_in != 0 && dev->ep_out != 0) - { - dev->configuration = ucd->bConfigurationValue; - dev->interface = uid->bInterfaceNumber; - dev->altInterface = uid->bAlternateSetting; - - dbgprintf("%08X:%08X\n", dev->configuration , ucd->bConfigurationValue ); - dbgprintf("%08X:%08X\n", dev->interface , uid->bInterfaceNumber ); - dbgprintf("%08X:%08X\n", dev->altInterface , uid->bAlternateSetting ); - - goto found; - } - } - } - } - - USB_FreeDescriptors(&udd); - retval = USBSTORAGE_ENOINTERFACE; - goto free_and_return; - -found: - USB_FreeDescriptors(&udd); - - retval = USBSTORAGE_EINIT; - if(USB_GetConfiguration(dev->usb_fd, &conf) < 0) - goto free_and_return; - if(conf != dev->configuration && USB_SetConfiguration(dev->usb_fd, dev->configuration) < 0) - goto free_and_return; - if(dev->altInterface != 0 && USB_SetAlternativeInterface(dev->usb_fd, dev->interface, dev->altInterface) < 0) - goto free_and_return; - dev->suspended = 0; - - retval = USBStorage_Reset(dev); - if(retval < 0) - goto free_and_return; - - retval = __USB_CtrlMsgTimeout(dev, (USB_CTRLTYPE_DIR_DEVICE2HOST | USB_CTRLTYPE_TYPE_CLASS | USB_CTRLTYPE_REC_INTERFACE), USBSTORAGE_GET_MAX_LUN, 0, dev->interface, 1, max_lun); - if(retval < 0) - dev->max_lun = 1; - else - dev->max_lun = *max_lun; - - - if(retval == USBSTORAGE_ETIMEDOUT) - goto free_and_return; - - retval = USBSTORAGE_OK; - - if(dev->max_lun == 0) - dev->max_lun++; - - /* taken from linux usbstorage module (drivers/usb/storage/transport.c) */ - /* - * Some devices (i.e. Iomega Zip100) need this -- apparently - * the bulk pipes get STALLed when the GetMaxLUN request is - * processed. This is, in theory, harmless to all other devices - * (regardless of if they stall or not). - */ - USB_ClearHalt(dev->usb_fd, dev->ep_in); - USB_ClearHalt(dev->usb_fd, dev->ep_out); - - dev->buffer = /*USB_Alloc(MAX_TRANSFER_SIZE)*/(u8*)0xFFFE4000; - - if(dev->buffer == NULL) retval = -ENOMEM; - else retval = USBSTORAGE_OK; - -free_and_return: - if(max_lun!=NULL) - USB_Free(max_lun); - - if(retval < 0) - { - if(dev->buffer != NULL) - USB_Free(dev->buffer); - memset(dev, 0, sizeof(*dev)); - return retval; - } - return 0; -} - -s32 USBStorage_Close(usbstorage_handle *dev) -{ - if(dev->buffer != NULL) - USB_Free(dev->buffer); - memset(dev, 0, sizeof(*dev)); - return 0; -} - -s32 USBStorage_Reset(usbstorage_handle *dev) -{ - s32 retval; - - retval = __usbstorage_reset(dev); - - return retval; -} - -s32 USBStorage_GetMaxLUN(usbstorage_handle *dev) -{ - - return dev->max_lun; -} - -s32 USBStorage_MountLUN(usbstorage_handle *dev, u8 lun) -{ - s32 retval; - - if(lun >= dev->max_lun) - return -EINVAL; - - retval = __usbstorage_clearerrors(dev, lun); - if(retval < 0) - return retval; - - retval = USBStorage_Inquiry(dev, lun); - - retval = USBStorage_ReadCapacity(dev, lun, &dev->sector_size[lun], &dev->n_sector[lun]); - return retval; -} - -s32 USBStorage_Inquiry(usbstorage_handle *dev, u8 lun) -{ - s32 retval; - u8 cmd[] = {SCSI_INQUIRY, lun << 5,0,0,36,0}; - u8 *response = USB_Alloc(36); - - retval = __cycle(dev, lun, response, 36, cmd, 6, 0, NULL, NULL); - //print_hex_dump_bytes("inquiry result:",DUMP_PREFIX_OFFSET,response,36); - USB_Free(response); - return retval; -} -s32 USBStorage_ReadCapacity(usbstorage_handle *dev, u8 lun, u32 *sector_size, u32 *n_sectors) -{ - s32 retval; - u8 cmd[] = {SCSI_READ_CAPACITY, lun << 5}; - u8 *response = USB_Alloc(8); - u32 val; - retval = __cycle(dev, lun, response, 8, cmd, 2, 0, NULL, NULL); - if(retval >= 0) - { - - memcpy(&val, response, 4); - if(n_sectors != NULL) - *n_sectors = be32_to_cpu(val); - memcpy(&val, response + 4, 4); - if(sector_size != NULL) - *sector_size = be32_to_cpu(val); - retval = USBSTORAGE_OK; - } - USB_Free(response); - return retval; -} - -s32 USBStorage_Read(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, u8 *buffer) -{ - u8 status = 0; - s32 retval; - u8 cmd[] = { - SCSI_READ_10, - lun << 5, - sector >> 24, - sector >> 16, - sector >> 8, - sector, - 0, - n_sectors >> 8, - n_sectors, - 0 - }; - if(lun >= dev->max_lun || dev->sector_size[lun] == 0) - return -EINVAL; - retval = __cycle(dev, lun, buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 0, &status, NULL); - if(retval > 0 && status != 0) - retval = USBSTORAGE_ESTATUS; - return retval; -} - -s32 USBStorage_Write(usbstorage_handle *dev, u8 lun, u32 sector, u16 n_sectors, const u8 *buffer) -{ - u8 status = 0; - s32 retval; - u8 cmd[] = { - SCSI_WRITE_10, - lun << 5, - sector >> 24, - sector >> 16, - sector >> 8, - sector, - 0, - n_sectors >> 8, - n_sectors, - 0 - }; - if(lun >= dev->max_lun || dev->sector_size[lun] == 0) - return -EINVAL; - retval = __cycle(dev, lun, (u8 *)buffer, n_sectors * dev->sector_size[lun], cmd, sizeof(cmd), 1, &status, NULL); - if(retval > 0 && status != 0) - retval = USBSTORAGE_ESTATUS; - return retval; -} - -s32 USBStorage_Suspend(usbstorage_handle *dev) -{ - if(dev->suspended == 1) - return USBSTORAGE_OK; - - USB_SuspendDevice(dev->usb_fd); - dev->suspended = 1; - - return USBSTORAGE_OK; - -} -/* -The following is for implementing the ioctl interface inpired by the disc_io.h -as used by libfat - -This opens the first lun of the first usbstorage device found. -*/ - -static usbstorage_handle __usbfd; -static u8 __lun = 0; -static u8 __mounted = 0; -static u16 __vid = 0; -static u16 __pid = 0; - -void switchbuf(void) -{ - memcpy( (void*)0x080A0000, __usbfd.buffer, CBW_SIZE ); - __usbfd.buffer = (u8*)0x080A0000; -} -/* perform 512 time the same read */ -s32 USBStorage_Read_Stress(u32 sector, u32 numSectors, void *buffer) -{ - s32 retval; - int i; - if(__mounted != 1) - return false; - - for(i=0;i<512;i++){ - retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer); - sector+=numSectors; - if(retval == USBSTORAGE_ETIMEDOUT) - { - __mounted = 0; - USBStorage_Close(&__usbfd); - } - if(retval < 0) - return false; - } - return true; - -} -// temp function before libfat is available */ -s32 USBStorage_Try_Device(struct ehci_device *fd) -{ - int maxLun,j,retval; - int ret = USBStorage_Open(&__usbfd, fd); - if( ret < 0) - { - dbgprintf("USB:Could not open device:%d\n",ret); - return -EINVAL; - } - - maxLun = USBStorage_GetMaxLUN(&__usbfd); - if(maxLun == USBSTORAGE_ETIMEDOUT) - { - dbgprintf("USB:Device timed out\n"); - return -EINVAL; - } - - for(j = 0; j < maxLun; j++) - { - retval = USBStorage_MountLUN(&__usbfd, j); - if(retval == USBSTORAGE_ETIMEDOUT) - { - USBStorage_Reset(&__usbfd); - USBStorage_Close(&__usbfd); - break; - } - - if(retval < 0) - continue; - - __vid=fd->desc.idVendor; - __pid=fd->desc.idProduct; - __mounted = 1; - __lun = j; - return 0; - } - - dbgprintf("USB:Device failed to mount\n"); - return -EINVAL; -} - -static int ums_init_done = 0; -s32 USBStorage_Init(void) -{ - s32 res = -ENODEV; - - int i; - //debug_printf("usbstorage init %d\n", ums_init_done); - if(ums_init_done) - return 0; - - - - for(i = 0;inum_port; i++) - { - struct ehci_device *dev = &ehci->devices[i]; - if(dev->id != 0) - { - res = USBStorage_Try_Device(dev); - if( res == 0 ) - ums_init_done = 1; - } - } - return res; -} - -s32 USBStorage_Get_Capacity(u32*sector_size) -{ - if(__mounted == 1) - { - if(sector_size){ - *sector_size = __usbfd.sector_size[__lun]; - } - return __usbfd.n_sector[__lun]; - } - return 0; -} - -s32 USBStorage_Read_Sectors(u32 sector, u32 numSectors, void *buffer) -{ - s32 retval; - - if(__mounted != 1) - return false; - - retval = USBStorage_Read(&__usbfd, __lun, sector, numSectors, buffer); - if(retval == USBSTORAGE_ETIMEDOUT) - { - __mounted = 0; - USBStorage_Close(&__usbfd); - } - if(retval < 0) - return false; - return true; -} - -s32 USBStorage_Write_Sectors(u32 sector, u32 numSectors, const void *buffer) -{ - s32 retval; - - if(__mounted != 1) - return false; - - retval = USBStorage_Write(&__usbfd, __lun, sector, numSectors, buffer); - if(retval == USBSTORAGE_ETIMEDOUT) - { - __mounted = 0; - USBStorage_Close(&__usbfd); - } - if(retval < 0) - return false; - return true; -} -