Device Driver "struct PCIDevice *pcidev;" pcidev's...

This forum is for general developer support questions.
Post Reply
Belxjander
Posts: 314
Joined: Mon May 14, 2012 10:26 pm
Location: 日本千葉県松戸市 / Matsudo City, Chiba, Japan
Contact:

Device Driver "struct PCIDevice *pcidev;" pcidev's...

Post by Belxjander »

I'm currently trying to write a device driver for a PCI bridged PCI-Express USB3 XHCI controller

and running into the following situation...

during ramlib execution of the device "DevInit" and eventually passing through "InitUnit()"

I can use the expansion.library "IPCI" Interface and get a valid pcidev=IPCI->FindDeviceTags(...) result...

However when using the IPCI interface from within the Unit specific Task created... I keep getting a NULL pcidev from exact search parameters (including an index of which unit it is).

This is what runs during DevInit...

Code: Select all

	if((Base = IExec->OpenLibrary("expansion.library",0L)))
	{
		Self->IExpansion = (APTR)IExec->GetInterface(Base,"main",1L,NULL);
		Self->IPCI = (APTR)IExec->GetInterface(Base,"pci",1L,NULL);
		for(hwcnt=0UL;hwcnt<DEVICE_UNIT_COUNT;hwcnt++)
		{
			pcidev=Self->IPCI->FindDeviceTags(
					FDT_Class,		0x000C0330,
					FDT_ClassMask,	0x00FFFFFF,
					FDT_Index,		hwcnt,
					TAG_DONE,		TAG_DONE
				);
			if(pcidev)
				InitUnit(Self,pcidev,hwcnt);
			IExec->DropInterface((APTR)pcidev);
		}
	}
And this is from within the UnitTask itself...

Code: Select all

	if(Unit->IPCI)
	{
		Unit->uCard=Unit->IPCI->FindDeviceTags(
					FDT_Class,		0x000C0330,
					FDT_ClassMask,	0x00FFFFFF,
					FDT_Index,		Unit->unitn,
					TAG_DONE,		TAG_DONE
				);
		KDEBUG("XHCI /UnitTask/ unit->uCard[%lx,%lx]\n",unitn,Unit->uCard);
	}
and the full code for the InitUnit() function is ...

Code: Select all

VOID InitUnit(struct DEVICE_CLASS *Base, struct PCIDevice *card, uint32 unitn)
{
	struct DEVICE_UNIT_CLASS *unit=NULL;

	if(card)
		unit=Base->IExec->AllocVecTags(DEVICE_UNIT_SIZE,AVT_Type,MEMF_SHARED,AVT_ClearWithValue,0L,TAG_DONE,TAG_DONE);
	if(unit)
	{
		Base->IExec->InitSemaphore((APTR)unit);
		unit->unitn=unitn;
		Base->IExec->ObtainSemaphore((APTR)unit);
		unit->InterruptService.is_Node.ln_Name=(APTR)xHCIdevInterruptName;
		unit->InterruptService.is_Data=unit;
		unit->InterruptService.is_Code=(APTR)&HwInterruptService;
		Base->IExec->NewList(&unit->uQueue);
		HwCardReset(card);
		unit->uTask=Base->IExec->CreateTaskTags("XHCI Controller Task", UNIT_TASK_PRIORITY, &ExecUnitTask, UNIT_STACK_SIZE,
			AT_Param1, (uint32)Base->IExec, AT_Param2, (uint32)unit, AT_Param3, (uint32)Base, CT_LockStack, TRUE, TAG_DONE );
		if(unit->uTask)
			Base->IExec->AddIntServer(card->MapInterrupt(),&unit->InterruptService);
		Base->Library.lib_OpenCnt++;
		Base->IExec->ReleaseSemaphore((APTR)unit);
	}
	return;
};
'
I'm mostly wondering about where I may have screwed up the controller specific access, as during the exec DevInit routine the card needs to be reset, and the UnitTask will switch the controller itself into a running state along with obtaining and locking system resources for the controller specific scratch memory and other unit specific details.

I am also still to work on expanding the HwInterruptService() function to handle controller specific Interrupts ( I'm also specifically allocating it this way since I will be possibly handling multiple XHCI controllers and they all apparently talk with the OS the same way (just different locations for pre-defined register blocks.
or that is at least what the XHCI specification documentation appears to read like so far.

(I still think I have missed something after reading all the documentation through 3-4 times too)
Post Reply