implemented pci_hook_interrupt()

formatted USB sources
This commit is contained in:
Markus Fröschle
2014-10-01 15:39:16 +00:00
parent c3cccfbae1
commit 16b2e35a2b
12 changed files with 1798 additions and 195 deletions

View File

@@ -270,3 +270,4 @@ tos/Makefile
usb/usb_hub.c usb/usb_hub.c
include/usb_hub.h include/usb_hub.h
tos/Makefile tos/Makefile
usb/usb_kbd.c

View File

@@ -97,6 +97,7 @@ CSRCS= \
ehci-hcd.c \ ehci-hcd.c \
usb_hub.c \ usb_hub.c \
usb_mouse.c \ usb_mouse.c \
usb_kbd.c \
ikbd.c \ ikbd.c \
\ \
nbuf.c \ nbuf.c \

View File

@@ -53,6 +53,7 @@ SECTIONS
OBJDIR/driver_mem.o(.text) OBJDIR/driver_mem.o(.text)
OBJDIR/usb_hub.o(.text) OBJDIR/usb_hub.o(.text)
OBJDIR/usb_mouse.o(.text) OBJDIR/usb_mouse.o(.text)
OBJDIR/usb_kbd.o(.text)
OBJDIR/ohci-hcd.o(.text) OBJDIR/ohci-hcd.o(.text)
OBJDIR/ehci-hcd.o(.text) OBJDIR/ehci-hcd.o(.text)
OBJDIR/wait.o(.text) OBJDIR/wait.o(.text)

View File

