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
include/usb_hub.h
tos/Makefile
usb/usb_kbd.c

View File

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

View File

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

View File

@@ -3,10 +3,14 @@
#define PCI_ANY_ID (~0)
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 class, class_mask; /* (class,subclass,prog-if) triplet */
struct pci_device_id
{
unsigned long vendor; /* Vendor and device ID or PCI_ANY_ID*/
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 */
};
@@ -15,7 +19,8 @@ struct pci_device_id {
#define IEEE1394_MATCH_SPECIFIER_ID 0x0004
#define IEEE1394_MATCH_VERSION 0x0008
struct ieee1394_device_id {
struct ieee1394_device_id
{
unsigned long match_flags;
unsigned long vendor_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
* record quirks of specific products.
*/
struct usb_device_id {
struct usb_device_id
{
/* which fields to match against? */
unsigned short match_flags;
@@ -118,7 +124,8 @@ struct usb_device_id {
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
/* s390 CCW devices */
struct ccw_device_id {
struct ccw_device_id
{
unsigned short match_flags; /* which fields to match against */
unsigned short cu_type; /* control unit type */
@@ -138,15 +145,18 @@ struct ccw_device_id {
#define PNP_ID_LEN 8
#define PNP_MAX_DEVICES 8
struct pnp_device_id {
struct pnp_device_id
{
unsigned char id[PNP_ID_LEN];
unsigned long driver_data;
};
struct pnp_card_device_id {
struct pnp_card_device_id
{
unsigned char id[PNP_ID_LEN];
unsigned long driver_data;
struct {
struct
{
unsigned char id[PNP_ID_LEN];
} devs[PNP_MAX_DEVICES];
};
@@ -154,7 +164,8 @@ struct pnp_card_device_id {
#define SERIO_ANY 0xff
struct serio_device_id {
struct serio_device_id
{
unsigned char type;
unsigned char extra;
unsigned char id;

View File

@@ -31,7 +31,6 @@ static int cc_to_error[16] =
/* Not Access */ -1
};
#ifdef DEBUG_OHCI
static const char *cc_to_string[16] =
{
"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" \
"on a list to be processed by the HC.(2)",
};
#endif /* DEBUG_OHCI */
/* ED States */

View File

@@ -91,9 +91,12 @@
#define PCICSR_STEPPING (1 << 7) /* if set: stepping 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_INT_DISABLE (1 << 10) /* if set: disable interrupts from this device */
/*
* 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_UDF (1 << 6) /* UDF supported */
#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_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 struct pci_rd *pci_get_resource(int32_t handle);

View File

@@ -180,8 +180,10 @@ struct usb_device
/* Maximum packet size; one of: PACKET_SIZE_* */
int maxpacketsize;
/* one bit for each endpoint ([0] = IN, [1] = OUT) */
unsigned int toggle[2];
/* endpoint halts; one bit per endpoint # & direction;
* [0] = IN, [1] = OUT
*/
@@ -199,6 +201,7 @@ struct usb_device
uint32_t irq_status;
int irq_act_len; /* transfered bytes */
void *privptr;
/*
* Child devices - if this is a hub device
* Each instance needs its own set of data structures.
@@ -227,7 +230,7 @@ typedef struct
} v;
} USB_COOKIE;
/**********************************************************************
/*
* this is how the lowlevel part communicate with the outer world
*/
@@ -322,6 +325,7 @@ 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
* appropriately.
*/
/* Create various pipes... */
#define create_pipe(dev, endpoint) \
(((dev)->devnum << 8) | (endpoint << 15) | \

View File

@@ -48,12 +48,9 @@
#include "bas_string.h" /* for memset() */
#include "pci.h"
//extern xQueueHandle queue_poll_hub;
#undef OHCI_USE_NPS /* force NoPowerSwitching mode */
#undef OHCI_VERBOSE_DEBUG /* not always helpful */
#undef SHOW_INFO
#undef OHCI_FILL_TRACE
//#define DEBUG_OHCI
@@ -62,6 +59,7 @@
#else
#define dbg(format, arg...) do { ; } while (0)
#endif /* DEBUG_OHCI */
#define err(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#include "usb.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 */
static ohci_t gohci[2];
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)
{
uint32_t td_list_hc;
@@ -1089,8 +1086,12 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
td_t *td_list = NULL;
td_list_hc = swpl(ohci->hcca->done_head) & ~0xf;
if (td_list_hc)
{
td_list_hc += ohci->dma_offset;
}
ohci->hcca->done_head = 0;
while (td_list_hc)
{
@@ -1100,8 +1101,10 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
td_rev = td_list;
td_list_hc = swpl(td_list->hwNextTD) & ~0xf;
if (td_list_hc)
{
td_list_hc += ohci->dma_offset;
}
}
return td_list;
}
@@ -1110,10 +1113,14 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status)
{
if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL))
{
urb->finished = sohci_return_job(ohci, urb);
}
else
{
dbg("finish_urb: strange.., ED state %x, \r\n", status);
}
}
/*
* Used to take back a TD from the host controller. This would normally be
@@ -1126,16 +1133,21 @@ static int takeback_td(ohci_t *ohci, td_t *td_list)
ed_t *ed;
int cc;
int stat = 0;
/* urb_t *urb; */
urb_priv_t *lurb_priv;
uint32_t tdINFO, edHeadP, edTailP;
uint32_t tdINFO;
uint32_t edHeadP;
uint32_t edTailP;
tdINFO = swpl(td_list->hwINFO);
ed = td_list->ed;
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;
}
lurb_priv = ed->purb;
dl_transfer_length(ohci, td_list);
lurb_priv->td_cnt++;
@@ -1144,26 +1156,40 @@ 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)\r\n", ohci->slot_name, (char) ohci->controller + '0', cc_to_string[cc], 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)
{
finish_urb(ohci, lurb_priv, ed->state);
}
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)))
{
edHeadP = swpl(ed->hwHeadP) & ~0xf;
edTailP = swpl(ed->hwTailP);
/* unlink eds if they are not busy */
if ((edHeadP == edTailP) && (ed->state == ED_OPER))
{
ep_unlink(ohci, ed);
}
}
if (cc && (ed->type == PIPE_INTERRUPT)) /* added, but it's not the better method */
{
ep_unlink(ohci, ed);
}
return stat;
}
@@ -1171,9 +1197,11 @@ static int dl_done_list(ohci_t *ohci)
{
int stat = 0;
td_t *td_list = dl_reverse_done_list(ohci);
while (td_list)
{
td_t *td_next = td_list->next_dl_td;
stat = takeback_td(ohci, td_list);
td_list = td_next;
}
@@ -1309,12 +1337,14 @@ int rh_check_port_status(ohci_t *controller)
for (i = 0; i < ndp; i++)
{
temp = roothub_portstatus(controller, i);
/* check for a device disconnect */
if (((temp & (RH_PS_PESC | RH_PS_CSC)) == (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0))
{
res = i;
break;
}
/* check for a device connect */
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));
#else
if (ohci->irq)
{
wait(1 * 1000);
}
#endif
if (usb_pipeint(pipe))
{
info("Root-Hub submit IRQ: NOT implemented");
err("Root-Hub submit IRQ: NOT implemented");
return 0;
}
bmRType_bReq = cmd->requesttype | (cmd->request << 8);
wValue = swpw(cmd->value);
wIndex = swpw(cmd->index);
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)
{
/* Request Destination:
without flags: Device,
RH_INTERFACE: interface,
RH_ENDPOINT: endpoint,
RH_CLASS means HUB here,
RH_OTHER | RH_CLASS almost ever means HUB_PORT here
/*
* Request Destination:
* without flags: Device,
* RH_INTERFACE: interface,
* RH_ENDPOINT: endpoint,
* RH_CLASS means HUB here,
* RH_OTHER | RH_CLASS almost ever means HUB_PORT here
*/
case RH_GET_STATUS:
*(uint16_t *) data_buf = swpw(1);
OK(2);
case RH_GET_STATUS | RH_INTERFACE:
*(uint16_t *)data_buf = swpw(0);
OK(2);
case RH_GET_STATUS | RH_ENDPOINT:
*(uint16_t *)data_buf = swpw(0);
OK(2);
case RH_GET_STATUS | RH_CLASS:
*(uint32_t *)data_buf = swpl(RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE));
OK(4);
case RH_GET_STATUS | RH_OTHER | RH_CLASS:
*(uint32_t *)data_buf = swpl(RD_RH_PORTSTAT);
OK(4);
case RH_CLEAR_FEATURE | RH_ENDPOINT:
switch (wValue)
{
case (RH_ENDPOINT_STALL): OK(0);
}
break;
case RH_CLEAR_FEATURE | RH_CLASS:
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);
}
break;
case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
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);
}
break;
case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
switch (wValue)
{
@@ -1426,9 +1469,11 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
OK(0);
}
break;
case RH_SET_ADDRESS:
ohci->rh.devnum = wValue;
OK(0);
case RH_GET_DESCRIPTOR:
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));
data_buf = root_hub_dev_des;
OK(len);
case(0x02): /* configuration descriptor */
len = min_t(unsigned int, leni, min_t(unsigned int, sizeof(root_hub_config_des), wLength));
data_buf = root_hub_config_des;
OK(len);
case(0x03): /* string descriptors */
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;
OK(len);
}
default:
stat = USB_ST_STALLED;
}
break;
case RH_GET_DESCRIPTOR | RH_CLASS:
{
uint32_t temp = roothub_a(ohci);
@@ -1465,19 +1514,30 @@ 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] = (uint8_t)ohci->ndp;
data_buf[3] = 0;
if (temp & RH_A_PSM) /* per-port power switching? */
{
data_buf[3] |= 0x1;
}
if (temp & RH_A_NOCP) /* no overcurrent reporting? */
{
data_buf[3] |= 0x10;
}
else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */
{
data_buf[3] |= 0x8;
}
/* corresponds to data_buf[4-7] */
datab[1] = 0;
data_buf[5] = (temp & RH_A_POTPGT) >> 24;
temp = roothub_b(ohci);
data_buf[7] = temp & RH_B_DR;
if (data_buf[2] < 7)
{
data_buf[8] = 0xff;
}
else
{
data_buf[0] += 2;
@@ -1487,8 +1547,11 @@ 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, data_buf[0], wLength));
OK(len);
}
case RH_GET_CONFIGURATION: *(uint8_t *) data_buf = 0x01; OK(1);
case RH_SET_CONFIGURATION: WR_RH_STAT(0x10000); OK(0);
default:
dbg("unsupported root hub command");
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);
#else
if (ohci->irq)
{
wait(1 * 1000);
}
#endif
len = min_t(int, len, leni);
if (data != data_buf)
{
memcpy(data, data_buf, len);
}
dev->act_len = len;
dev->status = stat;
#ifdef DEBUG_OHCI
pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/);
#else
if (ohci->irq)
{
wait(1 * 1000);
}
#endif
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,
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 maxsize = usb_maxpacket(dev, pipe);
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)
{
err("submit_common_msg malloc failed");
err("submit_common_msg driver_mem_alloc() failed\r\n");
return -1;
}
memset(urb, 0, sizeof(urb_priv_t));
urb->dev = dev;
urb->pipe = pipe;
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)
{
dev->status = USB_ST_CRC_ERR;
dbg("device is gone...\r\n");
return 0;
}
#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));
#else
if (ohci->irq)
{
wait(1 * 1000);
}
#endif
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;
}
if (sohci_submit_job(ohci, urb, setup) < 0)
{
err("sohci_submit_job failed");
err("sohci_submit_job failed\r\n");
return -1;
}
@@ -1567,22 +1648,31 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
wait(10 * 1000);
/* ohci_dump_status(ohci); */
#endif
/* allow more time for a BULK device to react - some are slow */
#define BULK_TO 5000 /* timeout in milliseconds */
if (usb_pipebulk(pipe))
{
timeout = BULK_TO;
}
else
{
timeout = 1000;
}
/* wait for it to complete */
while (ohci->irq)
{
/* check whether the controller is done */
flush_data_cache(ohci);
#ifndef CONFIG_USB_INTERRUPT_POLLING
if (ohci->irq_enabled)
{
stat = ohci->stat_irq;
}
else
#endif
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 */
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);
}
@@ -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;
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
pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe));
#else
if (ohci->irq)
{
wait(1 * 1000);
}
#endif
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)
{
ohci->rh.dev = dev;
/* root hub - redirect */
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)
{
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);
}
@@ -1769,7 +1864,7 @@ static int hc_reset(ohci_t *ohci)
{
/* SMM owns the HC */
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)
{
wait(10);
@@ -1895,21 +1990,26 @@ void ohci_usb_event_poll(int interrupt)
#endif /* CONFIG_USB_INTERRUPT_POLLING */
/* an interrupt happens */
/*
* an interrupt happens
*/
static int hc_interrupt(ohci_t *ohci)
{
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))
{
ints = OHCI_INTR_WDH;
}
else
{
ints = readl(&regs->intrstatus);
if (ints == ~(uint32_t) 0)
if (ints == ~ 0UL)
{
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;
}
else
@@ -1917,14 +2017,17 @@ static int hc_interrupt(ohci_t *ohci)
ints &= readl(&regs->intrenable);
if (ints == 0)
{
// dbg("hc_interrupt: returning..\r\n");
dbg("no interrupt...\r\n");
return 0xff;
}
}
}
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 */
{
@@ -1962,18 +2065,24 @@ static int hc_interrupt(ohci_t *ohci)
ohci_dump(ohci, 1);
#else
if (ohci->irq)
{
wait(1);
}
#endif
/* HC Reset */
ohci->hc_control = 0;
writel(ohci->hc_control, &ohci->regs->control);
return -1;
}
if (ints & OHCI_INTR_WDH)
{
if (ohci->irq)
{
wait(1);
}
writel(OHCI_INTR_WDH, &regs->intrdisable);
(void) readl(&regs->intrdisable); /* flush */
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 */
return(-1);
info("ohci %p", ohci);
err("ohci %p", ohci);
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);
ohci->hcca_unaligned = driver_mem_alloc(sizeof(struct ohci_hcca) + 256);
if (ohci->hcca_unaligned == NULL)
{
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 */
ohci->hcca = (struct ohci_hcca *) (((uint32_t) ohci->hcca_unaligned + 255) & ~255);
memset(ohci->hcca, 0, sizeof(struct ohci_hcca));
info("aligned ghcca %p", ohci->hcca);
ohci->ohci_dev_unaligned = (struct ohci_device *) driver_mem_alloc(sizeof(struct ohci_device) + 8);
err("aligned ghcca %p", ohci->hcca);
ohci->ohci_dev_unaligned = driver_mem_alloc(sizeof(struct ohci_device) + 8);
if (ohci->ohci_dev_unaligned == NULL)
{
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);
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)
{
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);
memset(ptd, 0, sizeof(td_t) * NUM_TD);
info("aligned TDs %p", ptd);
err("aligned TDs %p", ptd);
ohci->disabled = 1;
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 */
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() */
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)
{
@@ -154,15 +161,23 @@ __attribute__((interrupt)) void pci_interrupt(void)
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
static int32_t pci_get_interrupt_cause(int32_t *handles)
{
int32_t handle;
/*
* loop through all PCI devices...
*/
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 */
@@ -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)
{
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 */
}
#pragma GCC diagnostic pop
#ifdef MACHINE_M5484LITE
/*
* 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
@@ -191,7 +216,9 @@ void irq5_handler(void)
int32_t newvalue;
MCF_EPORT_EPFR |= (1 << 5); /* clear interrupt from edge port */
xprintf("IRQ5!\r\n");
if ((handle = pci_get_interrupt_cause(handles)) > 0)
{
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
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
@@ -580,20 +608,42 @@ int32_t pci_find_classcode(uint32_t classcode, int index)
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 */
dbg("pci_hook_interrupt() still not implemented\r\n");
int i;
/*
* 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_BUFFER_TOO_SMALL;
}
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_DEVICE_NOT_FOUND;
}
/*
* Not implemented PCI_BIOS functions

View File

@@ -429,7 +429,7 @@ irq7text:
.text
#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
irq6: // MFP interrupt from FPGA
@@ -466,6 +466,22 @@ irq6_1:
bne irq6_2
lea MCF_GPIO_PODR_FEC1L,a5
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:
move.l 0xF0020000,a5 // vector holen
add.l _rt_vbr,a5 // basis

View File

@@ -54,9 +54,6 @@
#include "usb.h"
#include "usb_hub.h"
extern int usb_stor_curr_dev;
extern uint32_t usb_1st_disk_drive;
//#define DEBUG_USB
#ifdef DEBUG_USB
#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;
int res = 0;
if (bus_index >= USB_MAX_BUS)
{
dbg("bus_index >= USB_MAX_BUS");
return -1;
}
dev_index[bus_index] = 0;
asynch_allowed = 1;
@@ -107,21 +107,29 @@ int usb_init(int32_t handle, const struct pci_device_id *ent)
if (driver_mem_init())
{
usb_started = 0;
dbg("driver_mem_init failed\r\n");
return -1; /* out of memory */
}
if (usb_dev == NULL)
{
usb_dev = (struct usb_device *) driver_mem_alloc(sizeof(struct usb_device) * USB_MAX_BUS * USB_MAX_DEVICE);
}
if (usb_dev == NULL)
{
usb_started = 0;
dbg("could not allocate memory\r\n");
return -1; /* out of memory */
}
}
else /* restart */
{
int i;
res = 0;
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)
{
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)
{
usb_started = 0;
dbg("could not allocate memory\r\n");
return -1; /* no memory, no USB */
}
}
@@ -311,6 +322,8 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
if ((timeout == 0) && (!asynch_allowed))
{
/* request for a asynch control pipe is not allowed */
dbg("request for an async control pipe is not allowed\r\n");
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 addr, err, tmp;
int addr;
int err;
int tmp;
unsigned char *tmpbuf;
#ifndef CONFIG_LEGACY_USB_INIT_SEQ
@@ -1075,7 +1090,10 @@ int usb_new_device(struct usb_device *dev)
#endif
if (dev == NULL)
{
dbg("called with NULL device\r\n");
return 1;
}
/* We still haven't set the Address yet */
addr = dev->devnum;
@@ -1084,7 +1102,7 @@ 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("malloc failure\r\n");
return 1;
}
@@ -1125,6 +1143,7 @@ int usb_new_device(struct usb_device *dev)
*/
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;
dev->epmaxpacketin[0] = 64;
@@ -1260,7 +1279,9 @@ int usb_new_device(struct usb_device *dev)
return 0;
}
/* build device Tree */
/*
* build device Tree
*/
void usb_scan_devices(void *priv)
{
int i;
@@ -1274,7 +1295,9 @@ void usb_scan_devices(void *priv)
}
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);
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]);
}
{
#ifdef _NOT_USED_ /* not implemented yet */
/* insert "driver" if possible */
if (drv_usb_kbd_init() < 0)
{
@@ -1301,7 +1321,6 @@ void usb_scan_devices(void *priv)
{
xprintf("USB HID keyboard driver installed\r\n");
}
#endif /* _NOT_USED */
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("Scan end\r\n");
}

1389
usb/usb_kbd.c Normal file

File diff suppressed because it is too large Load Diff