mirror of
https://github.com/reactos/reactos.git
synced 2024-07-14 00:25:05 +00:00
- Implement init and start of OHCI controller (interrupts are still disabled, because corresponding code is not implemented).
- Implement stubbed HCD interface functions for OHCI. - Add Endpoint Descriptor and Transfer Descriptor structs from Linux. svn path=/trunk/; revision=30607
This commit is contained in:
parent
0fdacaa71e
commit
de4fffafa1
|
@ -87,6 +87,12 @@ static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
|
|||
*/
|
||||
|
||||
|
||||
/* For initializing controller (mask in an HCFS mode too) */
|
||||
#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
|
||||
#define OHCI_INTR_INIT \
|
||||
(OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
|
||||
|
||||
|
||||
VOID
|
||||
ohci_wait_ms(POHCI_DEV ohci, LONG ms)
|
||||
{
|
||||
|
@ -161,6 +167,28 @@ PDEVICE_OBJECT ohci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
BOOLEAN ohci_mem_init (POHCI_DEVICE_EXTENSION dev_ext)
|
||||
{
|
||||
dev_ext->ohci->td_cache = HalAllocateCommonBuffer(dev_ext->padapter,
|
||||
sizeof(OHCI_TD), &dev_ext->ohci->td_logic_addr, FALSE);
|
||||
|
||||
if (!dev_ext->ohci->td_cache)
|
||||
return FALSE;
|
||||
|
||||
dev_ext->ohci->ed_cache = HalAllocateCommonBuffer(dev_ext->padapter,
|
||||
sizeof(OHCI_ED), &dev_ext->ohci->ed_logic_addr, FALSE);
|
||||
|
||||
if (!dev_ext->ohci->ed_cache)
|
||||
{
|
||||
HalFreeCommonBuffer(dev_ext->padapter, sizeof(OHCI_TD), dev_ext->ohci->td_logic_addr,
|
||||
dev_ext->ohci->td_cache, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
PDEVICE_OBJECT
|
||||
ohci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr)
|
||||
{
|
||||
|
@ -201,7 +229,9 @@ ohci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PU
|
|||
dev_desc.Dma32BitAddresses = TRUE;
|
||||
dev_desc.BusNumber = bus;
|
||||
dev_desc.InterfaceType = PCIBus;
|
||||
//dev_desc.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
|
||||
dev_desc.MaximumLength = EHCI_MAX_SIZE_TRANSFER;
|
||||
pdev_ext->map_regs = 2; // we do not use it seriously
|
||||
pdev_ext->padapter = HalGetAdapter(&dev_desc, &pdev_ext->map_regs);
|
||||
|
||||
DbgPrint("ohci_alloc(): reg_path=0x%x, \n \
|
||||
ohci_alloc(): bus=0x%x, bus_addr=0x%x \n \
|
||||
|
@ -333,13 +363,20 @@ ohci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PU
|
|||
|
||||
DbgPrint("OHCI: %d ports\n", pdev_ext->ohci->num_ports);
|
||||
|
||||
//ohci->hcca = dma_alloc_coherent (ohci_to_hcd(ohci)->self.controller,
|
||||
// sizeof *ohci->hcca, &ohci->hcca_dma, 0);
|
||||
//if (!ohci->hcca)
|
||||
// return -ENOMEM;
|
||||
pdev_ext->ohci->hcca = HalAllocateCommonBuffer(pdev_ext->padapter,
|
||||
sizeof(*pdev_ext->ohci->hcca), &pdev_ext->ohci->hcca_logic_addr, FALSE);
|
||||
|
||||
//if ((ret = ohci_mem_init (ohci)) < 0)
|
||||
// ohci_stop (ohci_to_hcd(ohci));
|
||||
if (!pdev_ext->ohci->hcca)
|
||||
{
|
||||
DbgPrint("OHCI: HCCA allocation failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ohci_mem_init(pdev_ext))
|
||||
{
|
||||
DbgPrint("OHCI: Mem init failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
//init ehci_caps
|
||||
|
@ -464,72 +501,137 @@ ohci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr)
|
|||
BOOLEAN
|
||||
ohci_start(PHCD hcd)
|
||||
{
|
||||
//ULONG tmp;
|
||||
ULONG temp, mask;
|
||||
//PBYTE base;
|
||||
//PEHCI_USBCMD_CONTENT usbcmd;
|
||||
//POHCI_DEV ohci;
|
||||
POHCI_DEV ohci;
|
||||
ULONG hc_control;
|
||||
|
||||
if (hcd == NULL)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
ohci = struct_ptr(hcd, OHCI_DEV, hcd_interf);
|
||||
|
||||
/* Reset USB nearly "by the book". RemoteWakeupConnected
|
||||
* saved if boot firmware (BIOS/SMM/...) told us it's connected
|
||||
* (for OHCI integrated on mainboard, it normally is)
|
||||
*/
|
||||
hc_control = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control);
|
||||
DbgPrint("resetting from state %x, control = 0x%x\n",
|
||||
(hc_control & OHCI_CTRL_HCFS),
|
||||
hc_control);
|
||||
|
||||
//if (hc_control & OHCI_CTRL_RWC
|
||||
// && !(ohci->flags & OHCI_QUIRK_AMD756))
|
||||
// ohci_to_hcd(ohci)->can_wakeup = 1;
|
||||
|
||||
switch (hc_control & OHCI_CTRL_HCFS) {
|
||||
case OHCI_USB_OPER:
|
||||
temp = 0;
|
||||
break;
|
||||
case OHCI_USB_SUSPEND:
|
||||
case OHCI_USB_RESUME:
|
||||
hc_control &= OHCI_CTRL_RWC;
|
||||
hc_control |= OHCI_USB_RESUME;
|
||||
temp = 10 /* msec wait */;
|
||||
break;
|
||||
// case OHCI_USB_RESET:
|
||||
default:
|
||||
hc_control &= OHCI_CTRL_RWC;
|
||||
hc_control |= OHCI_USB_RESET;
|
||||
temp = 50 /* msec wait */;
|
||||
break;
|
||||
}
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->control, hc_control);
|
||||
|
||||
// flush the writes
|
||||
(VOID)OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control);
|
||||
|
||||
ohci_wait_ms(ohci, temp);
|
||||
temp = roothub_a (ohci);
|
||||
if (!(temp & RH_A_NPS)) {
|
||||
/* power down each port */
|
||||
for (temp = 0; temp < ohci->num_ports; temp++)
|
||||
{
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus [temp], RH_PS_LSDA);
|
||||
}
|
||||
}
|
||||
// flush those writes
|
||||
(VOID)OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control);
|
||||
RtlZeroMemory(ohci->hcca, sizeof(OHCI_HCCA));
|
||||
|
||||
/* 2msec timelimit here means no irqs/preempt */
|
||||
//spin_lock_irq (&ohci->lock);
|
||||
|
||||
//retry:
|
||||
/* HC Reset requires max 10 us delay */
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->cmdstatus, OHCI_HCR);
|
||||
temp = 30; /* ... allow extra time */
|
||||
while ((OHCI_READ_PORT_ULONG ((PULONG)&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
|
||||
if (--temp == 0) {
|
||||
//spin_unlock_irq (&ohci->lock);
|
||||
//ohci_err (ohci, "USB HC reset timed out!\n");
|
||||
DbgPrint("OHCI: USB HC reset timed out!\n");
|
||||
return FALSE;
|
||||
}
|
||||
KeStallExecutionProcessor(1);
|
||||
}
|
||||
|
||||
/* now we're in the SUSPEND state ... must go OPERATIONAL
|
||||
* within 2msec else HC enters RESUME
|
||||
*
|
||||
* ... but some hardware won't init fmInterval "by the book"
|
||||
* (SiS, OPTi ...), so reset again instead. SiS doesn't need
|
||||
* this if we write fmInterval after we're OPERATIONAL.
|
||||
* Unclear about ALi, ServerWorks, and others ... this could
|
||||
* easily be a longstanding bug in chip init on Linux.
|
||||
*/
|
||||
#if 0
|
||||
ehci = struct_ptr(hcd, EHCI_DEV, hcd_interf);
|
||||
base = ehci->port_base;
|
||||
|
||||
// stop the controller
|
||||
tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD));
|
||||
usbcmd = (PEHCI_USBCMD_CONTENT) & tmp;
|
||||
usbcmd->run_stop = 0;
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
|
||||
|
||||
// wait the controller stop( ehci spec, 16 microframe )
|
||||
usb_wait_ms_dpc(2);
|
||||
|
||||
// reset the controller
|
||||
usbcmd = (PEHCI_USBCMD_CONTENT) & tmp;
|
||||
usbcmd->hcreset = TRUE;
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// interval.QuadPart = -100 * 10000; // 10 ms
|
||||
// KeDelayExecutionThread( KernelMode, FALSE, &interval );
|
||||
KeStallExecutionProcessor(10);
|
||||
tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD));
|
||||
if (!usbcmd->hcreset)
|
||||
break;
|
||||
}
|
||||
|
||||
// prepare the registers
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CTRLDSSEGMENT), 0);
|
||||
|
||||
// turn on all the int
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBINTR),
|
||||
EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR
|
||||
// EHCI_USBINTR_FLROVR | \ // it is noisy
|
||||
// EHCI_USBINTR_PC // we detect it by polling
|
||||
);
|
||||
// write the list base reg
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_PERIODICLISTBASE), ehci->frame_list_phys_addr.LowPart);
|
||||
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_ASYNCLISTBASE), ehci->skel_async_qh->phys_addr & ~(0x1f));
|
||||
|
||||
usbcmd->int_threshold = 1;
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
|
||||
|
||||
// let's rock
|
||||
usbcmd->run_stop = 1;
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
|
||||
|
||||
// set the configuration flag
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CONFIGFLAG), 1);
|
||||
|
||||
// enable the list traversaling
|
||||
usbcmd->async_enable = 1;
|
||||
usbcmd->periodic_enable = 1;
|
||||
EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp);
|
||||
if (ohci->flags & OHCI_QUIRK_INITRESET) {
|
||||
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
|
||||
// flush those writes
|
||||
(void) ohci_readl (ohci, &ohci->regs->control);
|
||||
}
|
||||
#endif
|
||||
/* Tell the controller where the control and bulk lists are
|
||||
* The lists are empty now. */
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->ed_controlhead, 0);
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->ed_bulkhead, 0);
|
||||
|
||||
/* a reset clears this */
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->hcca, (ULONG)ohci->hcca_logic_addr.LowPart);
|
||||
|
||||
//periodic_reinit (ohci);
|
||||
|
||||
/* start controller operations */
|
||||
hc_control &= OHCI_CTRL_RWC;
|
||||
hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->control, hc_control);
|
||||
//ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
|
||||
|
||||
/* wake on ConnectStatusChange, matching external hubs */
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.status, RH_HS_DRWE);
|
||||
|
||||
/* Choose the interrupts we care about now, others later on demand */
|
||||
mask = OHCI_INTR_INIT;
|
||||
//OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->intrstatus, mask);
|
||||
//OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->intrenable, mask);
|
||||
|
||||
/* handle root hub init quirks ... */
|
||||
temp = roothub_a(ohci);
|
||||
temp &= ~(RH_A_PSM | RH_A_OCPM);
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.status, RH_HS_LPSC);
|
||||
OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.b, (temp & RH_A_NPS) ? 0 : RH_B_PPCM);
|
||||
// flush those writes
|
||||
(VOID)OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control);
|
||||
|
||||
//spin_unlock_irq (&ohci->lock);
|
||||
|
||||
// POTPGT delay is bits 24-31, in 2 ms units.
|
||||
ohci_wait_ms(ohci, (temp >> 23) & 0x1fe);
|
||||
//ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -607,21 +709,49 @@ ohci_rh_reset_port(PHCD hcd, UCHAR port_idx)
|
|||
//ULONG i;
|
||||
POHCI_DEV ohci;
|
||||
//ULONG status;
|
||||
//UCHAR port_count;
|
||||
|
||||
if (hcd == NULL)
|
||||
return FALSE;
|
||||
|
||||
ohci = ohci_from_hcd(hcd);
|
||||
//port_count = (UCHAR) ((PEHCI_HCS_CONTENT) & ehci->ehci_caps.hcs_params)->port_count;
|
||||
|
||||
//if (port_idx < 1 || port_idx > port_count)
|
||||
// return FALSE;
|
||||
//if (port_idx < 1 || port_idx > ohci->num_ports)
|
||||
// return FALSE;
|
||||
|
||||
//usb_dbg_print(DBGLVL_MAXIMUM, ("ohci_rh_reset_port(): status after written=0x%x\n", status));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
ohci_rh_get_dev_change(PHCD hcd, PBYTE buf) //must have the rh dev_lock acquired
|
||||
{
|
||||
POHCI_DEV ohci;
|
||||
LONG i;
|
||||
ULONG status;
|
||||
|
||||
if (hcd == NULL)
|
||||
return FALSE;
|
||||
|
||||
ohci = ohci_from_hcd(hcd);
|
||||
|
||||
for(i = 0; i < ohci->num_ports; i++)
|
||||
{
|
||||
status = OHCI_READ_PORT_ULONG((PULONG)(ohci->regs->roothub.portstatus[i]));
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
ohci_dbg_print(DBGLVL_MAXIMUM, ("ohci_rh_get_dev_change(): erh port%d status=0x%x\n", i, status));
|
||||
}
|
||||
|
||||
if (status & (RH_PS_PESC | RH_PS_CSC | RH_PS_OCIC))
|
||||
{
|
||||
buf[(i + 1) >> 3] |= (1 << ((i + 1) & 7));
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
ohci_hcd_dispatch(PHCD hcd, LONG disp_code, PVOID param)
|
||||
{
|
||||
|
@ -630,24 +760,24 @@ ohci_hcd_dispatch(PHCD hcd, LONG disp_code, PVOID param)
|
|||
if (hcd == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
ohci = ohci_from_hcd(hcd);
|
||||
#if 0
|
||||
|
||||
switch (disp_code)
|
||||
{
|
||||
case HCD_DISP_READ_PORT_COUNT:
|
||||
{
|
||||
if (param == NULL)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
*((PUCHAR) param) = (UCHAR) HCS_N_PORTS(ehci->ehci_caps.hcs_params);
|
||||
*((PUCHAR) param) = ohci->num_ports;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
case HCD_DISP_READ_RH_DEV_CHANGE:
|
||||
{
|
||||
if (ehci_rh_get_dev_change(hcd, param) == FALSE)
|
||||
if (ohci_rh_get_dev_change(hcd, param) == FALSE)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,6 +114,146 @@
|
|||
#define RH_A_NOCP (1 << 12) /* no over current protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
|
||||
|
||||
/*
|
||||
* OHCI Endpoint Descriptor (ED) ... holds TD queue
|
||||
* See OHCI spec, section 4.2
|
||||
*
|
||||
* This is a "Queue Head" for those transfers, which is why
|
||||
* both EHCI and UHCI call similar structures a "QH".
|
||||
*/
|
||||
typedef struct _OHCI_ED {
|
||||
/* first fields are hardware-specified */
|
||||
ULONG hwINFO; /* endpoint config bitmap */
|
||||
/* info bits defined by hcd */
|
||||
#define ED_DEQUEUE (1 << 27)
|
||||
/* info bits defined by the hardware */
|
||||
#define ED_ISO (1 << 15)
|
||||
#define ED_SKIP (1 << 14)
|
||||
#define ED_LOWSPEED (1 << 13)
|
||||
#define ED_OUT (0x01 << 11)
|
||||
#define ED_IN (0x02 << 11)
|
||||
ULONG hwTailP; /* tail of TD list */
|
||||
ULONG hwHeadP; /* head of TD list (hc r/w) */
|
||||
#define ED_C (0x02) /* toggle carry */
|
||||
#define ED_H (0x01) /* halted */
|
||||
ULONG hwNextED; /* next ED in list */
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
#if 0
|
||||
dma_addr_t dma; /* addr of ED */
|
||||
struct _OHCI_TD *dummy; /* next TD to activate */
|
||||
|
||||
/* host's view of schedule */
|
||||
struct _OHCI_ED *ed_next; /* on schedule or rm_list */
|
||||
struct _OHCI_ED *ed_prev; /* for non-interrupt EDs */
|
||||
struct list_head td_list; /* "shadow list" of our TDs */
|
||||
|
||||
/* create --> IDLE --> OPER --> ... --> IDLE --> destroy
|
||||
* usually: OPER --> UNLINK --> (IDLE | OPER) --> ...
|
||||
*/
|
||||
UCHAR state; /* ED_{IDLE,UNLINK,OPER} */
|
||||
#define ED_IDLE 0x00 /* NOT linked to HC */
|
||||
#define ED_UNLINK 0x01 /* being unlinked from hc */
|
||||
#define ED_OPER 0x02 /* IS linked to hc */
|
||||
|
||||
UCHAR type; /* PIPE_{BULK,...} */
|
||||
|
||||
/* periodic scheduling params (for intr and iso) */
|
||||
UCHAR branch;
|
||||
USHORT interval;
|
||||
USHORT load;
|
||||
USHORT last_iso; /* iso only */
|
||||
|
||||
/* HC may see EDs on rm_list until next frame (frame_no == tick) */
|
||||
USHORT tick;
|
||||
#endif
|
||||
} OHCI_ED, *POHCI_ED;
|
||||
|
||||
#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */
|
||||
|
||||
|
||||
/*
|
||||
* OHCI Transfer Descriptor (TD) ... one per transfer segment
|
||||
* See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
|
||||
* and 4.3.2 (iso)
|
||||
*/
|
||||
typedef struct _OHCI_TD {
|
||||
/* first fields are hardware-specified */
|
||||
ULONG hwINFO; /* transfer info bitmask */
|
||||
|
||||
/* hwINFO bits for both general and iso tds: */
|
||||
#define TD_CC 0xf0000000 /* condition code */
|
||||
#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
|
||||
//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28)
|
||||
#define TD_DI 0x00E00000 /* frames before interrupt */
|
||||
#define TD_DI_SET(X) (((X) & 0x07)<< 21)
|
||||
/* these two bits are available for definition/use by HCDs in both
|
||||
* general and iso tds ... others are available for only one type
|
||||
*/
|
||||
#define TD_DONE 0x00020000 /* retired to donelist */
|
||||
#define TD_ISO 0x00010000 /* copy of ED_ISO */
|
||||
|
||||
/* hwINFO bits for general tds: */
|
||||
#define TD_EC 0x0C000000 /* error count */
|
||||
#define TD_T 0x03000000 /* data toggle state */
|
||||
#define TD_T_DATA0 0x02000000 /* DATA0 */
|
||||
#define TD_T_DATA1 0x03000000 /* DATA1 */
|
||||
#define TD_T_TOGGLE 0x00000000 /* uses ED_C */
|
||||
#define TD_DP 0x00180000 /* direction/pid */
|
||||
#define TD_DP_SETUP 0x00000000 /* SETUP pid */
|
||||
#define TD_DP_IN 0x00100000 /* IN pid */
|
||||
#define TD_DP_OUT 0x00080000 /* OUT pid */
|
||||
/* 0x00180000 rsvd */
|
||||
#define TD_R 0x00040000 /* round: short packets OK? */
|
||||
|
||||
/* (no hwINFO #defines yet for iso tds) */
|
||||
|
||||
ULONG hwCBP; /* Current Buffer Pointer (or 0) */
|
||||
ULONG hwNextTD; /* Next TD Pointer */
|
||||
ULONG hwBE; /* Memory Buffer End Pointer */
|
||||
|
||||
/* PSW is only for ISO. Only 1 PSW entry is used, but on
|
||||
* big-endian PPC hardware that's the second entry.
|
||||
*/
|
||||
#define MAXPSW 2
|
||||
USHORT hwPSW [MAXPSW];
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
#if 0
|
||||
UCHAR index;
|
||||
struct ed *ed;
|
||||
struct td *td_hash; /* dma-->td hashtable */
|
||||
struct td *next_dl_td;
|
||||
struct urb *urb;
|
||||
|
||||
dma_addr_t td_dma; /* addr of this TD */
|
||||
dma_addr_t data_dma; /* addr of data it points to */
|
||||
|
||||
struct list_head td_list; /* "shadow list", TDs on same ED */
|
||||
#endif
|
||||
} OHCI_TD, *POHCI_TD;
|
||||
|
||||
/*
|
||||
* The HCCA (Host Controller Communications Area) is a 256 byte
|
||||
* structure defined section 4.4.1 of the OHCI spec. The HC is
|
||||
* told the base address of it. It must be 256-byte aligned.
|
||||
*/
|
||||
typedef struct _OHCI_HCCA
|
||||
{
|
||||
#define NUM_INTS 32
|
||||
ULONG int_table [NUM_INTS]; /* periodic schedule */
|
||||
|
||||
/*
|
||||
* OHCI defines u16 frame_no, followed by u16 zero pad.
|
||||
* Since some processors can't do 16 bit bus accesses,
|
||||
* portable access must be a 32 bits wide.
|
||||
*/
|
||||
ULONG frame_no; /* current frame number */
|
||||
ULONG done_head; /* info returned for an interrupt */
|
||||
UCHAR reserved_for_hc [116];
|
||||
UCHAR what [4]; /* spec only identifies 252 bytes :) */
|
||||
} OHCI_HCCA, *POHCI_HCCA;
|
||||
|
||||
/*
|
||||
* This is the structure of the OHCI controller's memory mapped I/O region.
|
||||
* You must use readl() and writel() (in <asm/io.h>) to access these fields!!
|
||||
|
@ -165,6 +305,13 @@ typedef struct _OHCI_DEV
|
|||
BOOLEAN port_mapped;
|
||||
PBYTE port_base; // note: added by ehci_caps.length, operational regs base addr, not the actural base
|
||||
struct _OHCI_REGS *regs;
|
||||
struct _OHCI_HCCA *hcca;
|
||||
PVOID td_cache;
|
||||
PVOID ed_cache;
|
||||
|
||||
PHYSICAL_ADDRESS hcca_logic_addr;
|
||||
PHYSICAL_ADDRESS td_logic_addr;
|
||||
PHYSICAL_ADDRESS ed_logic_addr;
|
||||
|
||||
USHORT num_ports;
|
||||
|
||||
|
|
Loading…
Reference in a new issue