@@ -3,10 +3,14 @@
#define PCI_ANY_ID (~0) #define PCI_ANY_ID (~0)
struct pci_device_id { struct pci_device_id
unsigned long vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ {
unsigned long subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ unsigned long vendor; /* Vendor and device ID or PCI_ANY_ID*/
unsigned long class, class_mask; /* (class,subclass,prog-if) triplet */ unsigned long device;
unsigned long subvendor; /* Subsystem ID's or PCI_ANY_ID */
unsigned long subdevice;
unsigned long class; /* (class,subclass,prog-if) triplet */
unsigned long class_mask;
unsigned long driver_data; /* Data private to the driver */ unsigned long driver_data; /* Data private to the driver */
}; };
@@ -15,7 +19,8 @@ struct pci_device_id {
#define IEEE1394_MATCH_SPECIFIER_ID 0x0004 #define IEEE1394_MATCH_SPECIFIER_ID 0x0004
#define IEEE1394_MATCH_VERSION 0x0008 #define IEEE1394_MATCH_VERSION 0x0008
struct ieee1394_device_id { struct ieee1394_device_id
{
unsigned long match_flags; unsigned long match_flags;
unsigned long vendor_id; unsigned long vendor_id;
unsigned long model_id; unsigned long model_id;
@@ -81,7 +86,8 @@ struct ieee1394_device_id {
* matches towards the beginning of your table, so that driver_info can * matches towards the beginning of your table, so that driver_info can
* record quirks of specific products. * record quirks of specific products.
*/ */
struct usb_device_id { struct usb_device_id
{
/* which fields to match against? */ /* which fields to match against? */
unsigned short match_flags; unsigned short match_flags;
@@ -118,7 +124,8 @@ struct usb_device_id {
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 #define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
/* s390 CCW devices */ /* s390 CCW devices */
struct ccw_device_id { struct ccw_device_id
{
unsigned short match_flags; /* which fields to match against */ unsigned short match_flags; /* which fields to match against */
unsigned short cu_type; /* control unit type */ unsigned short cu_type; /* control unit type */
@@ -138,15 +145,18 @@ struct ccw_device_id {
#define PNP_ID_LEN 8 #define PNP_ID_LEN 8
#define PNP_MAX_DEVICES 8 #define PNP_MAX_DEVICES 8
struct pnp_device_id { struct pnp_device_id
{
unsigned char id[PNP_ID_LEN]; unsigned char id[PNP_ID_LEN];
unsigned long driver_data; unsigned long driver_data;
}; };
struct pnp_card_device_id { struct pnp_card_device_id
{
unsigned char id[PNP_ID_LEN]; unsigned char id[PNP_ID_LEN];
unsigned long driver_data; unsigned long driver_data;
struct { struct
{
unsigned char id[PNP_ID_LEN]; unsigned char id[PNP_ID_LEN];
} devs[PNP_MAX_DEVICES]; } devs[PNP_MAX_DEVICES];
}; };
@@ -154,7 +164,8 @@ struct pnp_card_device_id {
#define SERIO_ANY 0xff #define SERIO_ANY 0xff
struct serio_device_id { struct serio_device_id
{
unsigned char type; unsigned char type;
unsigned char extra; unsigned char extra;
unsigned char id; unsigned char id;

View File

@@ -31,7 +31,6 @@ static int cc_to_error[16] =
/* Not Access */ -1 /* Not Access */ -1
}; };
#ifdef DEBUG_OHCI
static const char *cc_to_string[16] = static const char *cc_to_string[16] =
{ {
"No Error", "No Error",
@@ -64,7 +63,6 @@ static const char *cc_to_string[16] =
"NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \ "NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \
"on a list to be processed by the HC.(2)", "on a list to be processed by the HC.(2)",
}; };
#endif /* DEBUG_OHCI */
/* ED States */ /* ED States */

View File

@@ -91,9 +91,12 @@
#define PCICSR_STEPPING (1 << 7) /* if set: stepping enabled */ #define PCICSR_STEPPING (1 << 7) /* if set: stepping enabled */
#define PCICSR_SERR (1 << 8) /* if set: SERR pin enabled */ #define PCICSR_SERR (1 << 8) /* if set: SERR pin enabled */
#define PCICSR_FAST_BTOB_E (1 << 9) /* if set: fast back-to-back enabled */ #define PCICSR_FAST_BTOB_E (1 << 9) /* if set: fast back-to-back enabled */
#define PCICSR_INT_DISABLE (1 << 10) /* if set: disable interrupts from this device */
/* /*
* bit definitions for PCICSR upper half (Status Register) * bit definitions for PCICSR upper half (Status Register)
*/ */
#define PCICSR_INTERRUPT (1 << 3) /* device requested interrupt */
#define PCICSR_CAPABILITIES (1 << 4) /* if set, capabilities pointer is valid */
#define PCICSR_66MHZ (1 << 5) /* 66 MHz capable */ #define PCICSR_66MHZ (1 << 5) /* 66 MHz capable */
#define PCICSR_UDF (1 << 6) /* UDF supported */ #define PCICSR_UDF (1 << 6) /* UDF supported */
#define PCICSR_FAST_BTOB (1 << 7) /* Fast back-to-back enabled */ #define PCICSR_FAST_BTOB (1 << 7) /* Fast back-to-back enabled */
@@ -243,7 +246,9 @@ extern int32_t pci_write_config_longword(int32_t handle, int offset, uint32_t va
extern int32_t pci_write_config_word(int32_t handle, int offset, uint16_t value); extern int32_t pci_write_config_word(int32_t handle, int offset, uint16_t value);
extern int32_t pci_write_config_byte(int32_t handle, int offset, uint8_t value); extern int32_t pci_write_config_byte(int32_t handle, int offset, uint8_t value);
extern int32_t pci_hook_interrupt(int32_t handle, void *interrupt_handler, void *parameter); typedef int (*pci_interrupt_handler)(int param);
extern int32_t pci_hook_interrupt(int32_t handle, pci_interrupt_handler handler, void *parameter);
extern int32_t pci_unhook_interrupt(int32_t handle); extern int32_t pci_unhook_interrupt(int32_t handle);
extern struct pci_rd *pci_get_resource(int32_t handle); extern struct pci_rd *pci_get_resource(int32_t handle);

View File

@@ -63,7 +63,7 @@ extern int sprintD(char *s, const char *fmt, ...);
#define USB_MAXCHILDREN 8 /* This is arbitrary */ #define USB_MAXCHILDREN 8 /* This is arbitrary */
#define USB_MAX_HUB 16 #define USB_MAX_HUB 16
#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */ #define USB_CNTL_TIMEOUT 100 /* 100 ms timeout */
#define USB_BUFSIZ 512 #define USB_BUFSIZ 512
@@ -180,8 +180,10 @@ struct usb_device
/* Maximum packet size; one of: PACKET_SIZE_* */ /* Maximum packet size; one of: PACKET_SIZE_* */
int maxpacketsize; int maxpacketsize;
/* one bit for each endpoint ([0] = IN, [1] = OUT) */ /* one bit for each endpoint ([0] = IN, [1] = OUT) */
unsigned int toggle[2]; unsigned int toggle[2];
/* endpoint halts; one bit per endpoint # & direction; /* endpoint halts; one bit per endpoint # & direction;
* [0] = IN, [1] = OUT * [0] = IN, [1] = OUT
*/ */
@@ -199,6 +201,7 @@ struct usb_device
uint32_t irq_status; uint32_t irq_status;
int irq_act_len; /* transfered bytes */ int irq_act_len; /* transfered bytes */
void *privptr; void *privptr;
/* /*
* Child devices - if this is a hub device * Child devices - if this is a hub device
* Each instance needs its own set of data structures. * Each instance needs its own set of data structures.
@@ -227,7 +230,7 @@ typedef struct
} v; } v;
} USB_COOKIE; } USB_COOKIE;
/********************************************************************** /*
* this is how the lowlevel part communicate with the outer world * this is how the lowlevel part communicate with the outer world
*/ */
@@ -322,8 +325,9 @@ extern int usb_set_interface(struct usb_device *dev, int interface, int alternat
* specification, so that much of the uhci driver can just mask the bits * specification, so that much of the uhci driver can just mask the bits
* appropriately. * appropriately.
*/ */
/* Create various pipes... */ /* Create various pipes... */
#define create_pipe(dev,endpoint) \ #define create_pipe(dev, endpoint) \
(((dev)->devnum << 8) | (endpoint << 15) | \ (((dev)->devnum << 8) | (endpoint << 15) | \
((dev)->speed << 26) | (dev)->maxpacketsize) ((dev)->speed << 26) | (dev)->maxpacketsize)
#define default_pipe(dev) ((dev)->speed << 26) #define default_pipe(dev) ((dev)->speed << 26)

View File

@@ -48,12 +48,9 @@
#include "bas_string.h" /* for memset() */ #include "bas_string.h" /* for memset() */
#include "pci.h" #include "pci.h"
//extern xQueueHandle queue_poll_hub;
#undef OHCI_USE_NPS /* force NoPowerSwitching mode */ #undef OHCI_USE_NPS /* force NoPowerSwitching mode */
#undef OHCI_VERBOSE_DEBUG /* not always helpful */ #undef OHCI_VERBOSE_DEBUG /* not always helpful */
#undef SHOW_INFO
#undef OHCI_FILL_TRACE #undef OHCI_FILL_TRACE
//#define DEBUG_OHCI //#define DEBUG_OHCI
@@ -62,6 +59,7 @@
#else #else
#define dbg(format, arg...) do { ; } while (0) #define dbg(format, arg...) do { ; } while (0)
#endif /* DEBUG_OHCI */ #endif /* DEBUG_OHCI */
#define err(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#include "usb.h" #include "usb.h"
#include "ohci.h" #include "ohci.h"
@@ -149,9 +147,6 @@ struct pci_device_id ohci_usb_pci_table[] =
} }
}; };
#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 */ /* global ohci_t */
static ohci_t gohci[2]; static ohci_t gohci[2];
int ohci_inited; int ohci_inited;
@@ -1080,8 +1075,10 @@ static void check_status(ohci_t *ohci, td_t *td_list)
} }
} }
/* replies to the request have to be on a FIFO basis so /*
* we reverse the reversed done-list */ * replies to the request have to be on a FIFO basis so
* we reverse the reversed done-list
*/
static td_t *dl_reverse_done_list(ohci_t *ohci) static td_t *dl_reverse_done_list(ohci_t *ohci)
{ {
uint32_t td_list_hc; uint32_t td_list_hc;
@@ -1089,19 +1086,25 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
td_t *td_list = NULL; td_t *td_list = NULL;
td_list_hc = swpl(ohci->hcca->done_head) & ~0xf; td_list_hc = swpl(ohci->hcca->done_head) & ~0xf;
if (td_list_hc) if (td_list_hc)
{
td_list_hc += ohci->dma_offset; td_list_hc += ohci->dma_offset;
}
ohci->hcca->done_head = 0; ohci->hcca->done_head = 0;
while (td_list_hc) while (td_list_hc)
{ {
td_list = (td_t *)td_list_hc; td_list = (td_t *) td_list_hc;
check_status(ohci, td_list); check_status(ohci, td_list);
td_list->next_dl_td = td_rev; td_list->next_dl_td = td_rev;
td_rev = td_list; td_rev = td_list;
td_list_hc = swpl(td_list->hwNextTD) & ~0xf; td_list_hc = swpl(td_list->hwNextTD) & ~0xf;
if (td_list_hc) if (td_list_hc)
{
td_list_hc += ohci->dma_offset; td_list_hc += ohci->dma_offset;
} }
}
return td_list; return td_list;
} }
@@ -1110,9 +1113,13 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status) static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status)
{ {
if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL)) if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL))
{
urb->finished = sohci_return_job(ohci, urb); urb->finished = sohci_return_job(ohci, urb);
}
else else
{
dbg("finish_urb: strange.., ED state %x, \r\n", status); dbg("finish_urb: strange.., ED state %x, \r\n", status);
}
} }
/* /*
@@ -1126,16 +1133,21 @@ static int takeback_td(ohci_t *ohci, td_t *td_list)
ed_t *ed; ed_t *ed;
int cc; int cc;
int stat = 0; int stat = 0;
/* urb_t *urb; */
urb_priv_t *lurb_priv; urb_priv_t *lurb_priv;
uint32_t tdINFO, edHeadP, edTailP; uint32_t tdINFO;
uint32_t edHeadP;
uint32_t edTailP;
tdINFO = swpl(td_list->hwINFO); tdINFO = swpl(td_list->hwINFO);
ed = td_list->ed; ed = td_list->ed;
if (ed == NULL) if (ed == NULL)
{ {
err("OHCI usb-%s-%c cannot get error code ED is null", ohci->slot_name, (char)ohci->controller + '0'); err("OHCI usb-%s-%c cannot get error code ED is null\r\n", ohci->slot_name, (char) ohci->controller + '0');
return stat; return stat;
} }
lurb_priv = ed->purb; lurb_priv = ed->purb;
dl_transfer_length(ohci, td_list); dl_transfer_length(ohci, td_list);
lurb_priv->td_cnt++; lurb_priv->td_cnt++;
@@ -1144,26 +1156,40 @@ static int takeback_td(ohci_t *ohci, td_t *td_list)
cc = TD_CC_GET(tdINFO); cc = TD_CC_GET(tdINFO);
if (cc) 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)\r\n", ohci->slot_name, (char) ohci->controller + '0', cc_to_string[cc], cc);
stat = cc_to_error[cc]; stat = cc_to_error[cc];
} }
/* see if this done list makes for all TD's of current URB, /*
* and mark the URB finished if so */ * see if this done list makes for all TD's of current URB,
* and mark the URB finished if so
*/
if (lurb_priv->td_cnt == lurb_priv->length) if (lurb_priv->td_cnt == lurb_priv->length)
{
finish_urb(ohci, lurb_priv, ed->state); finish_urb(ohci, lurb_priv, ed->state);
}
if (ohci->irq) if (ohci->irq)
dbg("dl_done_list: processing TD %x, len %x", lurb_priv->td_cnt, lurb_priv->length); {
dbg("dl_done_list: processing TD %x, len %x\r\n", lurb_priv->td_cnt, lurb_priv->length);
}
if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe))) if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe)))
{ {
edHeadP = swpl(ed->hwHeadP) & ~0xf; edHeadP = swpl(ed->hwHeadP) & ~0xf;
edTailP = swpl(ed->hwTailP); edTailP = swpl(ed->hwTailP);
/* unlink eds if they are not busy */ /* unlink eds if they are not busy */
if ((edHeadP == edTailP) && (ed->state == ED_OPER)) if ((edHeadP == edTailP) && (ed->state == ED_OPER))
{
ep_unlink(ohci, ed); ep_unlink(ohci, ed);
} }
}
if (cc && (ed->type == PIPE_INTERRUPT)) /* added, but it's not the better method */ if (cc && (ed->type == PIPE_INTERRUPT)) /* added, but it's not the better method */
{
ep_unlink(ohci, ed); ep_unlink(ohci, ed);
}
return stat; return stat;
} }
@@ -1171,9 +1197,11 @@ static int dl_done_list(ohci_t *ohci)
{ {
int stat = 0; int stat = 0;
td_t *td_list = dl_reverse_done_list(ohci); td_t *td_list = dl_reverse_done_list(ohci);
while (td_list) while (td_list)
{ {
td_t *td_next = td_list->next_dl_td; td_t *td_next = td_list->next_dl_td;
stat = takeback_td(ohci, td_list); stat = takeback_td(ohci, td_list);
td_list = td_next; td_list = td_next;
} }
@@ -1289,10 +1317,10 @@ static unsigned char root_hub_str_index1[] =
#define OK(x) len = (x); break #define OK(x) len = (x); break
#ifdef DEBUG_OHCI #ifdef DEBUG_OHCI
#define WR_RH_STAT(x) { info("WR:status %#8x", (x)); writel((x), &ohci->regs->roothub.status); } #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]); } #define WR_RH_PORTSTAT(x) { info("WR:portstatus[%d] %#8x", wIndex - 1, (x)); writel((x), &ohci->regs->roothub.portstatus[wIndex - 1]); }
#else #else
#define WR_RH_STAT(x) { writel((x), &ohci->regs->roothub.status); } #define WR_RH_STAT(x) { writel((x), &ohci->regs->roothub.status); }
#define WR_RH_PORTSTAT(x) { writel((x), &ohci->regs->roothub.portstatus[wIndex-1]); } #define WR_RH_PORTSTAT(x) { writel((x), &ohci->regs->roothub.portstatus[wIndex - 1]); }
#endif #endif
#define RD_RH_STAT roothub_status(ohci) #define RD_RH_STAT roothub_status(ohci)
#define RD_RH_PORTSTAT roothub_portstatus(ohci, wIndex-1) #define RD_RH_PORTSTAT roothub_portstatus(ohci, wIndex-1)
@@ -1309,12 +1337,14 @@ int rh_check_port_status(ohci_t *controller)
for (i = 0; i < ndp; i++) for (i = 0; i < ndp; i++)
{ {
temp = roothub_portstatus(controller, i); temp = roothub_portstatus(controller, i);
/* check for a device disconnect */ /* check for a device disconnect */
if (((temp & (RH_PS_PESC | RH_PS_CSC)) == (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0)) if (((temp & (RH_PS_PESC | RH_PS_CSC)) == (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0))
{ {
res = i; res = i;
break; break;
} }
/* check for a device connect */ /* check for a device connect */
if ((temp & RH_PS_CSC) && (temp & RH_PS_CCS)) if ((temp & RH_PS_CSC) && (temp & RH_PS_CCS))
{ {
@@ -1343,49 +1373,60 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
#else #else
if (ohci->irq) if (ohci->irq)
{
wait(1 * 1000); wait(1 * 1000);
}
#endif #endif
if (usb_pipeint(pipe)) if (usb_pipeint(pipe))
{ {
info("Root-Hub submit IRQ: NOT implemented"); err("Root-Hub submit IRQ: NOT implemented");
return 0; return 0;
} }
bmRType_bReq = cmd->requesttype | (cmd->request << 8); bmRType_bReq = cmd->requesttype | (cmd->request << 8);
wValue = swpw(cmd->value); wValue = swpw(cmd->value);
wIndex = swpw(cmd->index); wIndex = swpw(cmd->index);
wLength = swpw(cmd->length); wLength = swpw(cmd->length);
info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); dbg("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x\r\n", dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
switch (bmRType_bReq) switch (bmRType_bReq)
{ {
/* Request Destination: /*
without flags: Device, * Request Destination:
RH_INTERFACE: interface, * without flags: Device,
RH_ENDPOINT: endpoint, * RH_INTERFACE: interface,
RH_CLASS means HUB here, * RH_ENDPOINT: endpoint,
RH_OTHER | RH_CLASS almost ever means HUB_PORT here * RH_CLASS means HUB here,
* RH_OTHER | RH_CLASS almost ever means HUB_PORT here
*/ */
case RH_GET_STATUS: case RH_GET_STATUS:
*(uint16_t *)data_buf = swpw(1); *(uint16_t *) data_buf = swpw(1);
OK(2); OK(2);
case RH_GET_STATUS | RH_INTERFACE: case RH_GET_STATUS | RH_INTERFACE:
*(uint16_t *)data_buf = swpw(0); *(uint16_t *)data_buf = swpw(0);
OK(2); OK(2);
case RH_GET_STATUS | RH_ENDPOINT: case RH_GET_STATUS | RH_ENDPOINT:
*(uint16_t *)data_buf = swpw(0); *(uint16_t *)data_buf = swpw(0);
OK(2); OK(2);
case RH_GET_STATUS | RH_CLASS: case RH_GET_STATUS | RH_CLASS:
*(uint32_t *)data_buf = swpl(RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); *(uint32_t *)data_buf = swpl(RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
OK(4); OK(4);
case RH_GET_STATUS | RH_OTHER | RH_CLASS: case RH_GET_STATUS | RH_OTHER | RH_CLASS:
*(uint32_t *)data_buf = swpl(RD_RH_PORTSTAT); *(uint32_t *)data_buf = swpl(RD_RH_PORTSTAT);
OK(4); OK(4);
case RH_CLEAR_FEATURE | RH_ENDPOINT: case RH_CLEAR_FEATURE | RH_ENDPOINT:
switch (wValue) switch (wValue)
{ {
case (RH_ENDPOINT_STALL): OK(0); case (RH_ENDPOINT_STALL): OK(0);
} }
break; break;
case RH_CLEAR_FEATURE | RH_CLASS: case RH_CLEAR_FEATURE | RH_CLASS:
switch (wValue) switch (wValue)
{ {
@@ -1393,6 +1434,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
case (RH_C_HUB_OVER_CURRENT): WR_RH_STAT(RH_HS_OCIC); OK(0); case (RH_C_HUB_OVER_CURRENT): WR_RH_STAT(RH_HS_OCIC); OK(0);
} }
break; break;
case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
switch (wValue) switch (wValue)
{ {
@@ -1406,6 +1448,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
case (RH_C_PORT_RESET): WR_RH_PORTSTAT(RH_PS_PRSC); OK(0); case (RH_C_PORT_RESET): WR_RH_PORTSTAT(RH_PS_PRSC); OK(0);
} }
break; break;
case RH_SET_FEATURE | RH_OTHER | RH_CLASS: case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
switch (wValue) switch (wValue)
{ {
@@ -1426,9 +1469,11 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
OK(0); OK(0);
} }
break; break;
case RH_SET_ADDRESS: case RH_SET_ADDRESS:
ohci->rh.devnum = wValue; ohci->rh.devnum = wValue;
OK(0); OK(0);
case RH_GET_DESCRIPTOR: case RH_GET_DESCRIPTOR:
switch ((wValue & 0xff00) >> 8) switch ((wValue & 0xff00) >> 8)
{ {
@@ -1436,10 +1481,12 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_dev_des), wLength)); len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_dev_des), wLength));
data_buf = root_hub_dev_des; data_buf = root_hub_dev_des;
OK(len); OK(len);
case(0x02): /* configuration descriptor */ case(0x02): /* configuration descriptor */
len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_config_des), wLength)); len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_config_des), wLength));
data_buf = root_hub_config_des; data_buf = root_hub_config_des;
OK(len); OK(len);
case(0x03): /* string descriptors */ case(0x03): /* string descriptors */
if (wValue == 0x0300) if (wValue == 0x0300)
{ {
@@ -1453,10 +1500,12 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
data_buf = root_hub_str_index1; data_buf = root_hub_str_index1;
OK(len); OK(len);
} }
default: default:
stat = USB_ST_STALLED; stat = USB_ST_STALLED;
} }
break; break;
case RH_GET_DESCRIPTOR | RH_CLASS: case RH_GET_DESCRIPTOR | RH_CLASS:
{ {
uint32_t temp = roothub_a(ohci); uint32_t temp = roothub_a(ohci);
@@ -1465,30 +1514,44 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
// data_buf[2] = temp & RH_A_NDP; // data_buf[2] = temp & RH_A_NDP;
data_buf[2] = (uint8_t)ohci->ndp; data_buf[2] = (uint8_t)ohci->ndp;
data_buf[3] = 0; data_buf[3] = 0;
if (temp & RH_A_PSM) /* per-port power switching? */ if (temp & RH_A_PSM) /* per-port power switching? */
{
data_buf[3] |= 0x1; data_buf[3] |= 0x1;
}
if (temp & RH_A_NOCP) /* no overcurrent reporting? */ if (temp & RH_A_NOCP) /* no overcurrent reporting? */
{
data_buf[3] |= 0x10; data_buf[3] |= 0x10;
}
else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */
{
data_buf[3] |= 0x8; data_buf[3] |= 0x8;
}
/* corresponds to data_buf[4-7] */ /* corresponds to data_buf[4-7] */
datab[1] = 0; datab[1] = 0;
data_buf[5] = (temp & RH_A_POTPGT) >> 24; data_buf[5] = (temp & RH_A_POTPGT) >> 24;
temp = roothub_b(ohci); temp = roothub_b(ohci);
data_buf[7] = temp & RH_B_DR; data_buf[7] = temp & RH_B_DR;
if (data_buf[2] < 7) if (data_buf[2] < 7)
{
data_buf[8] = 0xff; data_buf[8] = 0xff;
}
else else
{ {
data_buf[0] += 2; data_buf[0] += 2;
data_buf[8] = (temp & RH_B_DR) >> 8; data_buf[8] = (temp & RH_B_DR) >> 8;
data_buf[10] = data_buf[9] = 0xff; data_buf[10] = data_buf[9] = 0xff;
} }
len = min_t(unsigned int, leni, min_t(unsigned int, data_buf [0], wLength)); len = min_t(unsigned int, leni, min_t(unsigned int, data_buf[0], wLength));
OK(len); OK(len);
} }
case RH_GET_CONFIGURATION: *(uint8_t *) data_buf = 0x01; OK(1); case RH_GET_CONFIGURATION: *(uint8_t *) data_buf = 0x01; OK(1);
case RH_SET_CONFIGURATION: WR_RH_STAT(0x10000); OK(0); case RH_SET_CONFIGURATION: WR_RH_STAT(0x10000); OK(0);
default: default:
dbg("unsupported root hub command"); dbg("unsupported root hub command");
stat = USB_ST_STALLED; stat = USB_ST_STALLED;
@@ -1497,25 +1560,38 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
ohci_dump_roothub(ohci, 1); ohci_dump_roothub(ohci, 1);
#else #else
if (ohci->irq) if (ohci->irq)
{
wait(1 * 1000); wait(1 * 1000);
}
#endif #endif
len = min_t(int, len, leni); len = min_t(int, len, leni);
if (data != data_buf) if (data != data_buf)
{
memcpy(data, data_buf, len); memcpy(data, data_buf, len);
}
dev->act_len = len; dev->act_len = len;
dev->status = stat; dev->status = stat;
#ifdef DEBUG_OHCI #ifdef DEBUG_OHCI
pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
#else #else
if (ohci->irq) if (ohci->irq)
{
wait(1 * 1000); wait(1 * 1000);
}
#endif #endif
return stat; return stat;
} }
/*-------------------------------------------------------------------------*/
/* common code for handling submit messages - used for all but root hub accesses. */ /*
* common code for handling submit messages - used for all but root hub accesses.
*/
static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, void *buffer, static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, void *buffer,
int transfer_len, struct devrequest *setup, int interval) int transfer_len, struct devrequest *setup, int interval)
@@ -1523,14 +1599,16 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
int stat = 0; int stat = 0;
int maxsize = usb_maxpacket(dev, pipe); int maxsize = usb_maxpacket(dev, pipe);
int timeout; int timeout;
urb_priv_t *urb = (urb_priv_t *) driver_mem_alloc(sizeof(urb_priv_t)); urb_priv_t *urb = driver_mem_alloc(sizeof(urb_priv_t));
if (urb == NULL) if (urb == NULL)
{ {
err("submit_common_msg malloc failed"); err("submit_common_msg driver_mem_alloc() failed\r\n");
return -1; return -1;
} }
memset(urb, 0, sizeof(urb_priv_t)); memset(urb, 0, sizeof(urb_priv_t));
urb->dev = dev; urb->dev = dev;
urb->pipe = pipe; urb->pipe = pipe;
urb->transfer_buffer = buffer; urb->transfer_buffer = buffer;
@@ -1541,6 +1619,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
if (ohci->devgone == dev) if (ohci->devgone == dev)
{ {
dev->status = USB_ST_CRC_ERR; dev->status = USB_ST_CRC_ERR;
dbg("device is gone...\r\n");
return 0; return 0;
} }
#ifdef DEBUG_OHCI #ifdef DEBUG_OHCI
@@ -1548,18 +1627,20 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
#else #else
if (ohci->irq) if (ohci->irq)
{
wait(1 * 1000); wait(1 * 1000);
}
#endif #endif
if (!maxsize) if (!maxsize)
{ {
err("submit_common_message: pipesize for pipe %lx is zero", pipe); err("submit_common_message: pipesize for pipe %lx is zero\r\n", pipe);
return -1; return -1;
} }
if (sohci_submit_job(ohci, urb, setup) < 0) if (sohci_submit_job(ohci, urb, setup) < 0)
{ {
err("sohci_submit_job failed"); err("sohci_submit_job failed\r\n");
return -1; return -1;
} }
@@ -1567,22 +1648,31 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
wait(10 * 1000); wait(10 * 1000);
/* ohci_dump_status(ohci); */ /* ohci_dump_status(ohci); */
#endif #endif
/* allow more time for a BULK device to react - some are slow */ /* allow more time for a BULK device to react - some are slow */
#define BULK_TO 5000 /* timeout in milliseconds */ #define BULK_TO 5000 /* timeout in milliseconds */
if (usb_pipebulk(pipe)) if (usb_pipebulk(pipe))
{
timeout = BULK_TO; timeout = BULK_TO;
}
else else
{
timeout = 1000; timeout = 1000;
}
/* wait for it to complete */ /* wait for it to complete */
while (ohci->irq) while (ohci->irq)
{ {
/* check whether the controller is done */ /* check whether the controller is done */
flush_data_cache(ohci); flush_data_cache(ohci);
#ifndef CONFIG_USB_INTERRUPT_POLLING #ifndef CONFIG_USB_INTERRUPT_POLLING
if (ohci->irq_enabled) if (ohci->irq_enabled)
{
stat = ohci->stat_irq; stat = ohci->stat_irq;
}
else else
#endif #endif
stat = hc_interrupt(ohci); stat = hc_interrupt(ohci);
@@ -1638,7 +1728,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
/* submit routines called from usb.c */ /* submit routines called from usb.c */
int ohci_submit_bulk_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len) int ohci_submit_bulk_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len)
{ {
info("submit_bulk_msg dev 0x%p ohci 0x%p buffer 0x%p len %d", dev, dev->priv_hcd, buffer, transfer_len); err("submit_bulk_msg dev 0x%p ohci 0x%p buffer 0x%p len %d", dev, dev->priv_hcd, buffer, transfer_len);
return submit_common_msg((ohci_t *)dev->priv_hcd, dev, pipe, buffer, transfer_len, NULL, 0); return submit_common_msg((ohci_t *)dev->priv_hcd, dev, pipe, buffer, transfer_len, NULL, 0);
} }
@@ -1646,12 +1736,16 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
{ {
ohci_t *ohci = (ohci_t *)dev->priv_hcd; ohci_t *ohci = (ohci_t *)dev->priv_hcd;
int maxsize = usb_maxpacket(dev, pipe); int maxsize = usb_maxpacket(dev, pipe);
info("submit_control_msg dev 0x%p ohci 0x%p", dev, ohci);
dbg("submit_control_msg dev 0x%p ohci 0x%p\r\n", dev, ohci);
#ifdef DEBUG_OHCI #ifdef DEBUG_OHCI
pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
#else #else
if (ohci->irq) if (ohci->irq)
{
wait(1 * 1000); wait(1 * 1000);
}
#endif #endif
if (!maxsize) if (!maxsize)
@@ -1663,6 +1757,7 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
if (((pipe >> 8) & 0x7f) == ohci->rh.devnum) if (((pipe >> 8) & 0x7f) == ohci->rh.devnum)
{ {
ohci->rh.dev = dev; ohci->rh.dev = dev;
/* root hub - redirect */ /* root hub - redirect */
return ohci_submit_rh_msg(ohci, dev, pipe, buffer, transfer_len, setup); return ohci_submit_rh_msg(ohci, dev, pipe, buffer, transfer_len, setup);
} }
@@ -1671,7 +1766,7 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
int ohci_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval) int ohci_submit_int_msg(struct usb_device *dev, uint32_t pipe, void *buffer, int transfer_len, int interval)
{ {
info("submit_int_msg dev 0x%p ohci 0x%p buffer 0x%p len %d", dev, dev->priv_hcd, buffer, transfer_len); err("submit_int_msg dev 0x%p ohci 0x%p buffer 0x%p len %d", dev, dev->priv_hcd, buffer, transfer_len);
return submit_common_msg((ohci_t *)dev->priv_hcd, dev, pipe, buffer, transfer_len, NULL, interval); return submit_common_msg((ohci_t *)dev->priv_hcd, dev, pipe, buffer, transfer_len, NULL, interval);
} }
@@ -1769,7 +1864,7 @@ static int hc_reset(ohci_t *ohci)
{ {
/* SMM owns the HC */ /* SMM owns the HC */
writel(OHCI_OCR, &ohci->regs->cmdstatus);/* request ownership */ writel(OHCI_OCR, &ohci->regs->cmdstatus);/* request ownership */
info("USB HC TakeOver from SMM"); err("USB HC TakeOver from SMM");
while (readl(&ohci->regs->control) & OHCI_CTRL_IR) while (readl(&ohci->regs->control) & OHCI_CTRL_IR)
{ {
wait(10); wait(10);
@@ -1895,21 +1990,26 @@ void ohci_usb_event_poll(int interrupt)
#endif /* CONFIG_USB_INTERRUPT_POLLING */ #endif /* CONFIG_USB_INTERRUPT_POLLING */
/* an interrupt happens */ /*
* an interrupt happens
*/
static int hc_interrupt(ohci_t *ohci) static int hc_interrupt(ohci_t *ohci)
{ {
struct ohci_regs *regs = ohci->regs; struct ohci_regs *regs = ohci->regs;
int ints, stat = -1; int ints;
int stat = -1;
if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01)) if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01))
{
ints = OHCI_INTR_WDH; ints = OHCI_INTR_WDH;
}
else else
{ {
ints = readl(&regs->intrstatus); ints = readl(&regs->intrstatus);
if (ints == ~(uint32_t) 0) if (ints == ~ 0UL)
{ {
ohci->disabled++; ohci->disabled++;
err("OHCI usb-%s-%c device removed!", ohci->slot_name, (char)ohci->controller + '0'); err("OHCI usb-%s-%c device removed!\r\n", ohci->slot_name, (char) ohci->controller + '0');
return -1; return -1;
} }
else else
@@ -1917,14 +2017,17 @@ static int hc_interrupt(ohci_t *ohci)
ints &= readl(&regs->intrenable); ints &= readl(&regs->intrenable);
if (ints == 0) if (ints == 0)
{ {
// dbg("hc_interrupt: returning..\r\n"); dbg("no interrupt...\r\n");
return 0xff; return 0xff;
} }
} }
} }
if (ohci->irq) if (ohci->irq)
dbg("Interrupt: 0x%x frame: 0x%x bus: %d", ints, swpw(ohci->hcca->frame_no), ohci->controller); {
dbg("Interrupt: 0x%x frame: 0x%x bus: %d\r\n", ints, swpw(ohci->hcca->frame_no), ohci->controller);
}
if (ints & OHCI_INTR_RHSC) /* root hub status change */ if (ints & OHCI_INTR_RHSC) /* root hub status change */
{ {
@@ -1950,7 +2053,7 @@ static int hc_interrupt(ohci_t *ohci)
(void) status; (void) status;
err("OHCI Unrecoverable Error, controller usb-%s-%c disabled\r\n(SR:0x%04X%s%s%s%s%s%s)", err("OHCI Unrecoverable Error, controller usb-%s-%c disabled\r\n(SR:0x%04X%s%s%s%s%s%s)",
ohci->slot_name, (char)ohci->controller + '0', status & 0xFFFF, ohci->slot_name, (char) ohci->controller + '0', status & 0xFFFF,
status & 0x8000 ? ", Parity error" : "", status & 0x8000 ? ", Parity error" : "",
status & 0x4000 ? ", Signaled system error" : "", status & 0x4000 ? ", Signaled system error" : "",
status & 0x2000 ? ", Received master abort" : "", status & 0x2000 ? ", Received master abort" : "",
@@ -1962,18 +2065,24 @@ static int hc_interrupt(ohci_t *ohci)
ohci_dump(ohci, 1); ohci_dump(ohci, 1);
#else #else
if (ohci->irq) if (ohci->irq)
{
wait(1); wait(1);
}
#endif #endif
/* HC Reset */ /* HC Reset */
ohci->hc_control = 0; ohci->hc_control = 0;
writel(ohci->hc_control, &ohci->regs->control); writel(ohci->hc_control, &ohci->regs->control);
return -1; return -1;
} }
if (ints & OHCI_INTR_WDH) if (ints & OHCI_INTR_WDH)
{ {
if (ohci->irq) if (ohci->irq)
{
wait(1); wait(1);
}
writel(OHCI_INTR_WDH, &regs->intrdisable); writel(OHCI_INTR_WDH, &regs->intrdisable);
(void) readl(&regs->intrdisable); /* flush */ (void) readl(&regs->intrdisable); /* flush */
stat = dl_done_list(ohci); stat = dl_done_list(ohci);
@@ -2086,13 +2195,13 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
else if (!ohci->handle) /* for restart USB cmd */ else if (!ohci->handle) /* for restart USB cmd */
return(-1); return(-1);
info("ohci %p", ohci); err("ohci %p", ohci);
ohci->controller = PCI_FUNCTION_FROM_HANDLE(ohci->handle); ohci->controller = PCI_FUNCTION_FROM_HANDLE(ohci->handle);
// ohci->controller = (ohci->handle >> 16) & 3; /* PCI function */ // ohci->controller = (ohci->handle >> 16) & 3; /* PCI function */
/* this must be aligned to a 256 byte boundary */ /* this must be aligned to a 256 byte boundary */
ohci->hcca_unaligned = (struct ohci_hcca *) driver_mem_alloc(sizeof(struct ohci_hcca) + 256); ohci->hcca_unaligned = driver_mem_alloc(sizeof(struct ohci_hcca) + 256);
if (ohci->hcca_unaligned == NULL) if (ohci->hcca_unaligned == NULL)
{ {
err("HCCA malloc failed"); err("HCCA malloc failed");
@@ -2102,8 +2211,8 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
/* align the storage */ /* align the storage */
ohci->hcca = (struct ohci_hcca *) (((uint32_t) ohci->hcca_unaligned + 255) & ~255); ohci->hcca = (struct ohci_hcca *) (((uint32_t) ohci->hcca_unaligned + 255) & ~255);
memset(ohci->hcca, 0, sizeof(struct ohci_hcca)); memset(ohci->hcca, 0, sizeof(struct ohci_hcca));
info("aligned ghcca %p", ohci->hcca); err("aligned ghcca %p", ohci->hcca);
ohci->ohci_dev_unaligned = (struct ohci_device *) driver_mem_alloc(sizeof(struct ohci_device) + 8); ohci->ohci_dev_unaligned = driver_mem_alloc(sizeof(struct ohci_device) + 8);
if (ohci->ohci_dev_unaligned == NULL) if (ohci->ohci_dev_unaligned == NULL)
{ {
err("EDs malloc failed"); err("EDs malloc failed");
@@ -2112,9 +2221,9 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
} }
ohci->ohci_dev = (struct ohci_device *) (((uint32_t) ohci->ohci_dev_unaligned + 7) & ~7); ohci->ohci_dev = (struct ohci_device *) (((uint32_t) ohci->ohci_dev_unaligned + 7) & ~7);
memset(ohci->ohci_dev, 0, sizeof(struct ohci_device)); memset(ohci->ohci_dev, 0, sizeof(struct ohci_device));
info("aligned EDs %p", ohci->ohci_dev); err("aligned EDs %p", ohci->ohci_dev);
ohci->td_unaligned = (struct td *) driver_mem_alloc(sizeof(struct td) * (NUM_TD + 1)); ohci->td_unaligned = driver_mem_alloc(sizeof(struct td) * (NUM_TD + 1));
if (ohci->td_unaligned == NULL) if (ohci->td_unaligned == NULL)
{ {
err("TDs malloc failed"); err("TDs malloc failed");
@@ -2126,7 +2235,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
dbg("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); memset(ptd, 0, sizeof(td_t) * NUM_TD);
info("aligned TDs %p", ptd); err("aligned TDs %p", ptd);
ohci->disabled = 1; ohci->disabled = 1;
ohci->sleeping = 0; ohci->sleeping = 0;

View File

@@ -78,19 +78,26 @@ static int num_pci_classes = sizeof(pci_classes) / sizeof(struct pci_class);
/* holds the handle of a card at position = array index */ /* holds the handle of a card at position = array index */
static int32_t handles[NUM_CARDS]; static int32_t handles[NUM_CARDS];
/* holds the interrupt handler addresses (see pci_hook_interrupt() and pci_unhook_interrupt()) of the PCI cards */
struct pci_interrupt
{
void (*handler)(void);
int32_t parameter;
struct pci_interrupt *next;
};
#define MAX_INTERRUPTS (NUM_CARDS * 3)
static struct pci_interrupt interrupts[MAX_INTERRUPTS];
/* holds the card's resource descriptors; filled in pci_device_config() */ /* holds the card's resource descriptors; filled in pci_device_config() */
static struct pci_rd resource_descriptors[NUM_CARDS][NUM_RESOURCES]; static struct pci_rd resource_descriptors[NUM_CARDS][NUM_RESOURCES];
typedef int (*pci_interrupt_handler)(int param);
/*
* holds the interrupt handler addresses (see pci_hook_interrupt()
* and pci_unhook_interrupt()) of the PCI cards
*/
struct pci_interrupt
{
int32_t handle;
int irq;
pci_interrupt_handler handler;
int32_t parameter;
struct pci_interrupt *next;
};
#define MAX_INTERRUPTS (NUM_CARDS * 3)
static struct pci_interrupt interrupts[MAX_INTERRUPTS];
__attribute__((aligned(16))) void chip_errata_135(void) __attribute__((aligned(16))) void chip_errata_135(void)
{ {
@@ -154,15 +161,23 @@ __attribute__((interrupt)) void pci_interrupt(void)
*/ */
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
static int32_t pci_get_interrupt_cause(int32_t *handles) static int32_t pci_get_interrupt_cause(int32_t *handles)
{ {
int32_t handle; int32_t handle;
/*
* loop through all PCI devices...
*/
while ((handle = *handles++) != -1) while ((handle = *handles++) != -1)
{ {
uint32_t csr = swpl(pci_read_config_longword(handle, PCICSR)); uint16_t command_register = swpw(pci_read_config_word(handle, PCICR));
uint16_t status_register = swpw(pci_read_config_word(handle, PCISR));
if ((csr & (1 << 3)) && (csr & !(csr & (1 << 10)))) /*
* ...to see which device caused the interrupt
*/
if ((status_register & PCICSR_INTERRUPT) && !(command_register & PCICSR_INT_DISABLE))
{ {
/* device has interrupts enabled and has an active interrupt, so its probably ours */ /* device has interrupts enabled and has an active interrupt, so its probably ours */
@@ -175,11 +190,21 @@ static int32_t pci_get_interrupt_cause(int32_t *handles)
static int32_t pci_call_interrupt_chain(int32_t handle, int32_t data) static int32_t pci_call_interrupt_chain(int32_t handle, int32_t data)
{ {
int i;
for (i = 0; i < MAX_INTERRUPTS; i++)
{
if (interrupts[i].handle == handle)
{
interrupts[i].handler(data);
return 1;
}
}
return data; /* unmodified - means: not handled */ return data; /* unmodified - means: not handled */
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#ifdef MACHINE_M5484LITE
/* /*
* This gets called from irq5 in exceptions.S * This gets called from irq5 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved * Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
@@ -191,7 +216,9 @@ void irq5_handler(void)
int32_t newvalue; int32_t newvalue;
MCF_EPORT_EPFR |= (1 << 5); /* clear interrupt from edge port */ MCF_EPORT_EPFR |= (1 << 5); /* clear interrupt from edge port */
xprintf("IRQ5!\r\n"); xprintf("IRQ5!\r\n");
if ((handle = pci_get_interrupt_cause(handles)) > 0) if ((handle = pci_get_interrupt_cause(handles)) > 0)
{ {
newvalue = pci_call_interrupt_chain(handle, value); newvalue = pci_call_interrupt_chain(handle, value);
@@ -202,6 +229,7 @@ void irq5_handler(void)
} }
} }
#ifdef MACHINE_M5484LITE
/* /*
* This gets called from irq7 in exceptions.S * This gets called from irq7 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved * Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
@@ -580,19 +608,41 @@ int32_t pci_find_classcode(uint32_t classcode, int index)
return PCI_DEVICE_NOT_FOUND; return PCI_DEVICE_NOT_FOUND;
} }
int32_t pci_hook_interrupt(int32_t handle, void *handler, void *parameter) int32_t pci_hook_interrupt(int32_t handle, pci_interrupt_handler handler, void *parameter)
{ {
/* FIXME: implement */ int i;
dbg("pci_hook_interrupt() still not implemented\r\n");
/*
* find empty slot
*/
for (i = 0; i < MAX_INTERRUPTS; i++)
{
if (interrupts[i].handle == 0)
{
interrupts[i].handle = handle;
interrupts[i].handler = handler;
interrupts[i].parameter = (int32_t) parameter;
return PCI_SUCCESSFUL; return PCI_SUCCESSFUL;
}
}
return PCI_BUFFER_TOO_SMALL;
} }
int32_t pci_unhook_interrupt(int32_t handle) int32_t pci_unhook_interrupt(int32_t handle)
{ {
/* FIXME: implement */ int i;
for (i = 0; i < MAX_INTERRUPTS; i++)
{
if (interrupts[i].handle == handle)
{
memset(&interrupts[i], 0, sizeof(struct pci_interrupt));
dbg("pci_unhook_interrupt() still not implemented\r\n");
return PCI_SUCCESSFUL; return PCI_SUCCESSFUL;
}
}
return PCI_DEVICE_NOT_FOUND;
} }
/* /*

View File

@@ -429,7 +429,7 @@ irq7text:
.text .text
#elif MACHINE_FIREBEE /* these handlers are only meaningful for the Firebee */ #elif MACHINE_FIREBEE /* these handlers are only meaningful for the Firebee */
irq5: // irq5 is tied to PCI INTC# and PCI INTD# on the M5484LITE irq5:
irq 0x74,5,0x20 irq 0x74,5,0x20
irq6: // MFP interrupt from FPGA irq6: // MFP interrupt from FPGA
@@ -466,6 +466,22 @@ irq6_1:
bne irq6_2 bne irq6_2
lea MCF_GPIO_PODR_FEC1L,a5 lea MCF_GPIO_PODR_FEC1L,a5
bset.b #4,(a5) // led off bset.b #4,(a5) // led off
/*
* Firebee inthandler. 0xf0020000 delivers the interrupt vector
*
* 0: PIC_INT
* 1: E0_INT
* 2: DVI_INT
* 3: PCI_INT#A
* 4: PCI_INT#B
* 5: PCI_INT#C
* 6: PCI_INT#D
* 7: DSP_INT
* 8: VSYNC
* 9: HSYNC
*/
irq6_2: irq6_2:
move.l 0xF0020000,a5 // vector holen move.l 0xF0020000,a5 // vector holen
add.l _rt_vbr,a5 // basis add.l _rt_vbr,a5 // basis

View File

@@ -54,9 +54,6 @@
#include "usb.h" #include "usb.h"
#include "usb_hub.h" #include "usb_hub.h"
extern int usb_stor_curr_dev;
extern uint32_t usb_1st_disk_drive;
//#define DEBUG_USB //#define DEBUG_USB
#ifdef DEBUG_USB #ifdef DEBUG_USB
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0) #define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
@@ -97,7 +94,10 @@ int usb_init(int32_t handle, const struct pci_device_id *ent)
struct hci *priv; struct hci *priv;
int res = 0; int res = 0;
if (bus_index >= USB_MAX_BUS) if (bus_index >= USB_MAX_BUS)
{
dbg("bus_index >= USB_MAX_BUS");
return -1; return -1;
}
dev_index[bus_index] = 0; dev_index[bus_index] = 0;
asynch_allowed = 1; asynch_allowed = 1;
@@ -107,21 +107,29 @@ int usb_init(int32_t handle, const struct pci_device_id *ent)
if (driver_mem_init()) if (driver_mem_init())
{ {
usb_started = 0; usb_started = 0;
dbg("driver_mem_init failed\r\n");
return -1; /* out of memory */ return -1; /* out of memory */
} }
if (usb_dev == NULL) if (usb_dev == NULL)
{
usb_dev = (struct usb_device *) driver_mem_alloc(sizeof(struct usb_device) * USB_MAX_BUS * USB_MAX_DEVICE); usb_dev = (struct usb_device *) driver_mem_alloc(sizeof(struct usb_device) * USB_MAX_BUS * USB_MAX_DEVICE);
}
if (usb_dev == NULL) if (usb_dev == NULL)
{ {
usb_started = 0; usb_started = 0;
dbg("could not allocate memory\r\n");
return -1; /* out of memory */ return -1; /* out of memory */
} }
} }
else /* restart */ else /* restart */
{ {
int i; int i;
res = 0; res = 0;
for (i = 0; i < USB_MAX_BUS; i++) for (i = 0; i < USB_MAX_BUS; i++)
{ {
@@ -131,7 +139,7 @@ int usb_init(int32_t handle, const struct pci_device_id *ent)
if (handle) if (handle)
{ {
res |= usb_init(handle, NULL); /* FIXME: recursive call! */ res |= usb_init(handle, NULL); /* FIXME: recursive call!? */
} }
} }
} }
@@ -176,6 +184,9 @@ int usb_init(int32_t handle, const struct pci_device_id *ent)
if (setup_packet == NULL) if (setup_packet == NULL)
{ {
usb_started = 0; usb_started = 0;
dbg("could not allocate memory\r\n");
return -1; /* no memory, no USB */ return -1; /* no memory, no USB */
} }
} }
@@ -306,11 +317,13 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
unsigned short value, unsigned short index, unsigned short value, unsigned short index,
void *data, unsigned short size, int timeout) void *data, unsigned short size, int timeout)
{ {
struct hci *priv = (struct hci *)dev->priv_hcd; struct hci *priv = (struct hci *) dev->priv_hcd;
if ((timeout == 0) && (!asynch_allowed)) if ((timeout == 0) && (!asynch_allowed))
{ {
/* request for a asynch control pipe is not allowed */ /* request for a asynch control pipe is not allowed */
dbg("request for an async control pipe is not allowed\r\n");
return -1; return -1;
} }
@@ -1064,7 +1077,9 @@ struct usb_device *usb_alloc_new_device(int bus_index, void *priv)
*/ */
int usb_new_device(struct usb_device *dev) int usb_new_device(struct usb_device *dev)
{ {
int addr, err, tmp; int addr;
int err;
int tmp;
unsigned char *tmpbuf; unsigned char *tmpbuf;
#ifndef CONFIG_LEGACY_USB_INIT_SEQ #ifndef CONFIG_LEGACY_USB_INIT_SEQ
@@ -1075,7 +1090,10 @@ int usb_new_device(struct usb_device *dev)
#endif #endif
if (dev == NULL) if (dev == NULL)
{
dbg("called with NULL device\r\n");
return 1; return 1;
}
/* We still haven't set the Address yet */ /* We still haven't set the Address yet */
addr = dev->devnum; addr = dev->devnum;
@@ -1084,7 +1102,7 @@ int usb_new_device(struct usb_device *dev)
tmpbuf = (unsigned char *) driver_mem_alloc(USB_BUFSIZ); tmpbuf = (unsigned char *) driver_mem_alloc(USB_BUFSIZ);
if (tmpbuf == NULL) if (tmpbuf == NULL)
{ {
dbg("usb_new_device: malloc failure\r\n"); dbg("malloc failure\r\n");
return 1; return 1;
} }
@@ -1125,6 +1143,7 @@ int usb_new_device(struct usb_device *dev)
*/ */
desc = (struct usb_device_descriptor *) tmpbuf; desc = (struct usb_device_descriptor *) tmpbuf;
dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */ dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */
/* Default to 64 byte max packet size */ /* Default to 64 byte max packet size */
dev->maxpacketsize = PACKET_SIZE_64; dev->maxpacketsize = PACKET_SIZE_64;
dev->epmaxpacketin[0] = 64; dev->epmaxpacketin[0] = 64;
@@ -1260,7 +1279,9 @@ int usb_new_device(struct usb_device *dev)
return 0; return 0;
} }
/* build device Tree */ /*
* build device Tree
*/
void usb_scan_devices(void *priv) void usb_scan_devices(void *priv)
{ {
int i; int i;
@@ -1274,7 +1295,9 @@ void usb_scan_devices(void *priv)
} }
dev_index[bus_index] = 0; dev_index[bus_index] = 0;
/* device 0 is always present (root hub, so let it analyze) */ /*
* device 0 is always present (root hub, so let it analyze)
*/
dev = usb_alloc_new_device(bus_index, priv); dev = usb_alloc_new_device(bus_index, priv);
if (usb_new_device(dev)) if (usb_new_device(dev))
{ {
@@ -1289,9 +1312,6 @@ void usb_scan_devices(void *priv)
xprintf("%d USB Device(s) found\r\n", dev_index[bus_index]); xprintf("%d USB Device(s) found\r\n", dev_index[bus_index]);
} }
{
#ifdef _NOT_USED_ /* not implemented yet */
/* insert "driver" if possible */ /* insert "driver" if possible */
if (drv_usb_kbd_init() < 0) if (drv_usb_kbd_init() < 0)
{ {
@@ -1301,7 +1321,6 @@ void usb_scan_devices(void *priv)
{ {
xprintf("USB HID keyboard driver installed\r\n"); xprintf("USB HID keyboard driver installed\r\n");
} }
#endif /* _NOT_USED */
if (drv_usb_mouse_init() < 0) if (drv_usb_mouse_init() < 0)
{ {
@@ -1311,7 +1330,6 @@ void usb_scan_devices(void *priv)
{ {
xprintf("USB HID mouse driver installed\r\n"); xprintf("USB HID mouse driver installed\r\n");
} }
}
xprintf("Scan end\r\n"); xprintf("Scan end\r\n");
} }

1389
usb/usb_kbd.c Normal file

File diff suppressed because it is too large Load Diff