uhci.c
来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· C语言 代码 · 共 2,164 行 · 第 1/5 页
C
2,164 行
if (status != STATUS_SUCCESS || pdev == NULL)
{
RtlFreeUnicodeString(&dev_name);
return NULL;
}
pdev_ext = pdev->DeviceExtension;
RtlZeroMemory(pdev_ext, sizeof(DEVICE_EXTENSION) + sizeof(UHCI_DEV));
pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD;
pdev_ext->dev_ext_hdr.dispatch = uhci_dispatch_irp;
pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio
pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
pdev_ext->pdev_obj = pdev;
pdev_ext->pdrvr_obj = drvr_obj;
pdev_ext->uhci = (PUHCI_DEV) & (pdev_ext[1]);
RtlInitString(&another_string, str_symb_name);
RtlAnsiStringToUnicodeString(&symb_name, &another_string, TRUE);
IoCreateSymbolicLink(&symb_name, &dev_name);
uhci_dbg_print(DBGLVL_MAXIMUM,
("uhci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, uhci=0x%x, dev_mgr=0x%x\n", pdev,
pdev_ext, pdev_ext->uhci, dev_mgr));
RtlFreeUnicodeString(&dev_name);
RtlFreeUnicodeString(&symb_name);
//register with dev_mgr though it is not initilized
uhci_init_hcd_interface(pdev_ext->uhci);
hcd_id = dev_mgr_register_hcd(dev_mgr, &pdev_ext->uhci->hcd_interf);
pdev_ext->uhci->hcd_interf.hcd_set_id(&pdev_ext->uhci->hcd_interf, hcd_id);
pdev_ext->uhci->hcd_interf.hcd_set_dev_mgr(&pdev_ext->uhci->hcd_interf, dev_mgr);
return pdev;
}
BOOLEAN
uhci_delete_device(PDEVICE_OBJECT pdev)
{
STRING string;
UNICODE_STRING symb_name;
PDEVICE_EXTENSION pdev_ext;
CHAR str_symb_name[64];
if (pdev == NULL)
return FALSE;
pdev_ext = pdev->DeviceExtension;
sprintf(str_symb_name,
"%s%d", DOS_DEVICE_NAME, pdev_ext->uhci->hcd_interf.hcd_get_id(&pdev_ext->uhci->hcd_interf));
RtlInitString(&string, str_symb_name);
RtlAnsiStringToUnicodeString(&symb_name, &string, TRUE);
IoDeleteSymbolicLink(&symb_name);
RtlFreeUnicodeString(&symb_name);
if (pdev_ext->res_list)
ExFreePool(pdev_ext->res_list); // not allocated by usb_alloc_mem
IoDeleteDevice(pdev);
uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_delete_device(): device deleted\n"));
return TRUE;
}
// we can not use endp here for it is within the dev scope, and
// we can not acquire the dev-lock, fortunately we saved some
// info in urb->pipe in uhci_internal_submit_XXX.
BOOLEAN NTAPI
uhci_isr(PKINTERRUPT interrupt, PVOID context)
{
PUHCI_DEV uhci;
USHORT status;
PLIST_ENTRY pthis, pnext;
PURB purb;
UNREFERENCED_PARAMETER(interrupt);
UNREFERENCED_PARAMETER(context);
uhci_dbg_print(DBGLVL_ULTRA, ("uhci_isr(): context=0x%x\n", context));
/*
* Read the interrupt status, and write it back to clear the
* interrupt cause
*/
uhci = (PUHCI_DEV) context;
if (uhci == NULL)
return FALSE;
status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBSTS));
if (!status) /* shared interrupt, not mine */
return FALSE;
if (status != 1)
{
uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_isr(): current uhci status=0x%x\n", status));
}
else
{
uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_isr(): congratulations, no error occurs\n"));
}
/* clear it */
WRITE_PORT_USHORT((PUSHORT) (uhci->port_base + USBSTS), status);
if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD))
{
if (status & USBSTS_HSE)
{
DbgPrint("uhci_isr(): host system error, PCI problems?\n");
//for( ; ; );
}
if (status & USBSTS_HCPE)
{
DbgPrint("uhci_isr(): host controller process error. something bad happened\n");
//for( ; ; );
//for( ; ; );
}
if ((status & USBSTS_HCH)) //&& !uhci->is_suspended
{
DbgPrint("uhci_isr(): host controller halted. very bad\n");
/* FIXME: Reset the controller, fix the offending TD */
}
}
// don't no how to handle it yet
//if (status & USBSTS_RD)
//{
//uhci_wakeup(uhci);
//}*/
//let's remove those force-cancel urbs from the schedule first
ListFirst(&uhci->urb_list, pthis);
while (pthis)
{
purb = (PURB) pthis;
if (purb->flags & URB_FLAG_FORCE_CANCEL)
{
uhci_remove_urb_from_schedule(uhci, purb);
}
ListNext(&uhci->urb_list, pthis, pnext);
pthis = pnext;
}
//clear the interrupt if the urb is force canceled
uhci->skel_term_td->status &= ~TD_CTRL_IOC;
//next we need to find if anything fininshed
ListFirst(&uhci->urb_list, pthis);
while (pthis)
{
purb = (PURB) pthis;
if (purb->flags & URB_FLAG_IN_SCHEDULE)
{
if (uhci_is_xfer_finished(purb))
uhci_remove_urb_from_schedule(uhci, purb);
}
ListNext(&uhci->urb_list, pthis, pnext);
pthis = pnext;
}
KeInsertQueueDpc(&uhci->pdev_ext->uhci_dpc, uhci, 0);
return TRUE;
}
BOOLEAN NTAPI
uhci_cal_cpu_freq(PVOID context)
{
UNREFERENCED_PARAMETER(context);
usb_cal_cpu_freq();
return TRUE;
}
PDEVICE_OBJECT
uhci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr)
{
LONG bus, i, j, ret = 0;
PCI_SLOT_NUMBER slot_num;
PPCI_COMMON_CONFIG pci_config;
PDEVICE_OBJECT pdev;
BYTE buffer[sizeof(PCI_COMMON_CONFIG)];
LONG count;
PDEVICE_EXTENSION pdev_ext;
slot_num.u.AsULONG = 0;
pci_config = (PPCI_COMMON_CONFIG) buffer;
count = 0;
pdev = NULL;
//scan the bus to find uhci controller
for(bus = 0; bus < 2; bus++) /*enum only bus0 and bus1 */
{
for(i = 0; i < PCI_MAX_DEVICES; i++)
{
slot_num.u.bits.DeviceNumber = i;
for(j = 0; j < PCI_MAX_FUNCTIONS; j++)
{
slot_num.u.bits.FunctionNumber = j;
ret = HalGetBusData(PCIConfiguration,
bus, slot_num.u.AsULONG, pci_config, PCI_COMMON_HDR_LENGTH);
if (ret == 0) /*no this bus */
break;
if (ret == 2) /*no device on the slot */
break;
if (pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03)
{
// well, we find our usb host controller, create device
#ifdef _MULTI_UHCI
{
pdev = uhci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr);
count++;
if (!pdev)
return NULL;
}
#else
pdev = uhci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr);
if (pdev)
goto LBL_LOOPOUT;
#endif
}
}
if (ret == 0)
break;
}
}
LBL_LOOPOUT:
if (pdev)
{
pdev_ext = pdev->DeviceExtension;
if (pdev_ext)
{
// acquire higher irql to eliminate pre-empty
KeSynchronizeExecution(pdev_ext->uhci_int, uhci_cal_cpu_freq, NULL);
}
}
return NULL;
}
PDEVICE_OBJECT
uhci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr)
{
LONG frd_num, prd_num;
PDEVICE_OBJECT pdev;
PDEVICE_EXTENSION pdev_ext;
ULONG vector, addr_space;
LONG bus;
KIRQL irql;
KAFFINITY affinity;
DEVICE_DESCRIPTION dev_desc;
CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd;
PCI_SLOT_NUMBER slot_num;
NTSTATUS status;
pdev = uhci_create_device(drvr_obj, dev_mgr);
pdev_ext = pdev->DeviceExtension;
pdev_ext->pci_addr = bus_addr;
bus = (bus_addr >> 8);
slot_num.u.AsULONG = 0;
slot_num.u.bits.DeviceNumber = ((bus_addr & 0xff) >> 3);
slot_num.u.bits.FunctionNumber = (bus_addr & 0x07);
if (pdev == NULL)
return pdev;
//now create adapter object
RtlZeroMemory(&dev_desc, sizeof(dev_desc));
dev_desc.Version = DEVICE_DESCRIPTION_VERSION;
dev_desc.Master = TRUE;
dev_desc.ScatterGather = TRUE;
dev_desc.Dma32BitAddresses = TRUE;
dev_desc.BusNumber = bus;
dev_desc.InterfaceType = PCIBus;
dev_desc.MaximumLength =
UHCI_MAX_POOL_TDS * sizeof(UHCI_TD) * UHCI_MAX_TD_POOLS
+ sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS + sizeof(ULONG) * UHCI_MAX_FRAMES;
pdev_ext->map_regs = 2; // UHCI_MAX_TD_POOLS +
//+ BYTES_TO_PAGES( ( UHCI_MAX_POOL_TDS * 64 ) * UHCI_MAX_TD_POOLS ) ;
pdev_ext->padapter = HalGetAdapter(&dev_desc, &pdev_ext->map_regs);
uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_alloc(): padapter=0x%x\n", pdev_ext->padapter));
if (pdev_ext->padapter == NULL)
{
//fatal error
uhci_delete_device(pdev);
return NULL;
}
DbgPrint("uhci_alloc(): reg_path=%p, \n \
uhci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \
uhci_alloc(): slot_num=0x%x, &res_list=%p \n", reg_path, (DWORD) PCIBus, (DWORD) bus,
(DWORD) bus_addr, (DWORD) slot_num.u.AsULONG, & pdev_ext->res_list);
//let's allocate resources for this device
DbgPrint("uhci_alloc(): about to assign slot res\n");
if ((status = HalAssignSlotResources(reg_path, NULL, //no class name yet
drvr_obj, NULL, //no support of another uhci controller
PCIBus,
bus, slot_num.u.AsULONG, &pdev_ext->res_list)) != STATUS_SUCCESS)
{
DbgPrint("uhci_alloc(): error assign slot res, 0x%x\n", status);
release_adapter(pdev_ext->padapter);
pdev_ext->padapter = NULL;
uhci_delete_device(pdev);
return NULL;
}
//parse the resource list
for(frd_num = 0; frd_num < (LONG) pdev_ext->res_list->Count; frd_num++)
{
for(prd_num = 0; prd_num < (LONG) pdev_ext->res_list->List[frd_num].PartialResourceList.Count;
prd_num++)
{
pprd = &pdev_ext->res_list->List[frd_num].PartialResourceList.PartialDescriptors[prd_num];
if (pprd->Type == CmResourceTypePort)
{
RtlCopyMemory(&pdev_ext->res_port, &pprd->u.Port, sizeof(pprd->u.Port));
}
else if (pprd->Type == CmResourceTypeInterrupt)
{
RtlCopyMemory(&pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof(pprd->u.Interrupt));
}
}
}
//for port, translate them to system address
addr_space = 1;
if (HalTranslateBusAddress(PCIBus, bus, pdev_ext->res_port.Start, &addr_space, //io space
&pdev_ext->uhci->uhci_reg_base) != (BOOLEAN) TRUE)
{
DbgPrint("uhci_alloc(): error, can not translate bus address\n");
release_adapter(pdev_ext->padapter);
pdev_ext->padapter = NULL;
uhci_delete_device(pdev);
return NULL;
}
DbgPrint("uhci_alloc(): address space=0x%x\n, reg_base=0x%x\n",
addr_space, pdev_ext->uhci->uhci_reg_base.u.LowPart);
if (addr_space == 0)
{
//port has been mapped to memory space
pdev_ext->uhci->port_mapped = TRUE;
pdev_ext->uhci->port_base = (PBYTE) MmMapIoSpace(pdev_ext->uhci->uhci_reg_base,
pdev_ext->res_port.Length, FALSE);
//fatal error can not map the registers
if (pdev_ext->uhci->port_base == NULL)
{
release_adapter(pdev_ext->padapter);
pdev_ext->padapter = NULL;
uhci_delete_device(pdev);
return NULL;
}
}
else
{
//io space
pdev_ext->uhci->port_mapped = FALSE;
pdev_ext->uhci->port_base = (PBYTE) pdev_ext->uhci->uhci_reg_base.LowPart;
}
//before we connect the interrupt, we have to init uhci
pdev_ext->uhci->fsbr_cnt = 0;
pdev_ext->uhci->pdev_ext = pdev_ext;
if (uhci_init_schedule(pdev_ext->uhci, pdev_ext->padapter) == FALSE)
{
release_adapter(pdev_ext->padapter);
pdev_ext->padapter = NULL;
uhci_delete_device(pdev);
return NULL;
}
InitializeListHead(&pdev_ext->uhci->urb_list);
KeInitializeSpinLock(&pdev_ext->uhci->pending_endp_list_lock);
InitializeListHead(&pdev_ext->uhci->pending_endp_list);
uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_alloc(): pending_endp_list=0x%x\n",
&pdev_ext->uhci->pending_endp_list));
init_pending_endp_pool(&pdev_ext->uhci->pending_endp_pool);
KeInitializeTimer(&pdev_ext->uhci->reset_timer);
vector = HalGetInterruptVector(PCIBus,
bus,
pdev_ext->res_interrupt.level,
pdev_ext->res_interrupt.vector,
&irql,
&affinity);
//connect the interrupt
DbgPrint("uhci_alloc(): the int=0x%x\n", vector);
if (IoConnectInterrupt(&pdev_ext->uhci_int,
uhci_isr,
pdev_ext->uhci,
NULL, //&pdev_ext->uhci->frame_list_lock,
vector,
irql,
irql,
LevelSensitive,
TRUE, //share the vector
affinity,
FALSE) //No float save
!= STATUS_SUCCESS)
{
uhci_release(pdev);
return NULL;
}
KeInitializeDpc(&pdev_ext->uhci_dpc, uhci_dpc_callback, (PVOID) pdev_ext->uhci);
return pdev;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?