diff --git a/BaS_gcc.files b/BaS_gcc.files index eda7528..06d653b 100644 --- a/BaS_gcc.files +++ b/BaS_gcc.files @@ -267,3 +267,5 @@ tos/jtagwait/sources/printf_helper.S tos/bascook/Makefile tos/bascook/sources/bascook.c tos/Makefile +usb/usb_hub.c +include/usb_hub.h diff --git a/Makefile b/Makefile index c21aaa9..b18f143 100644 --- a/Makefile +++ b/Makefile @@ -95,6 +95,7 @@ CSRCS= \ usb.c \ ohci-hcd.c \ ehci-hcd.c \ + usb_hub.c \ usb_mouse.c \ ikbd.c \ \ diff --git a/bas.lk.in b/bas.lk.in index 66d9831..a9b85d3 100644 --- a/bas.lk.in +++ b/bas.lk.in @@ -51,6 +51,7 @@ SECTIONS OBJDIR/pci_wrappers.o(.text) OBJDIR/usb.o(.text) OBJDIR/driver_mem.o(.text) + OBJDIR/usb_hub.o(.text) OBJDIR/usb_mouse.o(.text) OBJDIR/ohci-hcd.o(.text) OBJDIR/ehci-hcd.o(.text) diff --git a/include/ehci.h b/include/ehci.h index 6176a9a..e940205 100644 --- a/include/ehci.h +++ b/include/ehci.h @@ -51,7 +51,7 @@ struct ehci_hccr { #define HC_LENGTH(p) (((p) >> 0) & 0x00ff) #define HC_VERSION(p) (((p) >> 16) & 0xffff) uint32_t cr_hcsparams; -#define HCS_PPC(p) ((p) & (1 << 4)) +#define HCS_PPC(p) ((p) & (1 << 4)) #define HCS_INDICATOR(p) ((p) & (1 << 16)) /* Port indicators */ #define HCS_N_PORTS(p) (((p) >> 0) & 0xf) uint32_t cr_hccparams; @@ -70,20 +70,20 @@ struct ehci_hcor { #define CMD_RUN (1 << 0) /* start/stop HC */ uint32_t or_usbsts; #define STD_ASS (1 << 15) -#define STS_PSSTAT (1 << 14) -#define STS_RECL ( 1 << 13) +#define STS_PSSTAT (1 << 14) +#define STS_RECL (1 << 13) #define STS_HALT (1 << 12) -#define STS_IAA (1 << 5) -#define STS_HSE (1 << 4) -#define STS_FLR (1 << 3) -#define STS_PCD (1 << 2) +#define STS_IAA (1 << 5) +#define STS_HSE (1 << 4) +#define STS_FLR (1 << 3) +#define STS_PCD (1 << 2) #define STS_USBERRINT (1 << 1) -#define STS_USBINT (1 << 0) +#define STS_USBINT (1 << 0) uint32_t or_usbintr; -#define INTR_IAAE (1 << 5) -#define INTR_HSEE (1 << 4) -#define INTR_FLRE (1 << 3) -#define INTR_PCDE (1 << 2) +#define INTR_IAAE (1 << 5) +#define INTR_HSEE (1 << 4) +#define INTR_FLRE (1 << 3) +#define INTR_PCDE (1 << 2) #define INTR_USBERRINTE (1 << 1) #define INTR_USBINTE (1 << 0) uint32_t or_frindex; @@ -97,14 +97,15 @@ struct ehci_hcor { uint32_t or_systune; } __attribute__ ((packed)); -#define USBMODE 0x68 /* USB Device mode */ +#define USBMODE 0x68 /* USB Device mode */ #define USBMODE_SDIS (1 << 3) /* Stream disable */ -#define USBMODE_BE (1 << 2) /* BE/LE endiannes select */ +#define USBMODE_BE (1 << 2) /* BE/LE endiannes select */ #define USBMODE_CM_HC (3 << 0) /* host controller mode */ #define USBMODE_CM_IDLE (0 << 0) /* idle state */ /* Interface descriptor */ -struct usb_linux_interface_descriptor { +struct usb_linux_interface_descriptor +{ unsigned char bLength; unsigned char bDescriptorType; unsigned char bInterfaceNumber; @@ -117,7 +118,8 @@ struct usb_linux_interface_descriptor { } __attribute__ ((packed)); /* Configuration descriptor information.. */ -struct usb_linux_config_descriptor { +struct usb_linux_config_descriptor +{ unsigned char bLength; unsigned char bDescriptorType; unsigned short wTotalLength; @@ -129,11 +131,11 @@ struct usb_linux_config_descriptor { } __attribute__ ((packed)); #if defined CONFIG_EHCI_DESC_BIG_ENDIAN -#define ehci_readl(x) (*((volatile u32 *)(x))) -#define ehci_writel(a, b) (*((volatile u32 *)(a)) = ((volatile u32)b)) +#define ehci_readl(x) (*((volatile uint32_t *)(x))) +#define ehci_writel(a, b) (*((volatile uint32_t *)(a)) = ((volatile uint32_t) b)) #else -#define ehci_readl(x) swpl((*((volatile u32 *)(x)))) -#define ehci_writel(a, b) (*((volatile u32 *)(a)) = swpl(((volatile u32)b))) +#define ehci_readl(x) swpl((*((volatile uint32_t *)(x)))) +#define ehci_writel(a, b) (*((volatile uint32_t *)(a)) = swpl(((volatile uint32_t) b))) #endif #if defined CONFIG_EHCI_MMIO_BIG_ENDIAN @@ -147,18 +149,18 @@ struct usb_linux_config_descriptor { #define EHCI_PS_WKOC_E (1 << 22) /* RW wake on over current */ #define EHCI_PS_WKDSCNNT_E (1 << 21) /* RW wake on disconnect */ #define EHCI_PS_WKCNNT_E (1 << 20) /* RW wake on connect */ -#define EHCI_PS_PO (1 << 13) /* RW port owner */ -#define EHCI_PS_PP (1 << 12) /* RW,RO port power */ -#define EHCI_PS_LS (3 << 10) /* RO line status */ -#define EHCI_PS_PR (1 << 8) /* RW port reset */ -#define EHCI_PS_SUSP (1 << 7) /* RW suspend */ -#define EHCI_PS_FPR (1 << 6) /* RW force port resume */ -#define EHCI_PS_OCC (1 << 5) /* RWC over current change */ -#define EHCI_PS_OCA (1 << 4) /* RO over current active */ -#define EHCI_PS_PEC (1 << 3) /* RWC port enable change */ -#define EHCI_PS_PE (1 << 2) /* RW port enable */ -#define EHCI_PS_CSC (1 << 1) /* RWC connect status change */ -#define EHCI_PS_CS (1 << 0) /* RO connect status */ +#define EHCI_PS_PO (1 << 13) /* RW port owner */ +#define EHCI_PS_PP (1 << 12) /* RW,RO port power */ +#define EHCI_PS_LS (3 << 10) /* RO line status */ +#define EHCI_PS_PR (1 << 8) /* RW port reset */ +#define EHCI_PS_SUSP (1 << 7) /* RW suspend */ +#define EHCI_PS_FPR (1 << 6) /* RW force port resume */ +#define EHCI_PS_OCC (1 << 5) /* RWC over current change */ +#define EHCI_PS_OCA (1 << 4) /* RO over current active */ +#define EHCI_PS_PEC (1 << 3) /* RWC port enable change */ +#define EHCI_PS_PE (1 << 2) /* RW port enable */ +#define EHCI_PS_CSC (1 << 1) /* RWC connect status change */ +#define EHCI_PS_CS (1 << 0) /* RO connect status */ #define EHCI_PS_CLEAR (EHCI_PS_OCC | EHCI_PS_PEC | EHCI_PS_CSC) #define EHCI_PS_IS_LOWSPEED(x) (((x) & EHCI_PS_LS) == (1 << 10)) @@ -174,7 +176,8 @@ struct usb_linux_config_descriptor { */ /* Queue Element Transfer Descriptor (qTD). */ -struct qTD { +struct qTD +{ uint32_t qt_next; #define QT_NEXT_TERMINATE 1 uint32_t qt_altnext; @@ -183,7 +186,8 @@ struct qTD { }; /* Queue Head (QH). */ -struct QH { +struct QH +{ uint32_t qh_link; #define QH_LINK_TERMINATE 1 #define QH_LINK_TYPE_ITD 0 diff --git a/include/usb.h b/include/usb.h index 97ebc91..0604804 100644 --- a/include/usb.h +++ b/include/usb.h @@ -26,7 +26,6 @@ #ifndef _USB_H_ #define _USB_H_ -//#include #include #include "driver_mem.h" #include "pci.h" @@ -37,14 +36,6 @@ extern long *tab_funcs_pci; -#define in8(addr) Fast_read_mem_byte(usb_handle,addr) -#define in16r(addr) Fast_read_mem_word(usb_handle,addr) -#define in32r(addr) Fast_read_mem_longword(usb_handle,addr) -#define out8(addr,val) Write_mem_byte(usb_handle,addr,val) -#define out16r(addr,val) Write_mem_word(usb_handle,addr,val) -#define out32r(addr,val) Write_mem_longword(usb_handle,addr,val) - - #define __u8 uint8_t #define __u16 uint16_t #define __u32 uint32_t @@ -74,6 +65,8 @@ extern int sprintD(char *s, const char *fmt, ...); #define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ +#define USB_BUFSIZ 512 + /* String descriptor */ struct usb_string_descriptor { @@ -238,65 +231,62 @@ typedef struct * this is how the lowlevel part communicate with the outer world */ -int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void **priv); -int ohci_usb_lowlevel_stop(void *priv); -int ohci_submit_bulk_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len); -int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, struct devrequest *setup); -int ohci_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval); -void ohci_usb_enable_interrupt(int enable); +extern int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void **priv); +extern int ohci_usb_lowlevel_stop(void *priv); +extern int ohci_submit_bulk_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len); +extern int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, struct devrequest *setup); +extern int ohci_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval); +extern void ohci_usb_enable_interrupt(int enable); -int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **priv); -int ehci_usb_lowlevel_stop(void *priv); -int ehci_submit_bulk_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len); -int ehci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, struct devrequest *setup); -int ehci_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval); -void ehci_usb_enable_interrupt(int enable); +extern int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **priv); +extern int ehci_usb_lowlevel_stop(void *priv); +extern int ehci_submit_bulk_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len); +extern int ehci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, struct devrequest *setup); +extern int ehci_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval); +extern void ehci_usb_enable_interrupt(int enable); -void usb_enable_interrupt(int enable); +extern void usb_enable_interrupt(int enable); + +extern int usb_new_device(struct usb_device *dev); +extern struct usb_device *usb_alloc_new_device(int bus_index, void *priv); +extern void usb_disconnect(struct usb_device **pdev); #define USB_MAX_STOR_DEV 5 -block_dev_desc_t *usb_stor_get_dev(int index); -int usb_stor_scan(void); -int usb_stor_info(void); -int usb_stor_register(struct usb_device *dev); -int usb_stor_deregister(struct usb_device *dev); -int drv_usb_kbd_init(void); -int usb_kbd_register(struct usb_device *dev); -int usb_kbd_deregister(struct usb_device *dev); +extern block_dev_desc_t *usb_stor_get_dev(int index); +extern int usb_stor_scan(void); +extern int usb_stor_info(void); +extern int usb_stor_register(struct usb_device *dev); +extern int usb_stor_deregister(struct usb_device *dev); -int drv_usb_mouse_init(void); -int usb_mouse_register(struct usb_device *dev); -int usb_mouse_deregister(struct usb_device *dev); +extern int drv_usb_kbd_init(void); +extern int usb_kbd_register(struct usb_device *dev); +extern int usb_kbd_deregister(struct usb_device *dev); -/* memory */ -void *usb_malloc(long amount); -int usb_free(void *addr); -int usb_mem_init(void); -void usb_mem_stop(void); +extern int drv_usb_mouse_init(void); +extern int usb_mouse_register(struct usb_device *dev); +extern int usb_mouse_deregister(struct usb_device *dev); /* routines */ -USB_COOKIE *usb_get_cookie(long id); -void usb_error_msg(const char *const fmt, ... ); -int usb_init(int32_t handle, const struct pci_device_id *ent); /* initialize the USB Controller */ -int usb_stop(void); /* stop the USB Controller */ +extern int usb_init(int32_t handle, const struct pci_device_id *ent); /* initialize the USB Controller */ +extern int usb_stop(void); /* stop the USB Controller */ -int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); -int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id); -struct usb_device *usb_get_dev_index(int index, int bus); -int usb_control_msg(struct usb_device *dev, unsigned int pipe, uint8_t request, uint8_t requesttype, uint16_t value, - uint16_t index, void *data, uint16_t size, int timeout); -int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout); -int usb_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval); -void usb_disable_asynch(int disable); -int usb_maxpacket(struct usb_device *dev, uint32_t pipe); -void wait_ms(uint32_t ms); -int usb_get_configuration_no(struct usb_device *dev, uint8_t *buffer, int cfgno); -int usb_get_report(struct usb_device *dev, int ifnum, uint8_t type, uint8_t id, void *buf, int size); -int usb_get_class_descriptor(struct usb_device *dev, int ifnum, uint8_t type, uint8_t id, void *buf, int size); -int usb_clear_halt(struct usb_device *dev, int pipe); -int usb_string(struct usb_device *dev, int index, char *buf, size_t size); -int usb_set_interface(struct usb_device *dev, int interface, int alternate); +extern int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); +extern int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id); +extern struct usb_device *usb_get_dev_index(int index, int bus); +extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, uint8_t request, uint8_t requesttype, + uint16_t value, uint16_t index, void *data, uint16_t size, int timeout); +extern int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout); +extern int usb_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval); +extern void usb_disable_asynch(int disable); +extern int usb_maxpacket(struct usb_device *dev, uint32_t pipe); + +extern int usb_get_configuration_no(struct usb_device *dev, uint8_t *buffer, int cfgno); +extern int usb_get_report(struct usb_device *dev, int ifnum, uint8_t type, uint8_t id, void *buf, int size); +extern int usb_get_class_descriptor(struct usb_device *dev, int ifnum, uint8_t type, uint8_t id, void *buf, int size); +extern int usb_clear_halt(struct usb_device *dev, int pipe); +extern int usb_string(struct usb_device *dev, int index, char *buf, size_t size); +extern int usb_set_interface(struct usb_device *dev, int interface, int alternate); /* * Calling this entity a "pipe" is glorifying it. A USB pipe diff --git a/include/usb_hub.h b/include/usb_hub.h new file mode 100644 index 0000000..f26a3f4 --- /dev/null +++ b/include/usb_hub.h @@ -0,0 +1,10 @@ +#ifndef USB_HUB_H +#define USB_HUB_H + +extern int bus_index; + +extern void usb_hub_reset(int bus_index); +extern int usb_hub_probe(struct usb_device *dev, int ifnum); +extern int hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat); + +#endif // USB_HUB_H diff --git a/pci/ehci-hcd.c b/pci/ehci-hcd.c index d8bd896..eb393c5 100644 --- a/pci/ehci-hcd.c +++ b/pci/ehci-hcd.c @@ -31,8 +31,8 @@ //extern xQueueHandle queue_poll_hub; -#undef DEBUG -#undef SHOW_INFO +//#undef DEBUG +//#undef SHOW_INFO static char ehci_inited; static int rootdev; @@ -112,7 +112,7 @@ static struct descriptor rom_descriptor = { #define ehci_is_TDI() (0) #endif -struct pci_device_id ehci_usb_pci_table[] = +struct pci_device_id ehci_usb_pci_table[] = { { PCI_VENDOR_ID_NEC, @@ -208,7 +208,7 @@ static void cache_qh(struct QH *qh, int flush) qh = (struct QH *)(swpl(qh->qh_link) + gehci.dma_offset); } qh = qh_addr(qh); - + /* Save first qTD pointer, needed for invalidating pass on this QH */ if (flush) { @@ -278,7 +278,7 @@ static int ehci_reset(void) if ((gehci.ent->vendor == PCI_VENDOR_ID_NEC) && (gehci.ent->device == PCI_DEVICE_ID_NEC_USB_2)) { debug("ehci_reset set 48MHz clock\r\n"); - pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator + pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator } cmd = ehci_readl(&gehci.hcor->or_usbcmd); debug("%s cmd: 0x%08x\r\n", __FUNCTION__, cmd); @@ -291,7 +291,7 @@ static int ehci_reset(void) err("EHCI fail to reset"); goto out; } - + if (ehci_is_TDI()) { reg_ptr = (uint32_t *)((u8 *)gehci.hcor + USBMODE); @@ -553,7 +553,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer { dev->act_len = 0; debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\r\n", - dev->devnum, ehci_readl(&gehci.hcor->or_usbsts), + dev->devnum, ehci_readl(&gehci.hcor->or_usbsts), ehci_readl(&gehci.hcor->or_portsc[0]), ehci_readl(&gehci.hcor->or_portsc[1])); } return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; @@ -693,7 +693,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer, case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): memset(tmpbuf, 0, 4); - reg = ehci_readl(status_reg); + reg = ehci_readl(status_reg); if ((reg & EHCI_PS_PR) && (portreset & (1 << swpw(req->index)))) { @@ -705,7 +705,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer, if (!ret) { tmpbuf[0] |= USB_PORT_STAT_RESET; - reg = ehci_readl(status_reg); + reg = ehci_readl(status_reg); } else err("port(%d) reset error", swpw(req->index) - 1); @@ -739,7 +739,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer, } } else - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; + tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; if (reg & EHCI_PS_CSC) tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; @@ -886,7 +886,7 @@ static int hc_interrupt(struct ehci *ehci) } i--; } - } + } ehci_writel(&ehci->hcor->or_usbsts, status); return(1); /* interrupt was from this card */ @@ -950,7 +950,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void ** gehci.ent = ent; } else if (!gehci.handle) /* for restart USB cmd */ - return(-1); + return(-1); gehci.qh_list_unaligned = (struct QH *)driver_mem_alloc(sizeof(struct QH) + 32); if (gehci.qh_list_unaligned == NULL) @@ -983,7 +983,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void ** return(-1); } gehci.td[i] = (struct qTD *)(((uint32_t)gehci.td_unaligned[i] + 31) & ~31); - memset(gehci.td[i], 0, sizeof(struct qTD)); + memset(gehci.td[i], 0, sizeof(struct qTD)); } gehci.descriptor = (struct descriptor *)driver_mem_alloc(sizeof(struct descriptor)); @@ -1118,7 +1118,7 @@ int ehci_usb_lowlevel_stop(void *priv) ehci_writel(&gehci.hcor->or_configflag, 0); /* unblock posted write */ - cmd = ehci_readl(&gehci.hcor->or_usbcmd); + cmd = ehci_readl(&gehci.hcor->or_usbcmd); ehci_reset(); hc_free_buffers(&gehci); ehci_inited = 0; diff --git a/pci/ohci-hcd.c b/pci/ohci-hcd.c index 482c62f..d3f1c8e 100644 --- a/pci/ohci-hcd.c +++ b/pci/ohci-hcd.c @@ -53,22 +53,19 @@ //extern xQueueHandle queue_poll_hub; - -#undef DEBUG_PCIE - #undef OHCI_USE_NPS /* force NoPowerSwitching mode */ #undef OHCI_VERBOSE_DEBUG /* not always helpful */ -#undef DEBUG +#undef DEBUG_OHCI #undef SHOW_INFO #undef OHCI_FILL_TRACE -//#define DEBUG -#ifdef DEBUG -#define debug_printf(format, arg...) do { xprintf("DEBUG: " format "\r\n", ##arg); } while (0) +#define DEBUG_OHCI +#ifdef DEBUG_OHCI +#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #else -#define debug_printf(format, arg...) do { ; } while (0) -#endif /* DEBUG */ +#define dbg(format, arg...) do { ; } while (0) +#endif /* DEBUG_OHCI */ /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE @@ -86,19 +83,18 @@ inline uint32_t readl(volatile uint32_t *addr) { uint32_t res; - //debug_printf("reading from 0x%08x in %s, %d", addr, __FILE__, __LINE__); res = swpl(*addr); - chip_errata_135(); - //debug_printf(" result=0x%08x\r\n", res); + //chip_errata_135(); + //dbg("reading from 0x%08x = 0x%08x\r\n", addr, res); return res; } /* -#define writel(a, b) {debug_printf("writing %08x to %08x\r\n", (a), (b)); *((volatile uint32_t *)(b)) = swpl((volatile uint32_t)(a)); } +#define writel(a, b) {dbg("writing %08x to %08x\r\n", (a), (b)); *((volatile uint32_t *)(b)) = swpl((volatile uint32_t)(a)); } */ inline void writel(uint32_t value, uint32_t *address) { - //debug_printf("writing %08x to %08x in %s, %d\r\n", value, address, __FILE__, __LINE__); + // dbg("writing %08x to %08x\r\n", value, address); * (volatile uint32_t *) address = swpl(value); } #else @@ -152,16 +148,8 @@ struct pci_device_id ohci_usb_pci_table[] = } }; -#define DEBUG -#ifdef DEBUG -#define dbg(format, arg...) do {debug_printf("DEBUG: " format "\r\n", ## arg);} while(0) -#else -#define dbg(format, arg...) do {} while (0) -#endif /* DEBUG */ -#define err(format, arg...) do {debug_printf("ERROR: " format "\r\n", ## arg); }while(0) -#define info(format, arg...) debug_printf("INFO: " format "\r\n", ## arg) - -extern void udelay(long usec); +#define err(format, arg...) do {dbg("ERROR: " format "\r\n", ## arg); }while(0) +#define info(format, arg...) dbg("INFO: " format "\r\n", ## arg) /* global ohci_t */ static ohci_t gohci[2]; @@ -178,7 +166,7 @@ static int hc_interrupt(ohci_t *ohci); static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval); - + static struct td *ptd; @@ -231,17 +219,17 @@ static void urb_free_priv(urb_priv_t *urb) /*-------------------------------------------------------------------------*/ -#ifdef DEBUG +#ifdef DEBUG_OHCI static int sohci_get_current_frame_number(ohci_t *ohci, struct usb_device *dev); /* debug| print the main components of an URB * small: 0) header + data packets 1) just header */ static void pkt_print(ohci_t *ohci, urb_priv_t *purb, struct usb_device *dev, - uint32_t pipe, void *buffer, int transfer_len, - struct devrequest *setup, char *str, int small) + uint32_t pipe, void *buffer, int transfer_len, + struct devrequest *setup, char *str, int small) { - dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx", + dbg("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx\r\n", str, sohci_get_current_frame_number(ohci, dev), usb_pipedevice(pipe), @@ -257,30 +245,32 @@ static void pkt_print(ohci_t *ohci, urb_priv_t *purb, struct usb_device *dev, { int i; int len; - + if (usb_pipecontrol(pipe)) { - debug_printf(__FILE__ ": cmd(8):"); + dbg(__FILE__ ": cmd(8):"); for (i = 0; i < 8 ; i++) - debug_printf(" %02x", ((uint8_t *)setup)[i]); - debug_printf("\r\n"); + dbg(" %02x", ((uint8_t *)setup)[i]); + dbg("\r\n"); } if (transfer_len > 0 && buffer) { - debug_printf(__FILE__ ": data(%d/%d):", (purb ? purb->actual_length : 0), transfer_len); + dbg(__FILE__ ": data(%d/%d):", (purb ? purb->actual_length : 0), transfer_len); len = usb_pipeout(pipe)? transfer_len : (purb ? purb->actual_length : 0); for (i = 0; i < 16 && i < len; i++) - debug_printf(" %02x", ((uint8_t *)buffer)[i]); - debug_printf("%s\r\n", i < len? "...": ""); + dbg(" %02x", ((uint8_t *)buffer)[i]); + dbg("%s\r\n", i < len? "...": ""); } } #endif } -/* just for debugging; prints non-empty branches of the int ed tree - * inclusive iso eds */ +/* + * just for debugging; prints non-empty branches of the int ed tree + * inclusive iso eds + */ static void ep_print_int_eds(ohci_t *ohci, char *str) { int i, j; @@ -293,20 +283,20 @@ static void ep_print_int_eds(ohci_t *ohci, char *str) if (*ed_p == 0) continue; - debug_printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); + dbg(__FILE__ ": %s branch int %2d(%2x):", str, i, i); while (*ed_p != 0 && j--) { ed_t *ed = (ed_t *)swpl((uint32_t)ed_p); - debug_printf(" ed: %4x;", ed->hwINFO); + dbg(" ed: %4x;", ed->hwINFO); ed_p = &ed->hwNextED; } - debug_printf("\r\n"); + dbg("\r\n"); } } static void ohci_dump_intr_mask(char *label, uint32_t mask) { - dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + dbg("%s: 0x%08x%s%s%s%s%s%s%s%s%s\r\n", label, mask, (mask & OHCI_INTR_MIE) ? " MIE" : "", @@ -323,7 +313,7 @@ static void ohci_dump_intr_mask(char *label, uint32_t mask) static void maybe_print_eds(ohci_t *controller, char *label, uint32_t value) { - ed_t *edp; + ed_t *edp; value += controller->dma_offset; edp = (ed_t *) value; @@ -331,15 +321,15 @@ static void maybe_print_eds(ohci_t *controller, char *label, uint32_t value) if (value && (value < 0xDFFFF0)) /* STRAM */ { - dbg("%s %08x", label, value); - dbg("%08x", edp->hwINFO); - dbg("%08x", edp->hwTailP); - dbg("%08x", edp->hwHeadP); - dbg("%08x", edp->hwNextED); + dbg("%s %08x\r\n", label, value); + dbg("%08x\r\n", edp->hwINFO); + dbg("%08x\r\n", edp->hwTailP); + dbg("%08x\r\n", edp->hwHeadP); + dbg("%08x\r\n", edp->hwNextED); } } -#ifdef DEBUG +#ifdef DEBUG_OHCI static char *hcfs2string(int state) { switch (state) @@ -356,12 +346,14 @@ static char *hcfs2string(int state) /* dump control and status registers */ static void ohci_dump_status(ohci_t *controller) { - struct ohci_regs *regs = controller->regs; - uint32_t temp = readl(®s->revision) & 0xff; + struct ohci_regs *regs = controller->regs; + uint32_t temp = readl(®s->revision) & 0xff; + if (temp != 0x10) - dbg("spec %d.%d", (temp >> 4), (temp & 0x0f)); + dbg("spec %d.%d\r\n", (temp >> 4), (temp & 0x0f)); + temp = readl(®s->control); - dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + dbg("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\r\n", temp, (temp & OHCI_CTRL_RWE) ? " RWE" : "", (temp & OHCI_CTRL_RWC) ? " RWC" : "", (temp & OHCI_CTRL_IR) ? " IR" : "", @@ -372,8 +364,9 @@ static void ohci_dump_status(ohci_t *controller) (temp & OHCI_CTRL_PLE) ? " PLE" : "", temp & OHCI_CTRL_CBSR ); + temp = readl(®s->cmdstatus); - dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + dbg("cmdstatus: 0x%08x SOC=%d%s%s%s%s\r\n", temp, (temp & OHCI_SOC) >> 16, (temp & OHCI_OCR) ? " OCR" : "", (temp & OHCI_BLF) ? " BLF" : "", @@ -403,7 +396,7 @@ static void ohci_dump_roothub(ohci_t *controller, int verbose) ndp = controller->ndp; if (verbose) { - dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + dbg("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d\r\n", temp, ((temp & RH_A_POTPGT) >> 24) & 0xff, (temp & RH_A_NOCP) ? " NOCP" : "", (temp & RH_A_OCPM) ? " OCPM" : "", @@ -413,13 +406,13 @@ static void ohci_dump_roothub(ohci_t *controller, int verbose) ndp ); temp = roothub_b(controller); - dbg("roothub.b: %08x PPCM=%04x DR=%04x", + dbg("roothub.b: %08x PPCM=%04x DR=%04x\r\n", temp, (temp & RH_B_PPCM) >> 16, (temp & RH_B_DR) ); temp = roothub_status(controller); - dbg("roothub.status: %08x%s%s%s%s%s%s", + dbg("roothub.status: %08x%s%s%s%s%s%s\r\n", temp, (temp & RH_HS_CRWE) ? " CRWE" : "", (temp & RH_HS_OCIC) ? " OCIC" : "", @@ -433,7 +426,7 @@ static void ohci_dump_roothub(ohci_t *controller, int verbose) for (i = 0; i < ndp; i++) { temp = roothub_portstatus(controller, i); - dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + dbg("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\r\n", i, temp, (temp & RH_PS_PRSC) ? " PRSC" : "", @@ -456,15 +449,15 @@ static void ohci_dump_roothub(ohci_t *controller, int verbose) static void ohci_dump(ohci_t *ohci, int verbose) { - dbg("OHCI controller usb-%s-%c state", ohci->slot_name, (char)ohci->controller + '0'); + dbg("OHCI controller usb-%s-%c state\r\n", ohci->slot_name, (char)ohci->controller + '0'); /* dumps some of the state we know about */ ohci_dump_status(ohci); if (verbose) ep_print_int_eds(ohci, "hcca"); - dbg("hcca frame #%04x", ohci->hcca->frame_no); + dbg("hcca frame #%04x\r\n", ohci->hcca->frame_no); ohci_dump_roothub(ohci, 1); } -#endif /* DEBUG */ +#endif /* DEBUG_OHCI */ /*-------------------------------------------------------------------------* * Interface functions (URB) @@ -574,7 +567,7 @@ static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb) { writel(OHCI_INTR_WDH, ®s->intrenable); readl(®s->intrenable); /* PCI posting flush */ - /* call interrupt device routine */ + /* call interrupt device routine */ // dbg("irq_handle device %d", urb->dev->devnum); urb->dev->irq_handle(urb->dev); writel(OHCI_INTR_WDH, ®s->intrdisable); @@ -596,7 +589,7 @@ static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb) /*-------------------------------------------------------------------------*/ -#ifdef DEBUG +#ifdef DEBUG_OHCI /* tell us the current USB frame number */ static int sohci_get_current_frame_number(ohci_t *ohci, struct usb_device *usb_dev) @@ -677,13 +670,13 @@ static int ep_link(ohci_t *ohci, ed_t *edi) ed->state = ED_OPER; ed->int_interval = 0; switch (ed->type) - { + { case PIPE_CONTROL: ed->hwNextED = 0; if (ohci->ed_controltail == NULL) writel((uint32_t) ed - ohci->dma_offset, &ohci->regs->ed_controlhead); else - ohci->ed_controltail->hwNextED = swpl((uint32_t)ed - ohci->dma_offset); + ohci->ed_controltail->hwNextED = swpl((uint32_t)ed - ohci->dma_offset); ed->ed_prev = ohci->ed_controltail; if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && !ohci->ed_rm_list[1] && !ohci->sleeping) @@ -699,7 +692,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi) if (ohci->ed_bulktail == NULL) writel((uint32_t) ed - ohci->dma_offset, &ohci->regs->ed_bulkhead); else - ohci->ed_bulktail->hwNextED = swpl((uint32_t)ed - ohci->dma_offset); + ohci->ed_bulktail->hwNextED = swpl((uint32_t)ed - ohci->dma_offset); ed->ed_prev = ohci->ed_bulktail; if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && !ohci->ed_rm_list[1] && !ohci->sleeping) { @@ -707,7 +700,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi) writel(ohci->hc_control, &ohci->regs->control); } ohci->ed_bulktail = edi; - break; + break; case PIPE_INTERRUPT: load = ed->int_load; @@ -896,8 +889,8 @@ static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len, if (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { for (i = 0; i < len; i++) - debug_printf("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]); - debug_printf("\r\n"); + dbg("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]); + dbg("\r\n"); } #endif if (!len) @@ -921,14 +914,14 @@ static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len, if (data) { int i; - debug_printf("td_fill: %08x %08x %08X %08X at 0x%08X\r\n", + dbg("td_fill: %08x %08x %08X %08X at 0x%08X\r\n", swpl(td->hwINFO), swpl(td->hwCBP), swpl(td->hwNextTD), swpl(td->hwBE), td); for (i = 0; i < len; i++) - debug_printf("%02X ", *(unsigned char *)(data + i) & 0xff); - debug_printf("\r\n"); + dbg("%02X ", *(unsigned char *)(data + i) & 0xff); + dbg("\r\n"); } else - debug_printf("td_fill: %08x %08x %08X %08X at 0x%08X\r\n", + dbg("td_fill: %08x %08x %08X %08X at 0x%08X\r\n", swpl(td->hwINFO), swpl(td->hwCBP), swpl(td->hwNextTD), swpl(td->hwBE), td); #endif } @@ -991,7 +984,7 @@ static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, td_fill(ohci, info, data, data_len, dev, cnt++, urb); } /* Status phase */ - info = usb_pipeout(pipe) ? TD_CC | TD_DP_IN | TD_T_DATA1 : TD_CC | TD_DP_OUT | TD_T_DATA1; + info = usb_pipeout(pipe) ? TD_CC | TD_DP_IN | TD_T_DATA1 : TD_CC | TD_DP_OUT | TD_T_DATA1; td_fill(ohci, info, data, 0, dev, cnt++, urb); if (!ohci->sleeping) /* start Control list */ writel(OHCI_CLF, &ohci->regs->cmdstatus); @@ -1049,7 +1042,7 @@ static void check_status(ohci_t *ohci, td_t *td_list) if (cc) { - err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc); + //err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc); if (*phwHeadP & swpl(0x1)) { if (lurb_priv && ((td_list->index + 1) < urb_len)) @@ -1130,7 +1123,7 @@ static int takeback_td(ohci_t *ohci, td_t *td_list) cc = TD_CC_GET(tdINFO); if (cc) { - err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc); + //err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc); stat = cc_to_error[cc]; } @@ -1273,7 +1266,7 @@ static unsigned char root_hub_str_index1[] = /*-------------------------------------------------------------------------*/ #define OK(x) len = (x); break -#ifdef DEBUG +#ifdef DEBUG_OHCI #define WR_RH_STAT(x) { info("WR:status %#8x", (x)); writel((x), &ohci->regs->roothub.status); } #define WR_RH_PORTSTAT(x) { info("WR:portstatus[%d] %#8x", wIndex-1, (x)); writel((x), &ohci->regs->roothub.portstatus[wIndex-1]); } #else @@ -1325,7 +1318,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip uint16_t wIndex; uint16_t wLength; -#ifdef DEBUG +#ifdef DEBUG_OHCI pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); #else if (ohci->irq) @@ -1479,7 +1472,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip dbg("unsupported root hub command"); stat = USB_ST_STALLED; } -#ifdef DEBUG +#ifdef DEBUG_OHCI ohci_dump_roothub(ohci, 1); #else if (ohci->irq) @@ -1490,7 +1483,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip memcpy(data, data_buf, len); dev->act_len = len; dev->status = stat; -#ifdef DEBUG +#ifdef DEBUG_OHCI pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); #else if (ohci->irq) @@ -1529,7 +1522,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe dev->status = USB_ST_CRC_ERR; return 0; } -#ifdef DEBUG +#ifdef DEBUG_OHCI urb->actual_length = 0; pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); #else @@ -1609,7 +1602,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe } dev->status = stat; dev->act_len = transfer_len; -#ifdef DEBUG +#ifdef DEBUG_OHCI pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); #else if (ohci->irq) @@ -1633,7 +1626,7 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer, ohci_t *ohci = (ohci_t *)dev->priv_hcd; int maxsize = usb_maxpacket(dev, pipe); info("submit_control_msg dev 0x%p ohci 0x%p", dev, ohci); -#ifdef DEBUG +#ifdef DEBUG_OHCI pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); #else if (ohci->irq) @@ -1672,21 +1665,23 @@ static int hc_reset(ohci_t *ohci) int timeout = 30; int smm_timeout = 50; /* 0,5 sec */ - dbg("%s\r\n", __FUNCTION__); - if ((ohci->ent->vendor == PCI_VENDOR_ID_PHILIPS) && (ohci->ent->device == PCI_DEVICE_ID_PHILIPS_ISP1561)) { #define EHCI_USBCMD_OFF 0x20 #define EHCI_USBCMD_HCRESET (1 << 1) - /* Some multi-function controllers (e.g. ISP1562) allow root hub - resetting via EHCI registers only. */ + + /* + * Some multi-function controllers (e.g. ISP1562) allow root hub + * resetting via EHCI registers only. + */ short index = 0; long handle; do { handle = pci_find_device(0x0, 0xffff, index++); + if (handle >= 0) { uint32_t id = 0; @@ -1720,7 +1715,7 @@ static int hc_reset(ohci_t *ohci) } } flags = pci_rsc_desc->flags; - pci_rsc_desc = (struct pci_rd *) ((uint32_t)pci_rsc_desc->next + (uint32_t)pci_rsc_desc); + pci_rsc_desc = (struct pci_rd *) ((uint32_t) pci_rsc_desc->next + (uint32_t) pci_rsc_desc); } while (!(flags & FLG_LAST)); } @@ -1732,20 +1727,23 @@ static int hc_reset(ohci_t *ohci) if ((ohci->controller == 0) && (ohci->ent->vendor == PCI_VENDOR_ID_NEC) && (ohci->ent->device == PCI_DEVICE_ID_NEC_USB)) { - if (ohci->handle == 1) /* NEC on motherboard has FPGA clock */ + //if (ohci->handle == 1) /* NEC on motherboard has FPGA clock */ +#if defined(MACHINE_FIREBEE) { dbg("USB OHCI set 48MHz clock\r\n"); - pci_write_config_longword(ohci->handle, 0xE4, 0x21); // oscillator & disable ehci + pci_write_config_longword(ohci->handle, 0xE4, 0x21); // oscillator & disable ehci wait(10); } - else + //else +#else { - pci_write_config_longword(ohci->handle, 0xE4, pci_read_config_longword(ohci->handle, 0xE4) | 0x01); // disable ehci + pci_write_config_longword(ohci->handle, 0xE4, pci_read_config_longword(ohci->handle, 0xE4) | 0x01); // disable ehci wait(10); } +#endif } - debug_printf("control: %x\r\n", readl(&ohci->regs->control)); + dbg("control: %x\r\n", readl(&ohci->regs->control)); if (readl(&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ @@ -1765,11 +1763,14 @@ static int hc_reset(ohci_t *ohci) /* Disable HC interrupts */ writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); ohci_dump_status(ohci); - dbg("USB OHCI HC reset_hc usb-%s-%c: ctrl = 0x%X", ohci->slot_name, (char)ohci->controller + '0', readl(&ohci->regs->control)); + dbg("USB OHCI HC reset_hc usb-%s-%c: ctrl = 0x%X\r\n", ohci->slot_name, + (char) ohci->controller + '0', readl(&ohci->regs->control)); + /* Reset USB (needed by some controllers) */ ohci->hc_control = 0; writel(ohci->hc_control, &ohci->regs->control); wait(50); + /* HC Reset requires max 10 us delay */ writel(OHCI_HCR, &ohci->regs->cmdstatus); while ((readl(&ohci->regs->cmdstatus) & OHCI_HCR) != 0) @@ -1777,7 +1778,7 @@ static int hc_reset(ohci_t *ohci) if (--timeout == 0) { err("USB HC reset timed out!"); - ohci_dump_status(ohci); + ohci_dump_status(ohci); return -1; } wait(10); @@ -1911,7 +1912,7 @@ static int hc_interrupt(ohci_t *ohci) { portBASE_TYPE xNeedSwitch = pdFALSE; xNeedSwitch = xQueueSendFromISR(queue_poll_hub, &ohci->usbnum, xNeedSwitch); - } /* to fix xNeedSwitch usage */ + } /* to fix xNeedSwitch usage */ } #endif /* USB_POLL_HUB */ stat = 0xff; @@ -1927,7 +1928,7 @@ static int hc_interrupt(ohci_t *ohci) status & 0x8000 ? ", Parity error" : "", status & 0x4000 ? ", Signaled system error" : "", status & 0x2000 ? ", Received master abort" : "", status & 0x1000 ? ", Received target abort" : "", status & 0x800 ? ", Signaled target abort" : "", status & 0x100 ? ", Data parity error" : ""); ohci->disabled++; -#ifdef DEBUG +#ifdef DEBUG_OHCI ohci_dump(ohci, 1); #else if (ohci->irq) @@ -2053,11 +2054,12 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void ohci->ent = ent; } else if (!ohci->handle) /* for restart USB cmd */ - return(-1); + return(-1); info("ohci %p", ohci); - ohci->controller = (ohci->handle >> 16) & 3; /* PCI function */ + ohci->controller = PCI_FUNCTION_FROM_HANDLE(ohci->handle); + // ohci->controller = (ohci->handle >> 16) & 3; /* PCI function */ /* this must be aligned to a 256 byte boundary */ ohci->hcca_unaligned = (struct ohci_hcca *) driver_mem_alloc(sizeof(struct ohci_hcca) + 256); @@ -2089,10 +2091,10 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void hc_free_buffers(ohci); return(-1); } - + ptd = (struct td *) (((uint32_t) ohci->td_unaligned + 7) & ~7); - debug_printf("memset from %p to %p\r\n", ptd, ptd + sizeof(td_t) * NUM_TD); + dbg("memset from %p to %p\r\n", ptd, ptd + sizeof(td_t) * NUM_TD); memset(ptd, 0, sizeof(td_t) * NUM_TD); info("aligned TDs %p", ptd); @@ -2105,7 +2107,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void unsigned short flags; do { - debug_printf("\r\nPCI USB descriptors (at %p): flags 0x%04x start 0x%08lx \r\n offset 0x%08lx dmaoffset 0x%08lx length 0x%08lx\r\n", pci_rsc_desc, + dbg("\r\nPCI USB descriptors (at %p): flags 0x%04x start 0x%08lx \r\n offset 0x%08lx dmaoffset 0x%08lx length 0x%08lx\r\n", pci_rsc_desc, pci_rsc_desc->flags, pci_rsc_desc->start, pci_rsc_desc->offset, pci_rsc_desc->dmaoffset, pci_rsc_desc->length); if (!(pci_rsc_desc->flags & FLG_IO)) { @@ -2131,7 +2133,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void else { hc_free_buffers(ohci); - debug_printf("pci_get_resource() failed in %s %s\r\n", __FILE__, __LINE__); + dbg("pci_get_resource() failed in %s %s\r\n", __FILE__, __LINE__); return(-1); /* get_resource error */ } @@ -2153,7 +2155,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void } } - debug_printf("OHCI usb-%s-%c, regs address 0x%08X, PCI handle 0x%X\r\n", ohci->slot_name, (char)ohci->controller + '0', ohci->regs, handle); + dbg("OHCI usb-%s-%c, regs address 0x%08X, PCI handle 0x%X\r\n", ohci->slot_name, (char)ohci->controller + '0', ohci->regs, handle); if (hc_reset(ohci) < 0) { err("Can't reset OHCI usb-%s-%c", ohci->slot_name, (char)ohci->controller + '0'); @@ -2171,7 +2173,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void return(-1); } -#ifdef DEBUG +#ifdef DEBUG_OHCI ohci_dump(ohci, 1); #endif pci_hook_interrupt(handle, handle_usb_interrupt, ohci); diff --git a/sys/driver_mem.c b/sys/driver_mem.c index 0b917b8..7c81d5d 100644 --- a/sys/driver_mem.c +++ b/sys/driver_mem.c @@ -28,7 +28,7 @@ #error "unknown machine!" #endif -//#define DBG_DM +#define DBG_DM #ifdef DBG_DM #define dbg(fmt, args...) xprintf(fmt, ##args) diff --git a/usb/usb.c b/usb/usb.c index f5edef5..d7c19e8 100644 --- a/usb/usb.c +++ b/usb/usb.c @@ -52,6 +52,7 @@ #include "wait.h" #include #include "usb.h" +#include "usb_hub.h" extern int usb_stor_curr_dev; extern uint32_t usb_1st_disk_drive; @@ -63,9 +64,6 @@ extern uint32_t usb_1st_disk_drive; #define dbg(format, arg...) do { ; } while (0) #endif /* DEBUG_USB */ - -#define USB_BUFSIZ 512 - struct hci { /* ------- common part -------- */ @@ -76,7 +74,7 @@ struct hci }; static struct usb_device *usb_dev; -static int bus_index; +int bus_index; static int dev_index[USB_MAX_BUS]; static struct hci *controller_priv[USB_MAX_BUS]; static int asynch_allowed; @@ -84,33 +82,20 @@ static struct devrequest *setup_packet; char usb_started; /* flag for the started/stopped USB status */ -typedef struct -{ - int dest; - void (*func)(char); - char *loc; -} PRINTK_INFO; - #define DEST_CONSOLE (1) #define DEST_STRING (2) -/********************************************************************** +/* * some forward declerations... */ void usb_scan_devices(void *priv); -int usb_hub_probe(struct usb_device *dev, int ifnum); -void usb_hub_reset(int index_bus); -static int hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat); - -extern int printk(PRINTK_INFO *info, const char *fmt, va_list ap); - -/*************************************************************************** - * Init USB Device +/* + * Init USB device controller */ int usb_init(int32_t handle, const struct pci_device_id *ent) { - void *priv; + struct hci *priv; int res = 0; if (bus_index >= USB_MAX_BUS) return -1; @@ -154,41 +139,48 @@ int usb_init(int32_t handle, const struct pci_device_id *ent) usb_hub_reset(bus_index); /* init low_level USB */ - dbg("USB: "); switch(ent->class) { case PCI_CLASS_SERIAL_USB_UHCI: //res = uhci_usb_lowlevel_init(handle, ent, &priv); - dbg("sorry, no uhci driver available\r\n"); + dbg("sorry, no uhci driver available\r\n"); break; + case PCI_CLASS_SERIAL_USB_OHCI: - dbg("initialize ohci interface\r\n"); - res = ohci_usb_lowlevel_init(handle, ent, &priv); + dbg("initialize ohci host controller interface\r\n"); + res = ohci_usb_lowlevel_init(handle, ent, (void *) &priv); break; + case PCI_CLASS_SERIAL_USB_EHCI: - dbg("initialize ehci interface\r\n"); - res = ehci_usb_lowlevel_init(handle, ent, &priv); + dbg("initialize ehci host controller interface\r\n"); + res = ehci_usb_lowlevel_init(handle, ent, (void *) &priv); + break; + + default: + res = -1; break; - default: res = -1; break; } if (!res) { - /* if lowlevel init is OK, scan the bus for devices - * i.e. search HUBs and configure them */ - if (setup_packet == NULL) - setup_packet = (void *) driver_mem_alloc(sizeof(struct devrequest)); - + /* + * if lowlevel init is OK, scan the bus for devices + * i.e. search HUBs and configure them + */ if (setup_packet == NULL) { - usb_started = 0; - return -1; /* out of memoy */ + setup_packet = driver_mem_alloc(sizeof(struct devrequest)); + if (setup_packet == NULL) + { + usb_started = 0; + return -1; /* no memory, no USB */ + } } xprintf("Scanning bus for devices... "); - controller_priv[bus_index] = (struct hci *) priv; + controller_priv[bus_index] = priv; controller_priv[bus_index]->usbnum = bus_index; usb_scan_devices(priv); @@ -296,9 +288,9 @@ int usb_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int * and the current status are stored in the dev->act_len and dev->status. */ int usb_control_msg(struct usb_device *dev, unsigned int pipe, - unsigned char request, unsigned char requesttype, - unsigned short value, unsigned short index, - void *data, unsigned short size, int timeout) + unsigned char request, unsigned char requesttype, + unsigned short value, unsigned short index, + void *data, unsigned short size, int timeout) { struct hci *priv = (struct hci *)dev->priv_hcd; @@ -315,7 +307,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, setup_packet->index = swpw(index); setup_packet->length = swpw(size); - dbg("usb_control_msg: request: 0x%X, requesttype: 0x%X, value 0x%X index 0x%X length 0x%X\r\n", request, requesttype, value, index, size); + dbg("usb_control_msg: request: 0x%X, requesttype: 0x%X, value 0x%X index 0x%X length 0x%X\r\n", request, requesttype, value, index, size); switch(priv->ent->class) { @@ -323,6 +315,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, dev->status = USB_ST_NOT_PROC; /* not yet processed */ ohci_submit_control_msg(dev, pipe, data, size, setup_packet); break; + case PCI_CLASS_SERIAL_USB_EHCI: dev->status = USB_ST_NOT_PROC; /* not yet processed */ ehci_submit_control_msg(dev, pipe, data, size, setup_packet); @@ -332,7 +325,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, } if (timeout == 0) - return (int) size; + return (int) size; if (dev->status != 0) { @@ -340,7 +333,6 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, * Let's wait a while for the timeout to elapse. * It has no real use, but it keeps the interface happy. */ - wait(timeout); return -1; } return dev->act_len; @@ -381,7 +373,7 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, void *data, int len, *actual_length = dev->act_len; - if (dev->status == 0) + if (dev->status == 0) return 0; else return -1; @@ -427,7 +419,7 @@ static void usb_set_maxpacket_ep(struct usb_device *dev, struct usb_endpoint_des /* Control => bidirectional */ dev->epmaxpacketout[b] = ep->wMaxPacketSize; dev->epmaxpacketin[b] = ep->wMaxPacketSize; - dbg("##Control EP epmaxpacketout/in[%d] = %d\r\n", b, dev->epmaxpacketin[b]); + dbg("##Control EP epmaxpacketout/in[%d] = %d\r\n", b, dev->epmaxpacketin[b]); } else { @@ -437,7 +429,7 @@ static void usb_set_maxpacket_ep(struct usb_device *dev, struct usb_endpoint_des if (ep->wMaxPacketSize > dev->epmaxpacketout[b]) { dev->epmaxpacketout[b] = ep->wMaxPacketSize; - dbg("##EP epmaxpacketout[%d] = %d\r\n", b, dev->epmaxpacketout[b]); + dbg("##EP epmaxpacketout[%d] = %d\r\n", b, dev->epmaxpacketout[b]); } } else @@ -446,7 +438,7 @@ static void usb_set_maxpacket_ep(struct usb_device *dev, struct usb_endpoint_des if (ep->wMaxPacketSize > dev->epmaxpacketin[b]) { dev->epmaxpacketin[b] = ep->wMaxPacketSize; - dbg("##EP epmaxpacketin[%d] = %d\r\n", b, dev->epmaxpacketin[b]); + dbg("##EP epmaxpacketin[%d] = %d\r\n", b, dev->epmaxpacketin[b]); } } /* if out */ } /* if control */ @@ -457,8 +449,8 @@ static void usb_set_maxpacket_ep(struct usb_device *dev, struct usb_endpoint_des */ int usb_set_maxpacket(struct usb_device *dev) { - int i; - int ii; + int i; + int ii; for (i = 0; i < dev->config.bNumInterfaces; i++) for (ii = 0; ii < dev->config.if_desc[i].bNumEndpoints; ii++) @@ -473,20 +465,20 @@ int usb_set_maxpacket(struct usb_device *dev) int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) { struct usb_descriptor_header *head; - int index; - int ifno; - int epno; - int curr_if_num; + int index; + int ifno; + int epno; + int curr_if_num; ifno = -1; epno = -1; curr_if_num = -1; dev->configno = cfgno; - head = (struct usb_descriptor_header *) &buffer[0]; + head = (struct usb_descriptor_header *) &buffer[0]; if (head->bDescriptorType != USB_DT_CONFIG) { - dbg(" ERROR: NOT USB_CONFIG_DESC %x\r\n", head->bDescriptorType); + dbg(" ERROR: NOT USB_CONFIG_DESC %x\r\n", head->bDescriptorType); return -1; } memcpy(&dev->config, buffer, buffer[0]); @@ -498,12 +490,12 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) * now process the others */ head = (struct usb_descriptor_header *) &buffer[index]; - while (index + 1 < dev->config.wTotalLength) + while (index + 1 < dev->config.wTotalLength) { switch (head->bDescriptorType) { case USB_DT_INTERFACE: - if (((struct usb_interface_descriptor *) &buffer[index])->bInterfaceNumber != curr_if_num) + if (((struct usb_interface_descriptor *) &buffer[index])->bInterfaceNumber != curr_if_num) { /* this is a new interface, copy new desc */ ifno = dev->config.no_of_if; @@ -526,13 +518,13 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) dev->config.if_desc[ifno].no_of_ep++; memcpy(&dev->config.if_desc[ifno].ep_desc[epno], &buffer[index], buffer[index]); dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize = swpw(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize); - dbg("if %d, ep %d\r\n", ifno, epno); + dbg("if %d, ep %d\r\n", ifno, epno); break; default: if (head->bLength == 0) return 1; - dbg("unknown Description Type : %x\r\n", head->bDescriptorType); + dbg("unknown Description Type : %x\r\n", head->bDescriptorType); #ifdef USB_DEBUG { unsigned char *ch; @@ -540,8 +532,8 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno) ch = (unsigned char *)head; for (i = 0; i < head->bLength; i++) - dbg(" %02X", *ch++); - dbg("\r\n"); + dbg(" %02X", *ch++); + dbg("\r\n"); } #endif /* USB_DEBUG */ break; @@ -602,15 +594,15 @@ int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer, int unsigned int tmp; struct usb_config_descriptor *config; - config = (struct usb_config_descriptor *) &buffer[0]; + config = (struct usb_config_descriptor *) &buffer[0]; result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9); if (result < 9) { if (result < 0) - dbg("unable to get descriptor, error %lX\r\n", dev->status); + dbg("unable to get descriptor, error %lX\r\n", dev->status); else - dbg("config descriptor too short (expected %i, got %i)\n", 9, result); + dbg("config descriptor too short (expected %i, got %i)\n", 9, result); return -1; } @@ -618,11 +610,11 @@ int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer, int if (tmp > USB_BUFSIZ) { - dbg("usb_get_configuration_no: failed to get descriptor - too long: %d\r\n", tmp); + dbg("usb_get_configuration_no: failed to get descriptor - too long: %d\r\n", tmp); return -1; } result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp); - dbg("get_conf_no %d Result %d, wLength %d\r\n", cfgno, result, tmp); + dbg("get_conf_no %d Result %d, wLength %d\r\n", cfgno, result, tmp); return result; } @@ -635,7 +627,7 @@ int usb_set_address(struct usb_device *dev) { int res; - dbg("set address %d\r\n", dev->devnum); + dbg("set address %d\r\n", dev->devnum); res = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, 0, (dev->devnum), 0, NULL, 0, USB_CNTL_TIMEOUT); return res; } @@ -659,7 +651,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) if (!if_face) { - dbg("selecting invalid interface %d", interface); + dbg("selecting invalid interface %d", interface); return -1; } @@ -688,7 +680,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) { int res; - dbg("set configuration %d\r\n", configuration); + dbg("set configuration %d\r\n", configuration); /* set setup command */ res = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, USB_CNTL_TIMEOUT); @@ -707,9 +699,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration) */ int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol) { - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT); + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT); } /* @@ -717,9 +709,9 @@ int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol) */ int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id) { - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT); + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT); } /* @@ -728,9 +720,9 @@ int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id) int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); } /* @@ -739,9 +731,9 @@ int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, int usb_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size) { - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, - (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, + (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT); } /* @@ -755,8 +747,8 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char for (i = 0; i < 3; ++i) { /* some devices are flaky */ - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, - (USB_DT_STRING << 8) + index, langid, buf, size, USB_CNTL_TIMEOUT); + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, buf, size, USB_CNTL_TIMEOUT); if (result > 0) break; } @@ -765,8 +757,8 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char static void usb_try_string_workarounds(unsigned char *buf, int *length) { - int newlength; - int oldlength = *length; + int newlength; + int oldlength = *length; for (newlength = 2; newlength + 1 < oldlength; newlength += 2) { @@ -831,11 +823,11 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) return -1; buf[0] = 0; - tbuf = (unsigned char *) driver_mem_alloc(USB_BUFSIZ); + tbuf = (unsigned char *) driver_mem_alloc(USB_BUFSIZ); if (tbuf == NULL) { - dbg("usb_string: malloc failure\r\n"); + dbg("usb_string: malloc failure\r\n"); return -1; } @@ -845,13 +837,13 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) err = usb_string_sub(dev, 0, 0, tbuf); if (err < 0) { - dbg("error getting string descriptor 0 (error=%lx)\r\n", dev->status); + dbg("error getting string descriptor 0 (error=%lx)\r\n", dev->status); driver_mem_free(tbuf); return -1; } else if (tbuf[0] < 4) { - dbg("string descriptor 0 too short\r\n"); + dbg("string descriptor 0 too short\r\n"); driver_mem_free(tbuf); return -1; } @@ -860,7 +852,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) dev->have_langid = -1; dev->string_langid = tbuf[2] | (tbuf[3] << 8); /* always use the first langid listed */ - dbg("USB device number %d default language ID 0x%x\r\n", dev->devnum, dev->string_langid); + dbg("USB device number %d default language ID 0x%x\r\n", dev->devnum, dev->string_langid); } } err = usb_string_sub(dev, dev->string_langid, index, tbuf); @@ -900,8 +892,8 @@ void usb_disconnect(struct usb_device **pdev) if (dev != NULL) { int i; - dbg("USB %d disconnect on device %d\r\n", dev->parent->usbnum, dev->parent->devnum); - dbg("USB %d disconnected, device number %d\r\n", dev->usbnum, dev->devnum); + dbg("USB %d disconnect on device %d\r\n", dev->parent->usbnum, dev->parent->devnum); + dbg("USB %d disconnected, device number %d\r\n", dev->usbnum, dev->devnum); if (dev->deregister != NULL) dev->deregister(dev); /* Free up all the children.. */ @@ -909,7 +901,7 @@ void usb_disconnect(struct usb_device **pdev) { if (dev->children[i] != NULL) { - dbg("USB %d, disconnect children %d\r\n", dev->usbnum, dev->children[i]->devnum); + dbg("USB %d, disconnect children %d\r\n", dev->usbnum, dev->children[i]->devnum); usb_disconnect(&dev->children[i]); dev->children[i] = NULL; } @@ -932,8 +924,8 @@ void usb_disconnect(struct usb_device **pdev) struct usb_device *usb_get_dev_index(int index, int index_bus) { struct usb_device *dev; - if ((index_bus >= USB_MAX_BUS) || (index_bus < 0) - || (index >= USB_MAX_DEVICE) || (index < 0)) + if ((index_bus >= USB_MAX_BUS) || (index_bus < 0) + || (index >= USB_MAX_DEVICE) || (index < 0)) return NULL; dev = &usb_dev[(index_bus * USB_MAX_DEVICE) + index]; if ((controller_priv[index_bus] == NULL) || (dev->devnum == -1)) @@ -947,22 +939,22 @@ struct usb_device *usb_get_dev_index(int index, int index_bus) */ struct usb_device *usb_alloc_new_device(int bus_index, void *priv) { - int i; - int index = dev_index[bus_index]; + int i; + int index = dev_index[bus_index]; struct usb_device *dev; - dbg("USB %d new device %d\r\n", bus_index, index); + dbg("USB %d new device %d\r\n", bus_index, index); if (index >= USB_MAX_DEVICE) { - dbg("ERROR, too many USB Devices, max=%d\r\n", USB_MAX_DEVICE); + dbg("ERROR, too many USB Devices, max=%d\r\n", USB_MAX_DEVICE); return NULL; } /* default Address is 0, real addresses start with 1 */ dev = &usb_dev[(bus_index * USB_MAX_DEVICE) + index]; dev->devnum = index + 1; dev->maxchild = 0; - for (i = 0; i < USB_MAXCHILDREN; dev->children[i++] = NULL) - ; + for (i = 0; i < USB_MAXCHILDREN; dev->children[i++] = NULL) + ; dev->parent = NULL; dev->priv_hcd = priv; @@ -972,7 +964,7 @@ struct usb_device *usb_alloc_new_device(int bus_index, void *priv) return dev; } -#define CONFIG_LEGACY_USB_INIT_SEQ +// #define CONFIG_LEGACY_USB_INIT_SEQ /* * By the time we get here, the device has gotten a new device ID * and is in the default state. We need to identify the thing and @@ -1002,16 +994,18 @@ int usb_new_device(struct usb_device *dev) tmpbuf = (unsigned char *) driver_mem_alloc(USB_BUFSIZ); if (tmpbuf == NULL) { - dbg("usb_new_device: malloc failure\r\n"); + dbg("usb_new_device: malloc failure\r\n"); return 1; } #ifdef CONFIG_LEGACY_USB_INIT_SEQ - /* this is the old and known way of initializing devices, it is + /* + * this is the old and known way of initializing devices, it is * different than what Windows and Linux are doing. Windows and Linux * both retrieve 64 bytes while reading the device descriptor * Several USB stick devices report ERR: CTL_TIMEOUT, caused by an - * invalid header while reading 8 bytes as device descriptor. */ + * invalid header while reading 8 bytes as device descriptor. + */ dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ dev->maxpacketsize = PACKET_SIZE_8; dev->epmaxpacketin[0] = 8; @@ -1019,23 +1013,27 @@ int usb_new_device(struct usb_device *dev) err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); if (err < 8) { - dbg("\r\nUSB device not responding, giving up (status=%lX)\r\n", dev->status); + dbg("\r\nUSB device not responding, giving up (status=%lX)\r\n", dev->status); driver_mem_free(tmpbuf); return 1; } #else - /* This is a Windows scheme of initialization sequence, with double + /* + * This is a Windows scheme of initialization sequence, with double * reset of the device (Linux uses the same sequence) * Some equipment is said to work only with such init sequence; this * patch is based on the work by Alan Stern: * http://sourceforge.net/mailarchive/forum.php? * thread_id=5729457&forum_id=5398 */ - /* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is + + /* + * send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is * only 18 bytes long, this will terminate with a short packet. But if * the maxpacket size is 8 or 16 the device may be waiting to transmit - * some more, or keeps on retransmitting the 8 byte header. */ - desc = (struct usb_device_descriptor *)tmpbuf; + * some more, or keeps on retransmitting the 8 byte header. + */ + desc = (struct usb_device_descriptor *) tmpbuf; dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */ /* Default to 64 byte max packet size */ dev->maxpacketsize = PACKET_SIZE_64; @@ -1044,7 +1042,7 @@ int usb_new_device(struct usb_device *dev) err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); if (err < 0) { - dbg("usb_new_device: usb_get_descriptor() failed\r\n"); + dbg("usb_new_device: usb_get_descriptor() failed\r\n"); driver_mem_free(tmpbuf); return 1; } @@ -1062,17 +1060,19 @@ int usb_new_device(struct usb_device *dev) break; } } + if (port < 0) { - dbg("usb_new_device: cannot locate device's port.\r\n"); + dbg("usb_new_device: cannot locate device's port.\r\n"); driver_mem_free(tmpbuf); return 1; } + /* reset the port for the second time */ err = hub_port_reset(dev->parent, port, &portstatus); if (err < 0) { - dbg("\r\nCouldn't reset port %d\r\n", port); + dbg("\r\nCouldn't reset port %d\r\n", port); driver_mem_free(tmpbuf); return 1; } @@ -1091,7 +1091,7 @@ int usb_new_device(struct usb_device *dev) err = usb_set_address(dev); /* set address */ if (err < 0) { - dbg("\r\nUSB device not accepting new address (error=%lX)\r\n", dev->status); + dbg("\r\nUSB device not accepting new address (error=%lX)\r\n", dev->status); driver_mem_free(tmpbuf); return 1; } @@ -1101,13 +1101,14 @@ int usb_new_device(struct usb_device *dev) if (err < tmp) { if (err < 0) - dbg("unable to get device descriptor (error=%d)\r\n", err); + dbg("unable to get device descriptor (error=%d)\r\n", err); else - dbg("USB device descriptor short read (expected %i, got %i)\r\n", tmp, err); + dbg("USB device descriptor short read (expected %i, got %i)\r\n", tmp, err); driver_mem_free(tmpbuf); return 1; } - /* correct le values */ + + /* correct values */ dev->descriptor.bcdUSB = swpw(dev->descriptor.bcdUSB); dev->descriptor.idVendor = swpw(dev->descriptor.idVendor); dev->descriptor.idProduct = swpw(dev->descriptor.idProduct); @@ -1119,11 +1120,11 @@ int usb_new_device(struct usb_device *dev) /* we set the default configuration here */ if (usb_set_configuration(dev, dev->config.bConfigurationValue)) { - dbg("failed to set default configuration len %d, status %lX\r\n", dev->act_len, dev->status); + dbg("failed to set default configuration len %d, status %lX\r\n", dev->act_len, dev->status); driver_mem_free(tmpbuf); return -1; } - dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\r\n", + dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\r\n", dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); memset(dev->mf, 0, sizeof(dev->mf)); @@ -1135,12 +1136,14 @@ int usb_new_device(struct usb_device *dev) usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod)); if (dev->descriptor.iSerialNumber) usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial)); - dbg("Manufacturer %s\r\n", dev->mf); - dbg("Product %s\r\n", dev->prod); - dbg("SerialNumber %s\r\n", dev->serial); - /* now prode if the device is a hub */ + dbg("Manufacturer %s\r\n", dev->mf); + dbg("Product %s\r\n", dev->prod); + dbg("SerialNumber %s\r\n", dev->serial); + + /* now probe if the device is a hub */ usb_hub_probe(dev, 0); driver_mem_free(tmpbuf); + return 0; } @@ -1186,514 +1189,3 @@ void usb_scan_devices(void *priv) xprintf("Scan end\r\n"); } -/**************************************************************************** - * HUB "Driver" - * Probes device for being a hub and configurate it - */ - -//#define USB_HUB_DEBUG - -#ifdef USB_HUB_DEBUG -#define dbg_hub(fmt, args...) xprintf(fmt , ##args) -#else -#define dbg_hub(fmt, args...) -#endif - -static struct usb_hub_device hub_dev[USB_MAX_BUS][USB_MAX_HUB]; -static int usb_hub_index[USB_MAX_BUS]; - -int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT); -} - -int usb_clear_hub_feature(struct usb_device *dev, int feature) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, USB_CNTL_TIMEOUT); -} - -int usb_clear_port_feature(struct usb_device *dev, int port, int feature) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); -} - -int usb_set_port_feature(struct usb_device *dev, int port, int feature) -{ - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); -} - -int usb_get_hub_status(struct usb_device *dev, void *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT); -} - -int usb_get_port_status(struct usb_device *dev, int port, void *data) -{ - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT); -} - -static void usb_hub_power_on(struct usb_hub_device *hub) -{ - int i; - struct usb_device *dev; - - dev = hub->pusb_dev; - /* Enable power to the ports */ - dbg_hub("enabling power on all ports\r\n"); - for (i = 0; i < dev->maxchild; i++) - { - usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); - dbg_hub("port %d returns %lX\r\n", i + 1, dev->status); - wait(hub->desc.bPwrOn2PwrGood * 2 * 1000); - } -} - -void usb_hub_reset(int bus_index) -{ - usb_hub_index[bus_index] = 0; -} - -struct usb_hub_device *usb_hub_allocate(void) -{ - if (usb_hub_index[bus_index] < USB_MAX_HUB) - return &hub_dev[bus_index][usb_hub_index[bus_index]++]; - dbg_hub("ERROR: USB_MAX_HUB (%d) reached\r\n", USB_MAX_HUB); - return NULL; -} - -#define MAX_TRIES 5 - -static inline char *portspeed(int portstatus) -{ - if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) - return "480 Mb/s"; - else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) - return "1.5 Mb/s"; - else - return "12 Mb/s"; -} - -static int hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat) -{ - int tries; - struct usb_port_status portsts; - unsigned short portstatus, portchange; - - dbg_hub("hub_port_reset: resetting port %d...\r\n", port + 1); - - for (tries = 0; tries < MAX_TRIES; tries++) - { - usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); -#ifdef USB_POLL_HUB - if (pxCurrentTCB != NULL) - vTaskDelay((200*configTICK_RATE_HZ)/1000); - else -#endif - wait(10000); - if (usb_get_port_status(dev, port + 1, &portsts) < 0) - { - dbg_hub("get_port_status failed status %lX\r\n", dev->status); - return -1; - } - portstatus = swpw(portsts.wPortStatus); - portchange = swpw(portsts.wPortChange); - dbg_hub("USB %d portstatus 0x%x, change 0x%x, %s\r\n", dev->usbnum, portstatus, portchange, portspeed(portstatus)); - dbg_hub("STAT_C_CONNECTION = %d STAT_CONNECTION = %d USB_PORT_STAT_ENABLE = %d\r\n", - (portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0, - (portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0, - (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0); - - if ((portchange & USB_PORT_STAT_C_CONNECTION) || !(portstatus & USB_PORT_STAT_CONNECTION)) - return -1; - - if (portstatus & USB_PORT_STAT_ENABLE) - break; - -#ifdef USB_POLL_HUB - if (pxCurrentTCB != NULL) - vTaskDelay((200*configTICK_RATE_HZ)/1000); - else -#endif - wait(20000); - } - if (tries == MAX_TRIES) - { - dbg_hub("USB %d, cannot enable port %d after %d retries, disabling port.\r\n", dev->usbnum, port + 1, MAX_TRIES); - dbg_hub("Maybe the USB cable is bad?\r\n"); - return -1; - } - usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET); - *portstat = portstatus; - return 0; -} - -void usb_hub_port_connect_change(struct usb_device *dev, int port) -{ - struct usb_device *usb; - struct usb_port_status portsts; - unsigned short portstatus; - - - /* Check status */ - if (usb_get_port_status(dev, port + 1, &portsts) < 0) - { - dbg_hub("USB %d get_port_status failed\r\n", dev->usbnum); - return; - } - - portstatus = swpw(portsts.wPortStatus); -#ifdef USB_DEBUG - { - unsigned short portchange; - - portchange = swpw(portsts.wPortChange); - dbg_hub("USB %d, portstatus %x, change %x, %s\r\n", dev->usbnum, portstatus, portchange, portspeed(portstatus)); - } -#endif /* USB_DEBUG */ - - /* Clear the connection change status */ - usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION); - /* Disconnect any existing devices under this port */ - - if (((!(portstatus & USB_PORT_STAT_CONNECTION)) - && (!(portstatus & USB_PORT_STAT_ENABLE))) || (dev->children[port])) - { - dbg_hub("USB %d port %i disconnected\r\n", dev->usbnum, port + 1); - usb_disconnect(&dev->children[port]); - /* Return now if nothing is connected */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return; - } -#ifdef USB_POLL_HUB - if (pxCurrentTCB != NULL) - vTaskDelay((200*configTICK_RATE_HZ)/1000); - else -#endif - wait(2000); - /* Reset the port */ - if (hub_port_reset(dev, port, &portstatus) < 0) - { - dbg_hub("USB %d cannot reset port %i!?\r\n", dev->usbnum, port + 1); - return; - } -#ifdef USB_POLL_HUB - if (pxCurrentTCB != NULL) - vTaskDelay((200*configTICK_RATE_HZ)/1000); - else -#endif - wait(2000); - - /* Allocate a new device struct for it */ - usb = usb_alloc_new_device(dev->usbnum, dev->priv_hcd); - - if (portstatus & USB_PORT_STAT_HIGH_SPEED) - usb->speed = USB_SPEED_HIGH; - else if (portstatus & USB_PORT_STAT_LOW_SPEED) - usb->speed = USB_SPEED_LOW; - else - usb->speed = USB_SPEED_FULL; - dbg_hub("%s: usb=%p\r\n", __FUNCTION__, usb); - dev->children[port] = usb; - usb->parent = dev; - - /* Run it through the hoops (find a driver, etc) */ - if (usb_new_device(usb)) - { - /* Woops, disable the port */ - dbg_hub("USB %d hub: disabling port %d\r\n", dev->usbnum, port + 1); - usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE); - } - -#ifdef USB_POLL_HUB - else if (pxCurrentTCB != NULL) - { -#ifdef CONFIG_USB_KEYBOARD - usb_kbd_register(usb); -#endif /* CONFIG_USB_KEYBOARD */ -#ifdef CONFIG_USB_MOUSE - usb_mouse_register(usb); -#endif /* CONFIG_USB_MOUSE */ -#ifdef CONFIG_USB_STORAGE - usb_stor_register(usb); -#endif /* CONFIG_USB_STORAGE */ - } -#endif -} - -static void usb_hub_events(struct usb_device *dev) -{ - int i; - struct usb_hub_device *hub = dev->hub; - if (hub == NULL) - return; - for (i = 0; i < dev->maxchild; i++) - { - struct usb_port_status portsts; - unsigned short portstatus, portchange; - - if (usb_get_port_status(dev, i + 1, &portsts) < 0) - { - dbg_hub("get_port_status failed\r\n"); - continue; - } - portstatus = swpw(portsts.wPortStatus); - portchange = swpw(portsts.wPortChange); - dbg_hub("USB %d Port %d Status %X Change %X\r\n", dev->usbnum, i + 1, portstatus, portchange); - if (portchange & USB_PORT_STAT_C_CONNECTION) - { - dbg_hub("USB %d port %d connection change\r\n", dev->usbnum, i + 1); - usb_hub_port_connect_change(dev, i); - } - if (portchange & USB_PORT_STAT_C_ENABLE) - { - dbg_hub("USB %d port %d enable change, status %x\r\n", dev->usbnum, i + 1, portstatus); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); - /* EM interference sometimes causes bad shielded USB - * devices to be shutdown by the hub, this hack enables - * them again. Works at least with mouse driver */ - if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) && ((dev->children[i]))) - { - dbg_hub("USB %d already running port %i disabled by hub (EMI?), re-enabling...\r\n", dev->usbnum, i + 1); - usb_hub_port_connect_change(dev, i); - } - } - if (portstatus & USB_PORT_STAT_SUSPEND) - { - dbg_hub("USB %d port %d suspend change\r\n", dev->usbnum, i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); - } - if (portchange & USB_PORT_STAT_C_OVERCURRENT) - { - dbg_hub("USB %d port %d over-current change\r\n", dev->usbnum, i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); - usb_hub_power_on(hub); - } - if (portchange & USB_PORT_STAT_C_RESET) - { - dbg_hub("USB %d port %d reset change\r\n", dev->usbnum, i + 1); - usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); - } - } /* end for i all ports */ -} - -#ifdef USB_POLL_HUB -void usb_poll_hub_task(void *pvParameters) -{ - int index_bus = 0; - portTickType timeout = configTICK_RATE_HZ/10; - if (pvParameters); - while(1) - { - if (xQueueAltReceive(queue_poll_hub, &index_bus, timeout) == pdPASS) - { - if ((index_bus >= 0) && (index_bus < USB_MAX_BUS) && (controller_priv[index_bus] != NULL)) - { - dbg_hub("USB %d event change\r\n", index_bus); -#ifdef CONFIG_USB_INTERRUPT_POLLING - *vblsem = 0; -#endif - usb_hub_events(&usb_dev[index_bus * USB_MAX_DEVICE]); -#ifdef CONFIG_USB_INTERRUPT_POLLING - *vblsem = 1; -#endif - } - } - else /* timeout */ - { - int i; -#ifdef CONFIG_USB_INTERRUPT_POLLING - *vblsem = 0; -#endif - for (i = 0; i < USB_MAX_BUS ; i++) - { - if (controller_priv[i] != NULL) - usb_hub_events(&usb_dev[i * USB_MAX_DEVICE]); - } -#ifdef CONFIG_USB_INTERRUPT_POLLING - *vblsem = 1; -#endif - } - timeout = portMAX_DELAY; - } -} -#endif /* USB_POLL_HUB */ - -int usb_hub_configure(struct usb_device *dev) -{ - unsigned char *buffer, *bitmap; - struct usb_hub_descriptor *descriptor; - int i; - struct usb_hub_device *hub; - /* "allocate" Hub device */ - hub = usb_hub_allocate(); - dev->hub = hub; - if (hub == NULL) - return -1; - hub->pusb_dev = dev; - buffer = (unsigned char *)driver_mem_alloc(USB_BUFSIZ); - if (buffer == NULL) - { - dbg_hub("usb_hub_configure: malloc failure\r\n"); - return -1; - } - /* Get the the hub descriptor */ - if (usb_get_hub_descriptor(dev, buffer, 4) < 0) - { - dbg_hub("usb_hub_configure: failed to get hub descriptor, giving up %lX\r\n", dev->status); - driver_mem_free(buffer); - return -1; - } - dbg_hub("bLength:%02X bDescriptorType:%02X bNbrPorts:%02X\r\n", buffer[0], buffer[1], buffer[2]); - descriptor = (struct usb_hub_descriptor *)buffer; - /* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */ - i = descriptor->bLength; - if (i > USB_BUFSIZ) - { - dbg_hub("usb_hub_configure: failed to get hub descriptor - too long: %d\r\n", descriptor->bLength); - driver_mem_free(buffer); - return -1; - } - if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) - { - dbg_hub("usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\r\n", dev->status); - driver_mem_free(buffer); - return -1; - } - memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength); - /* adjust 16bit values */ - hub->desc.wHubCharacteristics = swpw(descriptor->wHubCharacteristics); - /* set the bitmap */ - bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; - /* devices not removable by default */ - memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); - bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0]; - memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */ - for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) - hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i]; - for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) - hub->desc.DeviceRemovable[i] = descriptor->PortPowerCtrlMask[i]; - dev->maxchild = descriptor->bNbrPorts; - dbg_hub("USB %d, %d ports detected\r\n", dev->usbnum, dev->maxchild); - if (dev->maxchild >= 10) - dev->maxchild = 10; - switch(hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) - { - case 0x00: dbg_hub("ganged power switching\r\n"); break; - case 0x01: dbg_hub("individual port power switching\r\n"); break; - case 0x02: - case 0x03: dbg_hub("unknown reserved power switching mode\r\n"); break; - } - if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND) - { - dbg_hub("part of a compound device\r\n"); - } - else - { - dbg_hub("standalone hub\r\n"); - } - switch(hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) - { - case 0x00: dbg_hub("global over-current protection\r\n"); break; - case 0x08: dbg_hub("individual port over-current protection\r\n"); break; - case 0x10: - case 0x18: dbg_hub("no over-current protection\r\n"); break; - } - dbg_hub("power on to power good time: %dms\r\n", descriptor->bPwrOn2PwrGood * 2); - dbg_hub("hub controller current requirement: %dmA\r\n", descriptor->bHubContrCurrent); - for (i = 0; i < dev->maxchild; i++) - { - dbg_hub("USB %d port %d is%s removable\r\n", dev->usbnum, i + 1, hub->desc.DeviceRemovable[(i + 1) / 8] & (1 << ((i + 1) % 8)) ? " not" : ""); - } - if (sizeof(struct usb_hub_status) > USB_BUFSIZ) - { - dbg_hub("usb_hub_configure: failed to get Status - too long: %d\r\n", descriptor->bLength); - driver_mem_free(buffer); - return -1; - } - if (usb_get_hub_status(dev, buffer) < 0) - { - dbg_hub("usb_hub_configure: failed to get Status %lX\r\n", dev->status); - driver_mem_free(buffer); - return -1; - } - -#ifdef USB_DEBUG - { - struct usb_hub_status *hubsts; - - hubsts = (struct usb_hub_status *)buffer; - dbg_hub("get_hub_status returned status %X, change %X\r\n", - swpw(hubsts->wHubStatus), swpw(hubsts->wHubChange)); - dbg_hub("local power source is %s\r\n", - (swpw(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); - dbg_hub("%sover-current condition exists\r\n", - (swpw(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no "); - } -#endif /* USB_DEBUG */ - - usb_hub_power_on(hub); - -#ifdef USB_POLL_HUB - if ((queue_poll_hub == NULL) && (pxCurrentTCB != NULL)) - { - queue_poll_hub = xQueueCreate(64, sizeof(int)); - if (queue_poll_hub != NULL) - { - /* Create poll/event task */ - if (xTaskCreate(usb_poll_hub_task, (void *)"USBHub", configMINIMAL_STACK_SIZE, NULL, 16, NULL) != pdPASS) - { - vQueueDelete(queue_poll_hub); - queue_poll_hub = NULL; - } - } - vTaskDelay(configTICK_RATE_HZ); - } - if (queue_poll_hub == NULL) -#endif - usb_hub_events(dev); - driver_mem_free(buffer); - return 0; -} - -int usb_hub_probe(struct usb_device *dev, int ifnum) -{ - struct usb_interface_descriptor *iface; - struct usb_endpoint_descriptor *ep; - int ret; - - iface = &dev->config.if_desc[ifnum]; - - /* Is it a hub? */ - if (iface->bInterfaceClass != USB_CLASS_HUB) - { - dbg("iface->bInterfaceClass != USB_CLASS_HUB (%d), %d instead\r\n", USB_CLASS_HUB, iface->bInterfaceClass); - return 0; - } - - /* Some hubs have a subclass of 1, which AFAICT according to the */ - /* specs is not defined, but it works */ - if ((iface->bInterfaceSubClass != 0) && (iface->bInterfaceSubClass != 1)) - return 0; - /* Multiple endpoints? What kind of mutant ninja-hub is this? */ - if (iface->bNumEndpoints != 1) - return 0; - ep = &iface->ep_desc[0]; - /* Output endpoint? Curiousier and curiousier.. */ - if (!(ep->bEndpointAddress & USB_DIR_IN)) - return 0; - /* If it's not an interrupt endpoint, we'd better punt! */ - if ((ep->bmAttributes & 3) != 3) - return 0; - /* We found a hub */ - dbg_hub("USB %d hub found\r\n", dev->usbnum); - ret = usb_hub_configure(dev); - return ret; -} - - diff --git a/usb/usb_hub.c b/usb/usb_hub.c new file mode 100644 index 0000000..810a176 --- /dev/null +++ b/usb/usb_hub.c @@ -0,0 +1,542 @@ +/* + * HUB "Driver" + * Probes device for being a hub and configure it + */ + +#include +#include "bas_string.h" +#include "bas_printf.h" +#include "util.h" /* for byte swap funcs */ +#include "wait.h" +#include +#include "usb.h" +#include "usb_hub.h" + +#define DEBUG_HUB +#ifdef DEBUG_HUB +#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) +#else +#define dbg(format, arg...) do { ; } while (0) +#endif /* DEBUG_HUB */ + +static struct usb_hub_device hub_dev[USB_MAX_BUS][USB_MAX_HUB]; +static int usb_hub_index[USB_MAX_BUS]; + +int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT); +} + +int usb_clear_hub_feature(struct usb_device *dev, int feature) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, USB_CNTL_TIMEOUT); +} + +int usb_clear_port_feature(struct usb_device *dev, int port, int feature) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); +} + +int usb_set_port_feature(struct usb_device *dev, int port, int feature) +{ + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT); +} + +int usb_get_hub_status(struct usb_device *dev, void *data) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT); +} + +int usb_get_port_status(struct usb_device *dev, int port, void *data) +{ + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT); +} + +static void usb_hub_power_on(struct usb_hub_device *hub) +{ + int i; + struct usb_device *dev; + + dev = hub->pusb_dev; + /* Enable power to the ports */ + dbg("enabling power on all ports\r\n"); + for (i = 0; i < dev->maxchild; i++) + { + usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); + dbg("port %d returns %lX\r\n", i + 1, dev->status); + wait(hub->desc.bPwrOn2PwrGood * 2 * 1000); + } +} + +void usb_hub_reset(int bus_index) +{ + usb_hub_index[bus_index] = 0; +} + +struct usb_hub_device *usb_hub_allocate(void) +{ + if (usb_hub_index[bus_index] < USB_MAX_HUB) + return &hub_dev[bus_index][usb_hub_index[bus_index]++]; + dbg("ERROR: USB_MAX_HUB (%d) reached\r\n", USB_MAX_HUB); + return NULL; +} + +#define MAX_TRIES 5 + +static inline char *portspeed(int portstatus) +{ + if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) + return "480 Mb/s"; + else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) + return "1.5 Mb/s"; + else + return "12 Mb/s"; +} + +int hub_port_reset(struct usb_device *dev, int port, unsigned short *portstat) +{ + int tries; + struct usb_port_status portsts; + unsigned short portstatus, portchange; + + dbg("hub_port_reset: resetting port %d...\r\n", port + 1); + + for (tries = 0; tries < MAX_TRIES; tries++) + { + usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET); +#ifdef USB_POLL_HUB + if (pxCurrentTCB != NULL) + vTaskDelay((200*configTICK_RATE_HZ)/1000); + else +#endif + wait(10000); + if (usb_get_port_status(dev, port + 1, &portsts) < 0) + { + dbg("get_port_status failed status %lX\r\n", dev->status); + return -1; + } + portstatus = swpw(portsts.wPortStatus); + portchange = swpw(portsts.wPortChange); + dbg("USB %d portstatus 0x%x, change 0x%x, %s\r\n", dev->usbnum, portstatus, portchange, portspeed(portstatus)); + dbg("STAT_C_CONNECTION = %d STAT_CONNECTION = %d USB_PORT_STAT_ENABLE = %d\r\n", + (portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0, + (portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0, + (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0); + + if ((portchange & USB_PORT_STAT_C_CONNECTION) || !(portstatus & USB_PORT_STAT_CONNECTION)) + return -1; + + if (portstatus & USB_PORT_STAT_ENABLE) + break; + +#ifdef USB_POLL_HUB + if (pxCurrentTCB != NULL) + vTaskDelay((200*configTICK_RATE_HZ)/1000); + else +#endif + wait(20000); + } + if (tries == MAX_TRIES) + { + dbg("USB %d, cannot enable port %d after %d retries, disabling port.\r\n", dev->usbnum, port + 1, MAX_TRIES); + dbg("Maybe the USB cable is bad?\r\n"); + return -1; + } + usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET); + *portstat = portstatus; + return 0; +} + +void usb_hub_port_connect_change(struct usb_device *dev, int port) +{ + struct usb_device *usb; + struct usb_port_status portsts; + unsigned short portstatus; + + + /* Check status */ + if (usb_get_port_status(dev, port + 1, &portsts) < 0) + { + dbg("USB %d get_port_status failed\r\n", dev->usbnum); + return; + } + + portstatus = swpw(portsts.wPortStatus); +#ifdef USB_DEBUG + { + unsigned short portchange; + + portchange = swpw(portsts.wPortChange); + dbg("USB %d, portstatus %x, change %x, %s\r\n", dev->usbnum, portstatus, portchange, portspeed(portstatus)); + } +#endif /* USB_DEBUG */ + + /* Clear the connection change status */ + usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION); + /* Disconnect any existing devices under this port */ + + if (((!(portstatus & USB_PORT_STAT_CONNECTION)) + && (!(portstatus & USB_PORT_STAT_ENABLE))) || (dev->children[port])) + { + dbg("USB %d port %i disconnected\r\n", dev->usbnum, port + 1); + usb_disconnect(&dev->children[port]); + /* Return now if nothing is connected */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return; + } +#ifdef USB_POLL_HUB + if (pxCurrentTCB != NULL) + vTaskDelay((200*configTICK_RATE_HZ)/1000); + else +#endif + wait(2000); + /* Reset the port */ + if (hub_port_reset(dev, port, &portstatus) < 0) + { + dbg("USB %d cannot reset port %i!?\r\n", dev->usbnum, port + 1); + return; + } +#ifdef USB_POLL_HUB + if (pxCurrentTCB != NULL) + vTaskDelay((200*configTICK_RATE_HZ)/1000); + else +#endif + wait(2000); + + /* Allocate a new device struct for it */ + usb = usb_alloc_new_device(dev->usbnum, dev->priv_hcd); + + if (portstatus & USB_PORT_STAT_HIGH_SPEED) + usb->speed = USB_SPEED_HIGH; + else if (portstatus & USB_PORT_STAT_LOW_SPEED) + usb->speed = USB_SPEED_LOW; + else + usb->speed = USB_SPEED_FULL; + + dbg("usb=%p\r\n", usb); + dev->children[port] = usb; + usb->parent = dev; + + /* Run it through the hoops (find a driver, etc) */ + if (usb_new_device(usb)) + { + /* Woops, disable the port */ + dbg("USB %d hub: disabling port %d\r\n", dev->usbnum, port + 1); + usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE); + } + +#ifdef USB_POLL_HUB + else if (pxCurrentTCB != NULL) + { +#ifdef CONFIG_USB_KEYBOARD + usb_kbd_register(usb); +#endif /* CONFIG_USB_KEYBOARD */ +#ifdef CONFIG_USB_MOUSE + usb_mouse_register(usb); +#endif /* CONFIG_USB_MOUSE */ +#ifdef CONFIG_USB_STORAGE + usb_stor_register(usb); +#endif /* CONFIG_USB_STORAGE */ + } +#endif +} + +static void usb_hub_events(struct usb_device *dev) +{ + int i; + struct usb_hub_device *hub = dev->hub; + if (hub == NULL) + return; + for (i = 0; i < dev->maxchild; i++) + { + struct usb_port_status portsts; + unsigned short portstatus, portchange; + + if (usb_get_port_status(dev, i + 1, &portsts) < 0) + { + dbg("get_port_status failed\r\n"); + continue; + } + portstatus = swpw(portsts.wPortStatus); + portchange = swpw(portsts.wPortChange); + dbg("USB %d Port %d Status %X Change %X\r\n", dev->usbnum, i + 1, portstatus, portchange); + if (portchange & USB_PORT_STAT_C_CONNECTION) + { + dbg("USB %d port %d connection change\r\n", dev->usbnum, i + 1); + usb_hub_port_connect_change(dev, i); + } + if (portchange & USB_PORT_STAT_C_ENABLE) + { + dbg("USB %d port %d enable change, status %x\r\n", dev->usbnum, i + 1, portstatus); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE); + /* EM interference sometimes causes bad shielded USB + * devices to be shutdown by the hub, this hack enables + * them again. Works at least with mouse driver */ + if (!(portstatus & USB_PORT_STAT_ENABLE) && (portstatus & USB_PORT_STAT_CONNECTION) && ((dev->children[i]))) + { + dbg("USB %d already running port %i disabled by hub (EMI?), re-enabling...\r\n", dev->usbnum, i + 1); + usb_hub_port_connect_change(dev, i); + } + } + if (portstatus & USB_PORT_STAT_SUSPEND) + { + dbg("USB %d port %d suspend change\r\n", dev->usbnum, i + 1); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_SUSPEND); + } + if (portchange & USB_PORT_STAT_C_OVERCURRENT) + { + dbg("USB %d port %d over-current change\r\n", dev->usbnum, i + 1); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT); + usb_hub_power_on(hub); + } + if (portchange & USB_PORT_STAT_C_RESET) + { + dbg("USB %d port %d reset change\r\n", dev->usbnum, i + 1); + usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET); + } + } /* end for i all ports */ +} + +#ifdef USB_POLL_HUB +void usb_poll_hub_task(void *pvParameters) +{ + int index_bus = 0; + portTickType timeout = configTICK_RATE_HZ/10; + if (pvParameters); + while(1) + { + if (xQueueAltReceive(queue_poll_hub, &index_bus, timeout) == pdPASS) + { + if ((index_bus >= 0) && (index_bus < USB_MAX_BUS) && (controller_priv[index_bus] != NULL)) + { + dbg("USB %d event change\r\n", index_bus); +#ifdef CONFIG_USB_INTERRUPT_POLLING + *vblsem = 0; +#endif + usb_hub_events(&usb_dev[index_bus * USB_MAX_DEVICE]); +#ifdef CONFIG_USB_INTERRUPT_POLLING + *vblsem = 1; +#endif + } + } + else /* timeout */ + { + int i; +#ifdef CONFIG_USB_INTERRUPT_POLLING + *vblsem = 0; +#endif + for (i = 0; i < USB_MAX_BUS ; i++) + { + if (controller_priv[i] != NULL) + usb_hub_events(&usb_dev[i * USB_MAX_DEVICE]); + } +#ifdef CONFIG_USB_INTERRUPT_POLLING + *vblsem = 1; +#endif + } + timeout = portMAX_DELAY; + } +} +#endif /* USB_POLL_HUB */ + +int usb_hub_configure(struct usb_device *dev) +{ + unsigned char *buffer, *bitmap; + struct usb_hub_descriptor *descriptor; + int i; + struct usb_hub_device *hub; + + /* "allocate" Hub device */ + hub = usb_hub_allocate(); + dev->hub = hub; + + if (hub == NULL) + return -1; + + hub->pusb_dev = dev; + buffer = (unsigned char *) driver_mem_alloc(USB_BUFSIZ); + if (buffer == NULL) + { + dbg("driver_mem_alloc() failure\r\n"); + return -1; + } + + /* Get the the hub descriptor */ + if (usb_get_hub_descriptor(dev, buffer, 4) < 0) + { + dbg("failed to get hub descriptor, giving up %lX\r\n", dev->status); + driver_mem_free(buffer); + return -1; + } + dbg("bLength:%02X bDescriptorType:%02X bNbrPorts:%02X\r\n", buffer[0], buffer[1], buffer[2]); + descriptor = (struct usb_hub_descriptor *)buffer; + + /* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */ + i = descriptor->bLength; + if (i > USB_BUFSIZ) + { + dbg("failed to get hub descriptor - too long: %d\r\n", descriptor->bLength); + driver_mem_free(buffer); + return -1; + } + if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) + { + dbg("failed to get hub descriptor 2nd giving up %lX\r\n", dev->status); + driver_mem_free(buffer); + return -1; + } + memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength); + + /* adjust 16bit values */ + hub->desc.wHubCharacteristics = swpw(descriptor->wHubCharacteristics); + + /* set the bitmap */ + bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0]; + + /* devices not removable by default */ + + memset(bitmap, 0xff, (USB_MAXCHILDREN + 1 + 7) / 8); + bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0]; + memset(bitmap, 0xff, (USB_MAXCHILDREN + 1 + 7) / 8); /* PowerMask = 1B */ + + for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7) / 8); i++) + hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i]; + + for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++) + hub->desc.DeviceRemovable[i] = descriptor->PortPowerCtrlMask[i]; + + dev->maxchild = descriptor->bNbrPorts; + dbg("USB %d, %d ports detected\r\n", dev->usbnum, dev->maxchild); + if (dev->maxchild >= 10) + dev->maxchild = 10; + switch(hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) + { + case 0x00: dbg("ganged power switching\r\n"); break; + case 0x01: dbg("individual port power switching\r\n"); break; + case 0x02: + case 0x03: dbg("unknown reserved power switching mode\r\n"); break; + } + if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND) + { + dbg("part of a compound device\r\n"); + } + else + { + dbg("standalone hub\r\n"); + } + switch(hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) + { + case 0x00: dbg("global over-current protection\r\n"); break; + case 0x08: dbg("individual port over-current protection\r\n"); break; + case 0x10: + case 0x18: dbg("no over-current protection\r\n"); break; + } + dbg("power on to power good time: %dms\r\n", descriptor->bPwrOn2PwrGood * 2); + dbg("hub controller current requirement: %dmA\r\n", descriptor->bHubContrCurrent); + + for (i = 0; i < dev->maxchild; i++) + { + dbg("USB %d port %d is%s removable\r\n", dev->usbnum, i + 1, hub->desc.DeviceRemovable[(i + 1) / 8] & (1 << ((i + 1) % 8)) ? " not" : ""); + } + + if (sizeof(struct usb_hub_status) > USB_BUFSIZ) + { + dbg("usb_hub_configure: failed to get Status - too long: %d\r\n", descriptor->bLength); + driver_mem_free(buffer); + return -1; + } + + if (usb_get_hub_status(dev, buffer) < 0) + { + dbg("usb_hub_configure: failed to get Status %lX\r\n", dev->status); + driver_mem_free(buffer); + return -1; + } + +#ifdef USB_DEBUG + { + struct usb_hub_status *hubsts; + + hubsts = (struct usb_hub_status *)buffer; + dbg("get_hub_status returned status %X, change %X\r\n", + swpw(hubsts->wHubStatus), swpw(hubsts->wHubChange)); + dbg("local power source is %s\r\n", + (swpw(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good"); + dbg("%sover-current condition exists\r\n", + (swpw(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no "); + } +#endif /* USB_DEBUG */ + + usb_hub_power_on(hub); + +#ifdef USB_POLL_HUB + if ((queue_poll_hub == NULL) && (pxCurrentTCB != NULL)) + { + queue_poll_hub = xQueueCreate(64, sizeof(int)); + if (queue_poll_hub != NULL) + { + /* Create poll/event task */ + if (xTaskCreate(usb_poll_hub_task, (void *)"USBHub", configMINIMAL_STACK_SIZE, NULL, 16, NULL) != pdPASS) + { + vQueueDelete(queue_poll_hub); + queue_poll_hub = NULL; + } + } + vTaskDelay(configTICK_RATE_HZ); + } + if (queue_poll_hub == NULL) +#endif + usb_hub_events(dev); + driver_mem_free(buffer); + + return 0; +} + +int usb_hub_probe(struct usb_device *dev, int ifnum) +{ + struct usb_interface_descriptor *iface; + struct usb_endpoint_descriptor *ep; + int ret; + + iface = &dev->config.if_desc[ifnum]; + + /* Is it a hub? */ + if (iface->bInterfaceClass != USB_CLASS_HUB) + { + dbg("iface->bInterfaceClass != USB_CLASS_HUB (%d), %d instead\r\n", USB_CLASS_HUB, iface->bInterfaceClass); + return 0; + } + + /* Some hubs have a subclass of 1, which AFAICT according to the */ + /* specs is not defined, but it works */ + if ((iface->bInterfaceSubClass != 0) && (iface->bInterfaceSubClass != 1)) + return 0; + + /* Multiple endpoints? What kind of mutant ninja-hub is this? */ + if (iface->bNumEndpoints != 1) + return 0; + + ep = &iface->ep_desc[0]; + + /* Output endpoint? Curiousier and curiousier.. */ + if (!(ep->bEndpointAddress & USB_DIR_IN)) + return 0; + + /* If it's not an interrupt endpoint, we'd better punt! */ + if ((ep->bmAttributes & 3) != 3) + return 0; + + /* We found a hub */ + dbg("USB %d hub found\r\n", dev->usbnum); + ret = usb_hub_configure(dev); + + return ret; +} + + diff --git a/usb/usb_mouse.c b/usb/usb_mouse.c index 500c8bd..6258507 100644 --- a/usb/usb_mouse.c +++ b/usb/usb_mouse.c @@ -99,7 +99,7 @@ int drv_usb_mouse_init(void) if (dev == NULL) break; - xprintf("USB mouse detected. Trying to register it\r\n"); + xprintf("Try to register usb device %d,%d as mouse\r\n", i, j); if (usb_mouse_register(dev) > 0) return 1; } @@ -222,24 +222,24 @@ static int usb_mouse_probe(struct usb_device *dev, unsigned int ifnum) iface = &dev->config.if_desc[ifnum]; - if (iface->bInterfaceClass != USB_CLASS_HID) + if (iface->bInterfaceClass != USB_CLASS_HID) { - dbg("iface->bInterfaceClass != USB_CLASS_HID (%d instead)\r\n", iface->bInterfaceClass); + dbg("iface->bInterfaceClass != USB_CLASS_HID (%d instead)\r\n", iface->bInterfaceClass); return 0; } - if (iface->bInterfaceSubClass != USB_SUB_HID_BOOT) + if (iface->bInterfaceSubClass != USB_SUB_HID_BOOT) { - dbg("iface->bInterfaceSubClass != USB_SUB_HID_BOOT (%d instead)\r\n", iface->bInterfaceSubClass); + dbg("iface->bInterfaceSubClass != USB_SUB_HID_BOOT (%d instead)\r\n", iface->bInterfaceSubClass); return 0; } - if (iface->bInterfaceProtocol != USB_PROT_HID_MOUSE) + if (iface->bInterfaceProtocol != USB_PROT_HID_MOUSE) { - dbg("iface->bInterfaceProtocol != USB_PROT_HID_MOUSE (%d)\r\n", iface->bInterfaceProtocol); + dbg("iface->bInterfaceProtocol != USB_PROT_HID_MOUSE (%d)\r\n", iface->bInterfaceProtocol); return 0; }