mirror of
https://github.com/reactos/reactos.git
synced 2024-07-11 07:05:12 +00:00
Merge 15329:15546 from trunk
svn path=/branches/xmlbuildsystem/; revision=15547
This commit is contained in:
commit
062423314c
|
@ -1,4 +1,4 @@
|
|||
/* $Id$
|
||||
/*
|
||||
*
|
||||
* ReactOS ps - process list console viewer
|
||||
*
|
||||
|
@ -26,6 +26,67 @@
|
|||
/* NOTE: W32API ddk/ntapi.h header has wrong definition of SYSTEM_PROCESSES. */
|
||||
#include <ntos/types.h>
|
||||
|
||||
typedef struct _SYSTEM_THREADS
|
||||
{
|
||||
LARGE_INTEGER KernelTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
LARGE_INTEGER CreateTime;
|
||||
ULONG WaitTime;
|
||||
PVOID StartAddress;
|
||||
CLIENT_ID ClientId;
|
||||
KPRIORITY Priority;
|
||||
LONG BasePriority;
|
||||
ULONG ContextSwitches;
|
||||
ULONG ThreadState;
|
||||
ULONG WaitReason;
|
||||
} SYSTEM_THREADS, *PSYSTEM_THREADS;
|
||||
|
||||
typedef struct _SYSTEM_PROCESSES
|
||||
{
|
||||
ULONG NextEntryOffset;
|
||||
ULONG NumberOfThreads;
|
||||
LARGE_INTEGER SpareLi1;
|
||||
LARGE_INTEGER SpareLi2;
|
||||
LARGE_INTEGER SpareLi3;
|
||||
LARGE_INTEGER CreateTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
LARGE_INTEGER KernelTime;
|
||||
UNICODE_STRING ImageName;
|
||||
KPRIORITY BasePriority;
|
||||
HANDLE UniqueProcessId;
|
||||
HANDLE InheritedFromUniqueProcessId;
|
||||
ULONG HandleCount;
|
||||
ULONG SessionId;
|
||||
ULONG PageDirectoryFrame;
|
||||
|
||||
/*
|
||||
* This part corresponds to VM_COUNTERS_EX.
|
||||
* NOTE: *NOT* THE SAME AS VM_COUNTERS!
|
||||
*/
|
||||
ULONG PeakVirtualSize;
|
||||
ULONG VirtualSize;
|
||||
ULONG PageFaultCount;
|
||||
ULONG PeakWorkingSetSize;
|
||||
ULONG WorkingSetSize;
|
||||
ULONG QuotaPeakPagedPoolUsage;
|
||||
ULONG QuotaPagedPoolUsage;
|
||||
ULONG QuotaPeakNonPagedPoolUsage;
|
||||
ULONG QuotaNonPagedPoolUsage;
|
||||
ULONG PagefileUsage;
|
||||
ULONG PeakPagefileUsage;
|
||||
ULONG PrivateUsage;
|
||||
|
||||
/* This part corresponds to IO_COUNTERS */
|
||||
LARGE_INTEGER ReadOperationCount;
|
||||
LARGE_INTEGER WriteOperationCount;
|
||||
LARGE_INTEGER OtherOperationCount;
|
||||
LARGE_INTEGER ReadTransferCount;
|
||||
LARGE_INTEGER WriteTransferCount;
|
||||
LARGE_INTEGER OtherTransferCount;
|
||||
|
||||
SYSTEM_THREADS Threads [1];
|
||||
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
|
||||
|
||||
|
||||
// x00000000 00000000 000:00:00 000:00:00 ()
|
||||
static char* title = "P PID PPID KTime UTime NAME\n";
|
||||
|
@ -36,7 +97,7 @@ static char* title2 = "w PID Hwnd WndStile TID WndName\n";
|
|||
struct status {
|
||||
DWORD state;
|
||||
char desc[10];
|
||||
} thread_stat[8 + 1] = {
|
||||
} thread_stat[8 + 1] = {
|
||||
{0, "Init "},
|
||||
{1, "Ready "},
|
||||
{2, "Running "},
|
||||
|
@ -50,39 +111,45 @@ struct status {
|
|||
|
||||
struct waitres {
|
||||
DWORD state;
|
||||
char desc[11];
|
||||
} waitreason[28 + 1] = {
|
||||
{0, "Executive "},
|
||||
{1, "FreePage "},
|
||||
{2, "PageIn "},
|
||||
{3, "PoolAlloc "},
|
||||
{4, "DelayExec "},
|
||||
{5, "Suspended "},
|
||||
{6, "UserReq "},
|
||||
{7, "WrExecutive"},
|
||||
{8, "WrFreePage "},
|
||||
{9, "WrPageIn "},
|
||||
{10,"WrPoolAlloc"},
|
||||
{11,"WrDelayExec"},
|
||||
{12,"WrSuspended"},
|
||||
{13,"WrUserReq "},
|
||||
{14,"WrEventPair"},
|
||||
{15,"WrQueue "},
|
||||
{16,"WrLpcRec "},
|
||||
{17,"WrLpcReply "},
|
||||
{18,"WrVirtualMm"},
|
||||
{19,"WrPageOut "},
|
||||
{20,"WrRendez "},
|
||||
{21,"Spare1 "},
|
||||
{22,"Spare2 "},
|
||||
{23,"Spare3 "},
|
||||
{24,"Spare4 "},
|
||||
{25,"Spare5 "},
|
||||
{26,"Spare6 "},
|
||||
{27,"WrKernel "},
|
||||
{-1," ? "}
|
||||
char desc[17];
|
||||
} waitreason[35 + 1] = {
|
||||
{0, "Executive "},
|
||||
{1, "FreePage "},
|
||||
{2, "PageIn "},
|
||||
{3, "PoolAllocation "},
|
||||
{4, "DelayExecution "},
|
||||
{5, "Suspended "},
|
||||
{6, "UserRequest "},
|
||||
{7, "WrExecutive "},
|
||||
{8, "WrFreePage "},
|
||||
{9, "WrPageIn "},
|
||||
{10,"WrPoolAllocation "},
|
||||
{11,"WrDelayExecution "},
|
||||
{12,"WrSuspended "},
|
||||
{13,"WrUserRequest "},
|
||||
{14,"WrEventPair "},
|
||||
{15,"WrQueue "},
|
||||
{16,"WrLpcReceive "},
|
||||
{17,"WrLpcReply "},
|
||||
{18,"WrVirtualMemory "},
|
||||
{19,"WrPageOut "},
|
||||
{20,"WrRendezvous "},
|
||||
{21,"Spare2 "},
|
||||
{22,"WrGuardedMutex "},
|
||||
{23,"Spare4 "},
|
||||
{24,"Spare5 "},
|
||||
{25,"Spare6 "},
|
||||
{26,"WrKernel "},
|
||||
{27,"WrResource "},
|
||||
{28,"WrPushLock "},
|
||||
{29,"WrMutex "},
|
||||
{30,"WrQuantumEnd "},
|
||||
{31,"WrDispatchInt "},
|
||||
{32,"WrPreempted "},
|
||||
{33,"WrYieldExecution "},
|
||||
{34,"MaximumWaitReason"},
|
||||
{-1," ? "}
|
||||
};
|
||||
|
||||
BOOL CALLBACK
|
||||
EnumThreadProc(HWND hwnd, LPARAM lp)
|
||||
{
|
||||
|
@ -90,9 +157,9 @@ EnumThreadProc(HWND hwnd, LPARAM lp)
|
|||
LONG style;
|
||||
HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
char buf[256];
|
||||
|
||||
|
||||
GetWindowText(hwnd, (LPTSTR)lp, 30);
|
||||
|
||||
|
||||
if(hwnd != 0)
|
||||
{
|
||||
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||
|
@ -110,13 +177,13 @@ int main()
|
|||
DWORD r;
|
||||
ANSI_STRING astring;
|
||||
HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
PSYSTEM_PROCESS_INFORMATION SystemProcesses = NULL;
|
||||
PSYSTEM_PROCESS_INFORMATION CurrentProcess;
|
||||
PSYSTEM_PROCESSES SystemProcesses = NULL;
|
||||
PSYSTEM_PROCESSES CurrentProcess;
|
||||
ULONG BufferSize, ReturnSize;
|
||||
NTSTATUS Status;
|
||||
char buf[256];
|
||||
char buf1[256];
|
||||
|
||||
|
||||
WriteFile(stdout, title, lstrlen(title), &r, NULL);
|
||||
WriteFile(stdout, title1, lstrlen(title1), &r, NULL);
|
||||
WriteFile(stdout, title2, lstrlen(title2), &r, NULL);
|
||||
|
@ -153,7 +220,7 @@ int main()
|
|||
hour = (ptime.QuadPart / (10000000LL * 3600LL));
|
||||
minute = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
|
||||
seconds = (ptime.QuadPart / 10000000LL) % 60LL;
|
||||
|
||||
|
||||
ptime.QuadPart = CurrentProcess->UserTime.QuadPart;
|
||||
hour1 = (ptime.QuadPart / (10000000LL * 3600LL));
|
||||
minute1 = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
|
||||
|
@ -166,7 +233,7 @@ int main()
|
|||
hour, minute, seconds, hour1, minute1, seconds1,
|
||||
astring.Buffer);
|
||||
WriteFile(stdout, buf, lstrlen(buf), &r, NULL);
|
||||
|
||||
|
||||
RtlFreeAnsiString(&astring);
|
||||
|
||||
for (ti = 0; ti < CurrentProcess->NumberOfThreads; ti++)
|
||||
|
@ -175,37 +242,37 @@ int main()
|
|||
struct waitres *waitt;
|
||||
char szWindowName[30] = {" "};
|
||||
|
||||
ptime = CurrentProcess->TH[ti].KernelTime;
|
||||
ptime = CurrentProcess->Threads[ti].KernelTime;
|
||||
thour = (ptime.QuadPart / (10000000LL * 3600LL));
|
||||
tmin = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
|
||||
tsec = (ptime.QuadPart / 10000000LL) % 60LL;
|
||||
|
||||
ptime = CurrentProcess->TH[ti].UserTime;
|
||||
ptime = CurrentProcess->Threads[ti].UserTime;
|
||||
thour1 = (ptime.QuadPart / (10000000LL * 3600LL));
|
||||
tmin1 = (ptime.QuadPart / (10000000LL * 60LL)) % 60LL;
|
||||
tsec1 = (ptime.QuadPart / 10000000LL) % 60LL;
|
||||
|
||||
statt = thread_stat;
|
||||
while (statt->state != CurrentProcess->TH[ti].ThreadState && statt->state >= 0)
|
||||
while (statt->state != CurrentProcess->Threads[ti].ThreadState && statt->state >= 0)
|
||||
statt++;
|
||||
|
||||
waitt = waitreason;
|
||||
while (waitt->state != CurrentProcess->TH[ti].WaitReason && waitt->state >= 0)
|
||||
while (waitt->state != CurrentProcess->Threads[ti].WaitReason && waitt->state >= 0)
|
||||
waitt++;
|
||||
|
||||
wsprintf (buf1,
|
||||
wsprintf (buf1,
|
||||
"t% %8d %3d:%02d:%02d %3d:%02d:%02d %s %s\n",
|
||||
CurrentProcess->TH[ti].ClientId.UniqueThread,
|
||||
CurrentProcess->Threads[ti].ClientId.UniqueThread,
|
||||
thour, tmin, tsec, thour1, tmin1, tsec1,
|
||||
statt->desc , waitt->desc);
|
||||
WriteFile(stdout, buf1, lstrlen(buf1), &r, NULL);
|
||||
|
||||
EnumThreadWindows((DWORD)CurrentProcess->TH[ti].ClientId.UniqueThread,
|
||||
EnumThreadWindows((DWORD)CurrentProcess->Threads[ti].ClientId.UniqueThread,
|
||||
(ENUMWINDOWSPROC) EnumThreadProc,
|
||||
(LPARAM)(LPTSTR) szWindowName );
|
||||
}
|
||||
CurrentProcess = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)CurrentProcess +
|
||||
CurrentProcess = (PSYSTEM_PROCESSES)((ULONG_PTR)CurrentProcess +
|
||||
CurrentProcess->NextEntryOffset);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -1715,7 +1715,7 @@ DetectKeyboardPeripheral(FRLDRHKEY ControllerKey)
|
|||
/* Set 'Identifier' value */
|
||||
strcpy(Buffer,
|
||||
"PCAT_ENHANCED");
|
||||
Error = RegSetValue(ControllerKey,
|
||||
Error = RegSetValue(PeripheralKey,
|
||||
"Identifier",
|
||||
REG_SZ,
|
||||
Buffer,
|
||||
|
|
|
@ -205,9 +205,27 @@ BOOL i386DiskGetBootVolume(PULONG DriveNumber, PULONGLONG StartSector, PULONGLON
|
|||
{
|
||||
// Partition requested was zero which means the boot partition
|
||||
if (! DiskGetActivePartitionEntry(i386BootDrive, &PartitionTableEntry))
|
||||
{
|
||||
/* Try partition-less disk */
|
||||
*StartSector = 0;
|
||||
*SectorCount = 0;
|
||||
}
|
||||
/* Check for valid partition */
|
||||
else if (PartitionTableEntry.SystemIndicator == PARTITION_ENTRY_UNUSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*StartSector = PartitionTableEntry.SectorCountBeforePartition;
|
||||
*SectorCount = PartitionTableEntry.PartitionSectorCount;
|
||||
}
|
||||
}
|
||||
else if (0xff == i386BootPartition)
|
||||
{
|
||||
/* Partition-less disk */
|
||||
*StartSector = 0;
|
||||
*SectorCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -216,25 +234,26 @@ BOOL i386DiskGetBootVolume(PULONG DriveNumber, PULONGLONG StartSector, PULONGLON
|
|||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for valid partition
|
||||
if (PartitionTableEntry.SystemIndicator == PARTITION_ENTRY_UNUSED)
|
||||
{
|
||||
return FALSE;
|
||||
/* Check for valid partition */
|
||||
else if (PartitionTableEntry.SystemIndicator == PARTITION_ENTRY_UNUSED)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*StartSector = PartitionTableEntry.SectorCountBeforePartition;
|
||||
*SectorCount = PartitionTableEntry.PartitionSectorCount;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to recognize the file system
|
||||
if (!FsRecognizeVolume(i386BootDrive, PartitionTableEntry.SectorCountBeforePartition, &VolumeType))
|
||||
if (!FsRecognizeVolume(i386BootDrive, *StartSector, &VolumeType))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*DriveNumber = i386BootDrive;
|
||||
*StartSector = PartitionTableEntry.SectorCountBeforePartition;
|
||||
*SectorCount = PartitionTableEntry.PartitionSectorCount;
|
||||
|
||||
//switch (PartitionTableEntry.SystemIndicator)
|
||||
switch (VolumeType)
|
||||
{
|
||||
case PARTITION_FAT_12:
|
||||
|
|
|
@ -63,12 +63,12 @@ BOOL DiskGetActivePartitionEntry(ULONG DriveNumber, PPARTITION_TABLE_ENTRY Parti
|
|||
// Make sure there was only one bootable partition
|
||||
if (BootablePartitionCount == 0)
|
||||
{
|
||||
DiskError("No bootable (active) partitions found.", 0);
|
||||
DbgPrint((DPRINT_DISK, "No bootable (active) partitions found.\n"));
|
||||
return FALSE;
|
||||
}
|
||||
else if (BootablePartitionCount != 1)
|
||||
{
|
||||
DiskError("Too many bootable (active) partitions found.", 0);
|
||||
DbgPrint((DPRINT_DISK, "Too many bootable (active) partitions found.\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ VOID BootMain(char *CmdLine)
|
|||
|
||||
DebugInit();
|
||||
|
||||
DbgPrint((DPRINT_WARNING, "BootMain() called. BootDrive = 0x%x BootPartition = %d\n", BootDrive, BootPartition));
|
||||
DbgPrint((DPRINT_WARNING, "BootMain() called.\n"));
|
||||
|
||||
if (!MmInitializeMemoryManager())
|
||||
{
|
||||
|
|
|
@ -36,10 +36,30 @@ VOID DecrementAllocationCount(VOID);
|
|||
VOID MemAllocTest(VOID);
|
||||
#endif // DEBUG
|
||||
|
||||
/*
|
||||
* Hack alert
|
||||
* Normally, we allocate whole pages. This is ofcourse wastefull for small
|
||||
* allocations (a few bytes). So, for small allocations (smaller than a page)
|
||||
* we sub-allocate. When the first small allocation is done, a page is
|
||||
* requested. We keep a pointer to that page in SubAllocationPage. The alloc
|
||||
* is satisfied by returning a pointer to the beginning of the page. We also
|
||||
* keep track of how many bytes are still available in the page in SubAllocationRest.
|
||||
* When the next small request comes in, we try to allocate it just after the
|
||||
* memory previously allocated. If it won't fit, we allocate a new page and
|
||||
* the whole process starts again.
|
||||
* Note that suballocations are done back-to-back, there's no bookkeeping at all.
|
||||
* That also means that we cannot really free suballocations. So, when a free is
|
||||
* done and it is determined that this might be a free of a sub-allocation, we
|
||||
* just no-op the free.
|
||||
* Perhaps we should use the heap routines from ntdll here.
|
||||
*/
|
||||
static PVOID SubAllocationPage = NULL;
|
||||
static unsigned SubAllocationRest = 0;
|
||||
|
||||
PVOID MmAllocateMemory(ULONG MemorySize)
|
||||
{
|
||||
ULONG PagesNeeded;
|
||||
ULONG FirstFreePageFromEnd;
|
||||
ULONG PagesNeeded;
|
||||
ULONG FirstFreePageFromEnd;
|
||||
PVOID MemPointer;
|
||||
|
||||
if (MemorySize == 0)
|
||||
|
@ -49,6 +69,14 @@ PVOID MmAllocateMemory(ULONG MemorySize)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
MemorySize = ROUND_UP(MemorySize, 4);
|
||||
if (MemorySize <= SubAllocationRest)
|
||||
{
|
||||
MemPointer = SubAllocationPage + MM_PAGE_SIZE - SubAllocationRest;
|
||||
SubAllocationRest -= MemorySize;
|
||||
return MemPointer;
|
||||
}
|
||||
|
||||
// Find out how many blocks it will take to
|
||||
// satisfy this allocation
|
||||
PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE;
|
||||
|
@ -76,6 +104,13 @@ PVOID MmAllocateMemory(ULONG MemorySize)
|
|||
FreePagesInLookupTable -= PagesNeeded;
|
||||
MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE);
|
||||
|
||||
if (MemorySize < MM_PAGE_SIZE)
|
||||
{
|
||||
SubAllocationPage = MemPointer;
|
||||
SubAllocationRest = MM_PAGE_SIZE - MemorySize;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
IncrementAllocationCount();
|
||||
DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, FirstFreePageFromEnd, AllocationCount));
|
||||
|
@ -235,6 +270,13 @@ VOID MmFreeMemory(PVOID MemoryPointer)
|
|||
|
||||
#endif
|
||||
|
||||
/* If this allocation is only a single page, it could be a sub-allocated page.
|
||||
* Just don't free it */
|
||||
if (1 == PageCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through our array and mark all the
|
||||
// blocks as free
|
||||
for (Idx=PageNumber; Idx<(PageNumber + PageCount); Idx++)
|
||||
|
|
|
@ -756,6 +756,16 @@ LoadAndBootReactOS(PCHAR OperatingSystemName)
|
|||
if (!FrLdrLoadDriver(szHalName, 10))
|
||||
return;
|
||||
|
||||
#if 0
|
||||
/* Load bootvid */
|
||||
strcpy(value, "INBV.DLL");
|
||||
strcpy(szHalName, szBootPath);
|
||||
strcat(szHalName, "SYSTEM32\\");
|
||||
strcat(szHalName, value);
|
||||
|
||||
if (!FrLdrLoadDriver(szHalName, 10))
|
||||
return;
|
||||
#endif
|
||||
/*
|
||||
* Load the System hive from disk
|
||||
*/
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "registry.h"
|
||||
|
||||
|
||||
//#define USE_UI
|
||||
#define USE_UI
|
||||
|
||||
|
||||
static BOOL
|
||||
|
@ -88,7 +88,7 @@ LoadKernel(PCHAR szSourcePath, PCHAR szFileName)
|
|||
* Update the status bar with the current file
|
||||
*/
|
||||
#ifdef USE_UI
|
||||
sprintf(szBuffer, "Reading %s", szShortName);
|
||||
sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
|
||||
UiDrawStatusText(szBuffer);
|
||||
#else
|
||||
printf("Reading %s\n", szShortName);
|
||||
|
@ -155,7 +155,7 @@ LoadDriver(PCHAR szSourcePath, PCHAR szFileName)
|
|||
* Update the status bar with the current file
|
||||
*/
|
||||
#ifdef USE_UI
|
||||
sprintf(szBuffer, "Reading %s", szShortName);
|
||||
sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
|
||||
UiDrawStatusText(szBuffer);
|
||||
#else
|
||||
printf("Reading %s\n", szShortName);
|
||||
|
@ -220,7 +220,7 @@ LoadNlsFile(PCHAR szSourcePath, PCHAR szFileName, PCHAR szModuleName)
|
|||
* Update the status bar with the current file
|
||||
*/
|
||||
#ifdef USE_UI
|
||||
sprintf(szBuffer, "Reading %s", szShortName);
|
||||
sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
|
||||
UiDrawStatusText(szBuffer);
|
||||
#else
|
||||
printf("Reading %s\n", szShortName);
|
||||
|
@ -232,6 +232,7 @@ LoadNlsFile(PCHAR szSourcePath, PCHAR szFileName, PCHAR szModuleName)
|
|||
return(TRUE);
|
||||
}
|
||||
|
||||
BOOL SetupUiInitialize(VOID);
|
||||
|
||||
VOID RunLoader(VOID)
|
||||
{
|
||||
|
@ -294,7 +295,7 @@ VOID RunLoader(VOID)
|
|||
#endif
|
||||
|
||||
#ifdef USE_UI
|
||||
UiInitialize();
|
||||
SetupUiInitialize();
|
||||
UiDrawStatusText("");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <inifile.h>
|
||||
#include <version.h>
|
||||
#include <video.h>
|
||||
#include <reactos/buildno.h>
|
||||
|
||||
ULONG UiScreenWidth = 80; // Screen Width
|
||||
ULONG UiScreenHeight = 25; // Screen Height
|
||||
|
@ -196,6 +197,39 @@ BOOL UiInitialize(BOOLEAN ShowGui)
|
|||
|
||||
UserInterfaceUp = TRUE;
|
||||
|
||||
DbgPrint((DPRINT_UI, "UiInitialize() returning TRUE.\n"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetupUiInitialize(VOID)
|
||||
{
|
||||
|
||||
CHAR DisplayModeText[260];
|
||||
ULONG Depth;
|
||||
|
||||
|
||||
DisplayModeText[0] = '\0';
|
||||
|
||||
|
||||
UiDisplayMode = MachVideoSetDisplayMode(DisplayModeText, TRUE);
|
||||
MachVideoGetDisplaySize(&UiScreenWidth, &UiScreenHeight, &Depth);
|
||||
|
||||
TuiInitialize();
|
||||
|
||||
// Draw the backdrop and fade it in if special effects are enabled
|
||||
TuiFillArea(0,
|
||||
0,
|
||||
UiScreenWidth - 1,
|
||||
UiScreenHeight - 2,
|
||||
0,
|
||||
ATTR(UiBackdropFgColor, UiBackdropBgColor));
|
||||
|
||||
UiStatusBarBgColor = 7;
|
||||
UserInterfaceUp = TRUE;
|
||||
|
||||
TuiDrawText(4, 1, "ReactOS " KERNEL_VERSION_STR " Setup", ATTR(COLOR_GRAY, UiBackdropBgColor));
|
||||
TuiDrawText(3, 2, "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD", ATTR(COLOR_GRAY, UiBackdropBgColor));
|
||||
|
||||
DbgPrint((DPRINT_UI, "UiInitialize() returning TRUE.\n"));
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -46,6 +46,9 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E975-E325-11CE-BFC1-08002BE103
|
|||
HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName",,0x00000012
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName","ComputerName",0x00000002,"COMPUTERNAME"
|
||||
|
||||
; Device classes key
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\DeviceClasses",,0x00000012
|
||||
|
||||
; Hardware profile settings
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\IDConfigDB",,0x00000012
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\IDConfigDB","CurrentConfig",0x00010001,0x00000000
|
||||
|
@ -529,7 +532,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Class2","Type",0x00010001,0x00000001
|
|||
HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","ErrorControl",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","Group",0x00000000,"Debug"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","ImagePath",0x00020000,"system32\drivers\debugout.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","Start",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","Start",0x00010001,0x00000004
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\DebugOut","Type",0x00010001,0x00000001
|
||||
|
||||
; Disk class driver
|
||||
|
@ -675,7 +678,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","Type",0x00010001,0x00000001
|
|||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne2000","ErrorControl",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne2000","Group",0x00000000,"NDIS"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne2000","ImagePath",0x00020000,"system32\drivers\ne2000.sys"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne2000","Start",0x00010001,0x00000004
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne2000","Start",0x00010001,0x00000003
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne2000","Type",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne2000","Route",0x00000000,"Ne20001"
|
||||
|
||||
|
@ -687,8 +690,8 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE103
|
|||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001\Linkage","Export",0x00000000,"\Device\Ne20001"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001\Linkage","RootDevice",0x00000000,"Ne20001"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001\Linkage","UpperBind",0x00000000,"Tcpip"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001","Port",0x00000000,"280"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001","Irq",0x00000000,"9"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001","Port",0x00000000,"c100"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001","Irq",0x00000000,"B"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0001","NetworkAddress",0x00000000,"001122334455"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne20001\Parameters\Tcpip","DefaultGateway",0x00010000,"0.0.0.0"
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Ne20001\Parameters\Tcpip","IPAddress",0x00010000,"0.0.0.0"
|
||||
|
@ -926,6 +929,12 @@ HKLM,"SYSTEM\CurrentControlSet\Services\VBE","Start",0x00010001,0x00000004
|
|||
HKLM,"SYSTEM\CurrentControlSet\Services\VBE","Type",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\VBE\Device0","InstalledDisplayDrivers",0x00010000,"framebuf"
|
||||
|
||||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.VRefresh",0x00010001,1
|
||||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.BitsPerPel",0x00010001,8
|
||||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.XResolution",0x00010001,640
|
||||
HKLM,"SYSTEM\CurrentControlSet\Hardware Profiles\Current\System\CurrentControlSet\Services\VBE\Device0","DefaultSettings.YResolution",0x00010001,480
|
||||
|
||||
|
||||
; VGA miniport driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Vga","ErrorControl",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Vga","Group",0x00000000,"Video Save"
|
||||
|
@ -934,6 +943,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Vga","Start",0x00010001,0x00000004
|
|||
HKLM,"SYSTEM\CurrentControlSet\Services\Vga","Type",0x00010001,0x00000001
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Vga\Device0","InstalledDisplayDrivers",0x00010000,"vgaddi"
|
||||
|
||||
|
||||
; VMware SVGA driver
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\vmx_svga","ErrorControl",0x00010001,0x00000000
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\vmx_svga","Group",0x00000000,"Video"
|
||||
|
|
|
@ -16,7 +16,7 @@ Signature = "$ReactOS$"
|
|||
1 = system32
|
||||
2 = system32\drivers
|
||||
3 = media\fonts
|
||||
4 = .
|
||||
4 =
|
||||
5 = system32\drivers\etc
|
||||
6 = inf
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ DriverEntry(
|
|||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
DbgPrint("Advanced Configuration and Power Interface Bus Driver\n");
|
||||
DPRINT("Advanced Configuration and Power Interface Bus Driver\n");
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH) ACPIDispatchDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) ACPIPnpControl;
|
||||
|
|
|
@ -119,12 +119,16 @@ AcpiCreateInstanceIDString(PUNICODE_STRING InstanceID,
|
|||
static BOOLEAN
|
||||
AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
|
||||
PULONG ResourceListSize,
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST* pRequirementsList,
|
||||
PULONG RequirementsListSize,
|
||||
RESOURCE* resources)
|
||||
{
|
||||
BOOLEAN Done;
|
||||
ULONG NumberOfResources = 0;
|
||||
PCM_RESOURCE_LIST ResourceList;
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
|
||||
PIO_RESOURCE_DESCRIPTOR RequirementDescriptor;
|
||||
RESOURCE* resource;
|
||||
ULONG i;
|
||||
KIRQL Dirql;
|
||||
|
@ -176,6 +180,24 @@ AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
|
|||
ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
|
||||
ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
|
||||
|
||||
*RequirementsListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
|
||||
RequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(PagedPool, *RequirementsListSize);
|
||||
*pRequirementsList = RequirementsList;
|
||||
if (!RequirementsList)
|
||||
{
|
||||
ExFreePool(ResourceList);
|
||||
return FALSE;
|
||||
}
|
||||
RequirementsList->ListSize = *RequirementsListSize;
|
||||
RequirementsList->InterfaceType = ResourceList->List[0].InterfaceType;
|
||||
RequirementsList->BusNumber = ResourceList->List[0].BusNumber;
|
||||
RequirementsList->SlotNumber = 0; /* Not used by WDM drivers */
|
||||
RequirementsList->AlternativeLists = 1;
|
||||
RequirementsList->List[0].Version = 1;
|
||||
RequirementsList->List[0].Revision = 1;
|
||||
RequirementsList->List[0].Count = NumberOfResources;
|
||||
RequirementDescriptor = RequirementsList->List[0].Descriptors;
|
||||
|
||||
/* Fill resources list structure */
|
||||
Done = FALSE;
|
||||
resource = resources;
|
||||
|
@ -199,7 +221,16 @@ AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
|
|||
&Dirql,
|
||||
&ResourceDescriptor->u.Interrupt.Affinity);
|
||||
ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql;
|
||||
|
||||
RequirementDescriptor->Option = 0; /* Required */
|
||||
RequirementDescriptor->Type = ResourceDescriptor->Type;
|
||||
RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
|
||||
RequirementDescriptor->Flags = ResourceDescriptor->Flags;
|
||||
RequirementDescriptor->u.Interrupt.MinimumVector = RequirementDescriptor->u.Interrupt.MaximumVector
|
||||
= irq_data->interrupts[i];
|
||||
|
||||
ResourceDescriptor++;
|
||||
RequirementDescriptor++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -225,7 +256,16 @@ AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
|
|||
case TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
|
||||
}
|
||||
ResourceDescriptor->u.Dma.Channel = dma_data->channels[i];
|
||||
|
||||
RequirementDescriptor->Option = 0; /* Required */
|
||||
RequirementDescriptor->Type = ResourceDescriptor->Type;
|
||||
RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
|
||||
RequirementDescriptor->Flags = ResourceDescriptor->Flags;
|
||||
RequirementDescriptor->u.Dma.MinimumChannel = RequirementDescriptor->u.Dma.MaximumChannel
|
||||
= ResourceDescriptor->u.Dma.Channel;
|
||||
|
||||
ResourceDescriptor++;
|
||||
RequirementDescriptor++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -242,7 +282,18 @@ AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
|
|||
ResourceDescriptor->u.Port.Start.u.HighPart = 0;
|
||||
ResourceDescriptor->u.Port.Start.u.LowPart = io_data->min_base_address;
|
||||
ResourceDescriptor->u.Port.Length = io_data->range_length;
|
||||
|
||||
RequirementDescriptor->Option = 0; /* Required */
|
||||
RequirementDescriptor->Type = ResourceDescriptor->Type;
|
||||
RequirementDescriptor->ShareDisposition = ResourceDescriptor->ShareDisposition;
|
||||
RequirementDescriptor->Flags = ResourceDescriptor->Flags;
|
||||
RequirementDescriptor->u.Port.Length = ResourceDescriptor->u.Port.Length;
|
||||
RequirementDescriptor->u.Port.Alignment = 1; /* Start address is specified, so it doesn't matter */
|
||||
RequirementDescriptor->u.Port.MinimumAddress = RequirementDescriptor->u.Port.MaximumAddress
|
||||
= ResourceDescriptor->u.Port.Start;
|
||||
|
||||
ResourceDescriptor++;
|
||||
RequirementDescriptor++;
|
||||
break;
|
||||
}
|
||||
case end_tag:
|
||||
|
@ -366,6 +417,8 @@ FdoQueryBusRelations(
|
|||
}
|
||||
if (!AcpiCreateResourceList(&PdoDeviceExtension->ResourceList,
|
||||
&PdoDeviceExtension->ResourceListSize,
|
||||
&PdoDeviceExtension->ResourceRequirementsList,
|
||||
&PdoDeviceExtension->ResourceRequirementsListSize,
|
||||
(RESOURCE*)Buffer.pointer))
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
|
@ -573,7 +626,9 @@ FdoStartDevice(
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
ACPIPrintInfo(DeviceExtension);
|
||||
#endif
|
||||
|
||||
/* Initialize ACPI bus manager */
|
||||
AcpiStatus = bm_initialize();
|
||||
|
|
|
@ -50,6 +50,9 @@ typedef struct _PDO_DEVICE_EXTENSION
|
|||
// Resource list
|
||||
PCM_RESOURCE_LIST ResourceList;
|
||||
ULONG ResourceListSize;
|
||||
// Requirement list
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
|
||||
ULONG ResourceRequirementsListSize;
|
||||
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
|
||||
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ acpi_os_vprintf(const NATIVE_CHAR *fmt, va_list args)
|
|||
static char Buffer[512];
|
||||
LONG Size = vsprintf(Buffer, fmt, args);
|
||||
|
||||
DbgPrint("%s", Buffer);
|
||||
DPRINT("%s", Buffer);
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,35 @@ PdoQueryId(
|
|||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
PdoQueryResourceRequirements(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PPDO_DEVICE_EXTENSION DeviceExtension;
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
|
||||
|
||||
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
if (DeviceExtension->ResourceRequirementsListSize == 0)
|
||||
{
|
||||
return Irp->IoStatus.Status;
|
||||
}
|
||||
|
||||
ResourceRequirementsList = ExAllocatePool(PagedPool, DeviceExtension->ResourceRequirementsListSize);
|
||||
if (!ResourceRequirementsList)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(ResourceRequirementsList, DeviceExtension->ResourceRequirementsList, DeviceExtension->ResourceRequirementsListSize);
|
||||
Irp->IoStatus.Information = (ULONG_PTR)ResourceRequirementsList;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
PdoQueryResources(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -227,6 +256,9 @@ PdoPnpControl(
|
|||
break;
|
||||
|
||||
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
||||
Status = PdoQueryResourceRequirements(DeviceObject,
|
||||
Irp,
|
||||
IrpSp);
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_RESOURCES:
|
||||
|
|
|
@ -172,7 +172,7 @@ DriverEntry(
|
|||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
DbgPrint("Peripheral Component Interconnect Bus Driver\n");
|
||||
DPRINT("Peripheral Component Interconnect Bus Driver\n");
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl;
|
||||
|
|
|
@ -409,6 +409,8 @@ PdoQueryResourceRequirements(
|
|||
|
||||
ResourceList->ListSize = ListSize;
|
||||
ResourceList->InterfaceType = PCIBus;
|
||||
ResourceList->BusNumber = DeviceExtension->BusNumber,
|
||||
ResourceList->SlotNumber = DeviceExtension->SlotNumber.u.AsULONG,
|
||||
ResourceList->AlternativeLists = 1;
|
||||
|
||||
ResourceList->List[0].Version = 1;
|
||||
|
@ -433,7 +435,7 @@ PdoQueryResourceRequirements(
|
|||
if (Length == 0)
|
||||
{
|
||||
DPRINT("Unused address register\n");
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set preferred descriptor */
|
||||
|
@ -497,6 +499,7 @@ PdoQueryResourceRequirements(
|
|||
|
||||
if (PciConfig.u.type0.InterruptPin != 0)
|
||||
{
|
||||
Descriptor->Option = 0; /* Required */
|
||||
Descriptor->Type = CmResourceTypeInterrupt;
|
||||
Descriptor->ShareDisposition = CmResourceShareShared;
|
||||
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
||||
|
@ -522,7 +525,7 @@ PdoQueryResourceRequirements(
|
|||
if (Length == 0)
|
||||
{
|
||||
DPRINT("Unused address register\n");
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set preferred descriptor */
|
||||
|
@ -722,7 +725,7 @@ PdoQueryResources(
|
|||
if (Length == 0)
|
||||
{
|
||||
DPRINT("Unused address register\n");
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Flags & PCI_ADDRESS_IO_SPACE)
|
||||
|
@ -776,7 +779,7 @@ PdoQueryResources(
|
|||
if (Length == 0)
|
||||
{
|
||||
DPRINT("Unused address register\n");
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Flags & PCI_ADDRESS_IO_SPACE)
|
||||
|
|
|
@ -83,12 +83,13 @@ DetectLegacyDevice(
|
|||
{
|
||||
ULONG ResourceListSize;
|
||||
PCM_RESOURCE_LIST ResourceList;
|
||||
PCM_RESOURCE_LIST ResourceListTranslated;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptorTranslated;
|
||||
BOOLEAN ConflictDetected;
|
||||
UART_TYPE UartType;
|
||||
PDEVICE_OBJECT Pdo = NULL;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
KIRQL Dirql;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Create resource list */
|
||||
|
@ -96,29 +97,60 @@ DetectLegacyDevice(
|
|||
ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, ResourceListSize, SERIAL_TAG);
|
||||
if (!ResourceList)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
ResourceList->Count = 1;
|
||||
ResourceList->List[0].InterfaceType = InterfaceTypeUndefined;
|
||||
ResourceList->List[0].BusNumber = -1; /* unknown */
|
||||
ResourceList->List[0].PartialResourceList.Version = 1;
|
||||
ResourceList->List[0].PartialResourceList.Revision = 1;
|
||||
ResourceList->List[0].PartialResourceList.Count = 2;
|
||||
ResourceListTranslated = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, ResourceListSize, SERIAL_TAG);
|
||||
if (!ResourceListTranslated)
|
||||
{
|
||||
ExFreePoolWithTag(ResourceList, SERIAL_TAG);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Resource header */
|
||||
ResourceList->Count = ResourceListTranslated->Count
|
||||
= 1;
|
||||
ResourceList->List[0].InterfaceType = ResourceListTranslated->List[0].InterfaceType
|
||||
= InterfaceTypeUndefined;
|
||||
ResourceList->List[0].BusNumber = ResourceListTranslated->List[0].BusNumber
|
||||
= -1; /* unknown */
|
||||
ResourceList->List[0].PartialResourceList.Version = ResourceListTranslated->List[0].PartialResourceList.Version
|
||||
= 1;
|
||||
ResourceList->List[0].PartialResourceList.Revision = ResourceListTranslated->List[0].PartialResourceList.Revision
|
||||
= 1;
|
||||
ResourceList->List[0].PartialResourceList.Count = ResourceListTranslated->List[0].PartialResourceList.Count
|
||||
= 2;
|
||||
|
||||
/* I/O port */
|
||||
ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
|
||||
ResourceDescriptor->Type = CmResourceTypePort;
|
||||
ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
|
||||
ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
|
||||
ResourceDescriptor->u.Port.Start.u.HighPart = 0;
|
||||
ResourceDescriptor->u.Port.Start.u.LowPart = ComPortBase;
|
||||
ResourceDescriptor->u.Port.Length = 8;
|
||||
ResourceDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[0];
|
||||
ResourceDescriptor->Type = ResourceDescriptorTranslated->Type
|
||||
= CmResourceTypePort;
|
||||
ResourceDescriptor->ShareDisposition = ResourceDescriptorTranslated->ShareDisposition
|
||||
= CmResourceShareDriverExclusive;
|
||||
ResourceDescriptor->Flags = ResourceDescriptorTranslated->Flags
|
||||
= CM_RESOURCE_PORT_IO;
|
||||
ResourceDescriptor->u.Port.Start.u.HighPart = ResourceDescriptorTranslated->u.Port.Start.u.HighPart
|
||||
= 0;
|
||||
ResourceDescriptor->u.Port.Start.u.LowPart = ResourceDescriptorTranslated->u.Port.Start.u.LowPart
|
||||
= ComPortBase;
|
||||
ResourceDescriptor->u.Port.Length = ResourceDescriptorTranslated->u.Port.Length
|
||||
= 8;
|
||||
|
||||
ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[1];
|
||||
ResourceDescriptor->Type = CmResourceTypeInterrupt;
|
||||
ResourceDescriptor->ShareDisposition = CmResourceShareShared;
|
||||
ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
||||
ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector(
|
||||
Internal, 0, 0, Irq,
|
||||
&Dirql,
|
||||
ResourceDescriptorTranslated = &ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[1];
|
||||
ResourceDescriptor->Type = ResourceDescriptorTranslated->Type
|
||||
= CmResourceTypeInterrupt;
|
||||
ResourceDescriptor->ShareDisposition = ResourceDescriptorTranslated->ShareDisposition
|
||||
= CmResourceShareShared;
|
||||
ResourceDescriptor->Flags = ResourceDescriptorTranslated->Flags
|
||||
= CM_RESOURCE_INTERRUPT_LATCHED;
|
||||
ResourceDescriptor->u.Interrupt.Level = Irq;
|
||||
ResourceDescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector(
|
||||
ResourceList->List[0].InterfaceType,
|
||||
ResourceList->List[0].BusNumber,
|
||||
ResourceDescriptor->u.Interrupt.Level,
|
||||
ResourceDescriptor->u.Interrupt.Vector,
|
||||
(PKIRQL)&ResourceDescriptorTranslated->u.Interrupt.Level,
|
||||
&ResourceDescriptor->u.Interrupt.Affinity);
|
||||
ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql;
|
||||
ResourceDescriptorTranslated->u.Interrupt.Affinity = ResourceDescriptor->u.Interrupt.Affinity;
|
||||
|
||||
/* Report resource list */
|
||||
Status = IoReportResourceForDetection(
|
||||
|
@ -129,11 +161,13 @@ DetectLegacyDevice(
|
|||
{
|
||||
DPRINT("Serial: conflict detected for serial port at 0x%lx (Irq %lu)\n", ComPortBase, Irq);
|
||||
ExFreePoolWithTag(ResourceList, SERIAL_TAG);
|
||||
ExFreePoolWithTag(ResourceListTranslated, SERIAL_TAG);
|
||||
return STATUS_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePoolWithTag(ResourceList, SERIAL_TAG);
|
||||
ExFreePoolWithTag(ResourceListTranslated, SERIAL_TAG);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -154,7 +188,7 @@ DetectLegacyDevice(
|
|||
Status = SerialAddDeviceInternal(DriverObject, Pdo, UartType, pComPortNumber, &Fdo);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
Status = SerialPnpStartDevice(Fdo, ResourceList);
|
||||
Status = SerialPnpStartDevice(Fdo, ResourceList, ResourceListTranslated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,6 +202,7 @@ DetectLegacyDevice(
|
|||
Status = STATUS_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
ExFreePoolWithTag(ResourceList, SERIAL_TAG);
|
||||
ExFreePoolWithTag(ResourceListTranslated, SERIAL_TAG);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,8 @@ SerialAddDevice(
|
|||
NTSTATUS STDCALL
|
||||
SerialPnpStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PCM_RESOURCE_LIST ResourceList)
|
||||
IN PCM_RESOURCE_LIST ResourceList,
|
||||
IN PCM_RESOURCE_LIST ResourceListTranslated)
|
||||
{
|
||||
PSERIAL_DEVICE_EXTENSION DeviceExtension;
|
||||
WCHAR DeviceNameBuffer[32];
|
||||
|
@ -174,8 +175,8 @@ SerialPnpStartDevice(
|
|||
case CmResourceTypeInterrupt:
|
||||
if (Dirql != 0)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
Dirql = (KIRQL)PartialDescriptor->u.Interrupt.Level;
|
||||
Vector = PartialDescriptor->u.Interrupt.Vector;
|
||||
Dirql = (KIRQL)ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j].u.Interrupt.Level;
|
||||
Vector = ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j].u.Interrupt.Vector;
|
||||
Affinity = PartialDescriptor->u.Interrupt.Affinity;
|
||||
if (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
|
||||
InterruptMode = Latched;
|
||||
|
@ -338,16 +339,9 @@ SerialPnp(
|
|||
BOOLEAN ConflictDetected;
|
||||
DPRINT("Serial: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
|
||||
|
||||
/* FIXME: first HACK: PnP manager can send multiple
|
||||
* IRP_MN_START_DEVICE for one device
|
||||
*/
|
||||
if (((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PnpState != dsStopped)
|
||||
{
|
||||
DPRINT1("Serial: device already started. Ignoring this irp!\n");
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
/* FIXME: second HACK: verify that we have some allocated resources.
|
||||
ASSERT(((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PnpState == dsStopped);
|
||||
|
||||
/* FIXME: HACK: verify that we have some allocated resources.
|
||||
* It seems not to be always the case on some hardware
|
||||
*/
|
||||
if (Stack->Parameters.StartDevice.AllocatedResources == NULL)
|
||||
|
@ -357,7 +351,7 @@ SerialPnp(
|
|||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
break;
|
||||
}
|
||||
/* FIXME: third HACK: verify that we don't have resource conflict,
|
||||
/* FIXME: HACK: verify that we don't have resource conflict,
|
||||
* because PnP manager doesn't do it automatically
|
||||
*/
|
||||
Status = IoReportResourceForDetection(
|
||||
|
@ -377,7 +371,8 @@ SerialPnp(
|
|||
if (NT_SUCCESS(Status))
|
||||
Status = SerialPnpStartDevice(
|
||||
DeviceObject,
|
||||
Stack->Parameters.StartDevice.AllocatedResources);
|
||||
Stack->Parameters.StartDevice.AllocatedResources,
|
||||
Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
|
||||
|
|
|
@ -327,7 +327,8 @@ SerialAddDevice(
|
|||
NTSTATUS STDCALL
|
||||
SerialPnpStartDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PCM_RESOURCE_LIST ResourceList);
|
||||
IN PCM_RESOURCE_LIST ResourceList,
|
||||
IN PCM_RESOURCE_LIST ResourceListTranslated);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
SerialPnp(
|
||||
|
|
|
@ -96,7 +96,7 @@ NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe,
|
|||
|
||||
RemoveEntryList(&Waiter->Entry);
|
||||
Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
|
||||
Irp->IoStatus.Status = STATUS_PIPE_CONNECTED;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
|
|
@ -86,7 +86,7 @@ typedef struct _I8042_SETTINGS
|
|||
DWORD OverrideKeyboardType;
|
||||
DWORD OverrideKeyboardSubtype;
|
||||
DWORD MouseResendStallTime;
|
||||
DWORD MouseSynchIn100ns;
|
||||
DWORD MouseSynchIn100ns; /* done */
|
||||
DWORD MouseResolution; /* done */
|
||||
DWORD NumberOfButtons;
|
||||
DWORD EnableWheelDetection;
|
||||
|
@ -169,6 +169,7 @@ typedef struct _DEVICE_EXTENSION
|
|||
MOUSE_INPUT_DATA *MouseBuffer;
|
||||
ULONG MouseInBuffer;
|
||||
USHORT MouseButtonState;
|
||||
ULARGE_INTEGER MousePacketStartTime;
|
||||
|
||||
UCHAR MouseLogiBuffer[3];
|
||||
UCHAR MouseLogitechID;
|
||||
|
|
|
@ -113,7 +113,7 @@ BOOLEAN STDCALL I8042InterruptServiceKbd(struct _KINTERRUPT *Interrupt,
|
|||
} while (Iterations < DevExt->Settings.PollStatusIterations);
|
||||
|
||||
if (STATUS_SUCCESS != Status) {
|
||||
DPRINT1("Spurious I8042 interrupt\n");
|
||||
DPRINT("Spurious I8042 interrupt\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,39 @@ NTSTATUS STDCALL I8042SynchWritePortMouse(PVOID Context,
|
|||
WaitForAck);
|
||||
}
|
||||
|
||||
/* Test if packets are taking too long to come in. If they do, we
|
||||
* might have gotten out of sync and should just drop what we have.
|
||||
*
|
||||
* If we want to be totally right, we'd also have to keep a count of
|
||||
* errors, and totally reset the mouse after too much of them (can
|
||||
* happen if the user is using a KVM switch and an OS on another port
|
||||
* resets the mouse, or if the user hotplugs the mouse, or if we're just
|
||||
* generally unlucky). Also note the input parsing routine where we
|
||||
* drop invalid input packets.
|
||||
*/
|
||||
static VOID STDCALL I8042MouseInputTestTimeout(PDEVICE_EXTENSION DevExt)
|
||||
{
|
||||
ULARGE_INTEGER Now;
|
||||
|
||||
if (DevExt->MouseState == MouseExpectingACK ||
|
||||
DevExt->MouseState == MouseResetting)
|
||||
return;
|
||||
|
||||
Now.QuadPart = KeQueryInterruptTime();
|
||||
|
||||
if (DevExt->MouseState != MouseIdle) {
|
||||
/* Check if the last byte came too long ago */
|
||||
if (Now.QuadPart - DevExt->MousePacketStartTime.QuadPart >
|
||||
DevExt->Settings.MouseSynchIn100ns) {
|
||||
DPRINT1("Mouse input packet timeout\n");
|
||||
DevExt->MouseState = MouseIdle;
|
||||
}
|
||||
}
|
||||
|
||||
if (DevExt->MouseState == MouseIdle)
|
||||
DevExt->MousePacketStartTime.QuadPart = Now.QuadPart;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the customization hook. The Ret2 parameter is about wether
|
||||
* we should go on with the interrupt. The return value is what
|
||||
|
@ -301,7 +334,7 @@ BOOLEAN STDCALL I8042MouseResetIsr(PDEVICE_EXTENSION DevExt,
|
|||
case ExpectingFinalResolutionACK:
|
||||
I8042IsrWritePortMouse(DevExt,
|
||||
DevExt->Settings.MouseResolution & 0xff);
|
||||
DPRINT1("%x\n", DevExt->Settings.MouseResolution);
|
||||
DPRINT("%x\n", DevExt->Settings.MouseResolution);
|
||||
DevExt->MouseResetState = ExpectingFinalResolutionValueACK;
|
||||
return TRUE;
|
||||
case ExpectingFinalResolutionValueACK:
|
||||
|
@ -517,6 +550,8 @@ BOOLEAN STDCALL I8042InterruptServiceMouse(struct _KINTERRUPT *Interrupt,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
I8042MouseInputTestTimeout(DevExt);
|
||||
|
||||
if (I8042MouseResetIsr(DevExt, PortStatus, &Output)) {
|
||||
DPRINT("Handled by ResetIsr or hooked Isr\n");
|
||||
if (NoChange != DevExt->MouseTimeoutState) {
|
||||
|
|
|
@ -141,7 +141,7 @@ AfdGetSockOrPeerName( PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|||
}
|
||||
|
||||
/* MmUnlockPages( Mdl ); */
|
||||
IoFreeMdl( Mdl );
|
||||
/* IoFreeMdl( Mdl ); */
|
||||
} else {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <ndissys.h>
|
||||
|
||||
struct _ADAPTER_BINDING;
|
||||
|
||||
typedef struct _HARDWARE_ADDRESS {
|
||||
union {
|
||||
|
@ -77,9 +78,9 @@ typedef struct _LOGICAL_ADAPTER
|
|||
KDPC MiniportDpc; /* DPC routine for adapter */
|
||||
BOOLEAN MiniportBusy; /* A MiniportXxx routine is executing */
|
||||
ULONG WorkQueueLevel; /* Number of used work item buffers */
|
||||
NDIS_MINIPORT_WORK_ITEM WorkQueue[NDIS_MINIPORT_WORK_QUEUE_SIZE];
|
||||
PNDIS_MINIPORT_WORK_ITEM WorkQueueHead; /* Head of work queue */
|
||||
PNDIS_MINIPORT_WORK_ITEM WorkQueueTail; /* Tail of work queue */
|
||||
INTERNAL_NDIS_MINIPORT_WORK_ITEM WorkQueue[NDIS_MINIPORT_WORK_QUEUE_SIZE];
|
||||
PINTERNAL_NDIS_MINIPORT_WORK_ITEM WorkQueueHead; /* Head of work queue */
|
||||
PINTERNAL_NDIS_MINIPORT_WORK_ITEM WorkQueueTail; /* Tail of work queue */
|
||||
LIST_ENTRY ListEntry; /* Entry on global list */
|
||||
LIST_ENTRY MiniportListEntry; /* Entry on miniport driver list */
|
||||
LIST_ENTRY ProtocolListHead; /* List of bound protocols */
|
||||
|
@ -145,7 +146,7 @@ MiniQueryInformation(
|
|||
NDIS_STATUS
|
||||
FASTCALL
|
||||
MiniQueueWorkItem(
|
||||
PLOGICAL_ADAPTER Adapter,
|
||||
struct _ADAPTER_BINDING *AdapterBinding,
|
||||
NDIS_WORK_ITEM_TYPE WorkItemType,
|
||||
PVOID WorkItemContext);
|
||||
|
||||
|
@ -153,12 +154,13 @@ NDIS_STATUS
|
|||
FASTCALL
|
||||
MiniDequeueWorkItem(
|
||||
PLOGICAL_ADAPTER Adapter,
|
||||
struct _ADAPTER_BINDING **AdapterBinding,
|
||||
NDIS_WORK_ITEM_TYPE *WorkItemType,
|
||||
PVOID *WorkItemContext);
|
||||
|
||||
NDIS_STATUS
|
||||
MiniDoRequest(
|
||||
PLOGICAL_ADAPTER Adapter,
|
||||
struct _ADAPTER_BINDING *AdapterBinding,
|
||||
PNDIS_REQUEST NdisRequest);
|
||||
|
||||
BOOLEAN
|
||||
|
|
|
@ -27,6 +27,14 @@ typedef struct _ATM_ADDRESS *PATM_ADDRESS;
|
|||
#include <ddk/ntapi.h>
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
struct _ADAPTER_BINDING;
|
||||
|
||||
typedef struct _INTERNAL_NDIS_MINIPORT_WORK_ITEM {
|
||||
SINGLE_LIST_ENTRY Link;
|
||||
struct _ADAPTER_BINDING *AdapterBinding;
|
||||
NDIS_MINIPORT_WORK_ITEM RealWorkItem;
|
||||
} INTERNAL_NDIS_MINIPORT_WORK_ITEM, *PINTERNAL_NDIS_MINIPORT_WORK_ITEM;
|
||||
|
||||
#include "miniport.h"
|
||||
#include "protocol.h"
|
||||
|
||||
|
|
|
@ -327,6 +327,23 @@ MiniResetComplete(
|
|||
}
|
||||
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
MiniRequestComplete(
|
||||
IN PADAPTER_BINDING AdapterBinding,
|
||||
IN PNDIS_REQUEST Request,
|
||||
IN NDIS_STATUS Status)
|
||||
{
|
||||
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
|
||||
|
||||
if( AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler ) {
|
||||
(*AdapterBinding->ProtocolBinding->Chars.RequestCompleteHandler)(
|
||||
AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.ProtocolBindingContext,
|
||||
Request,
|
||||
Status);
|
||||
}
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
MiniSendComplete(
|
||||
IN NDIS_HANDLE MiniportAdapterHandle,
|
||||
|
@ -615,7 +632,7 @@ MiniQueryInformation(
|
|||
NDIS_STATUS
|
||||
FASTCALL
|
||||
MiniQueueWorkItem(
|
||||
PLOGICAL_ADAPTER Adapter,
|
||||
PADAPTER_BINDING AdapterBinding,
|
||||
NDIS_WORK_ITEM_TYPE WorkItemType,
|
||||
PVOID WorkItemContext)
|
||||
/*
|
||||
|
@ -630,49 +647,51 @@ MiniQueueWorkItem(
|
|||
* Status of operation
|
||||
*/
|
||||
{
|
||||
PNDIS_MINIPORT_WORK_ITEM Item;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
ASSERT(Adapter);
|
||||
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
|
||||
PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item;
|
||||
PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
ASSERT(Adapter);
|
||||
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
|
||||
|
||||
#if 0
|
||||
if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1)
|
||||
if (Adapter->WorkQueueLevel < NDIS_MINIPORT_WORK_QUEUE_SIZE - 1)
|
||||
{
|
||||
Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
|
||||
Adapter->WorkQueueLevel++;
|
||||
Item = &Adapter->WorkQueue[Adapter->WorkQueueLevel];
|
||||
Adapter->WorkQueueLevel++;
|
||||
}
|
||||
else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Item = ExAllocatePool(NonPagedPool, sizeof(NDIS_MINIPORT_WORK_ITEM));
|
||||
if (Item == NULL)
|
||||
Item = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_NDIS_MINIPORT_WORK_ITEM));
|
||||
if (Item == NULL)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return NDIS_STATUS_RESOURCES;
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return NDIS_STATUS_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
Item->WorkItemType = WorkItemType;
|
||||
Item->WorkItemContext = WorkItemContext;
|
||||
|
||||
/* safe due to adapter lock held */
|
||||
Item->Link.Next = NULL;
|
||||
if (!Adapter->WorkQueueHead)
|
||||
|
||||
Item->AdapterBinding = AdapterBinding;
|
||||
Item->RealWorkItem.WorkItemType = WorkItemType;
|
||||
Item->RealWorkItem.WorkItemContext = WorkItemContext;
|
||||
|
||||
/* safe due to adapter lock held */
|
||||
Item->Link.Next = NULL;
|
||||
if (!Adapter->WorkQueueHead)
|
||||
{
|
||||
Adapter->WorkQueueHead = Item;
|
||||
Adapter->WorkQueueTail = Item;
|
||||
Adapter->WorkQueueHead = Item;
|
||||
Adapter->WorkQueueTail = Item;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
|
||||
Adapter->WorkQueueTail = Item;
|
||||
Adapter->WorkQueueTail->Link.Next = (PSINGLE_LIST_ENTRY)Item;
|
||||
Adapter->WorkQueueTail = Item;
|
||||
}
|
||||
|
||||
KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
|
||||
KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -680,12 +699,14 @@ NDIS_STATUS
|
|||
FASTCALL
|
||||
MiniDequeueWorkItem(
|
||||
PLOGICAL_ADAPTER Adapter,
|
||||
PADAPTER_BINDING *AdapterBinding,
|
||||
NDIS_WORK_ITEM_TYPE *WorkItemType,
|
||||
PVOID *WorkItemContext)
|
||||
/*
|
||||
* FUNCTION: Dequeues a work item from the work queue of a logical adapter
|
||||
* ARGUMENTS:
|
||||
* Adapter = Pointer to the logical adapter object to dequeue work item from
|
||||
* AdapterBinding = Address of buffer for adapter binding for this request
|
||||
* WorkItemType = Address of buffer for work item type
|
||||
* WorkItemContext = Address of buffer for pointer to context information
|
||||
* NOTES:
|
||||
|
@ -694,52 +715,55 @@ MiniDequeueWorkItem(
|
|||
* Status of operation
|
||||
*/
|
||||
{
|
||||
PNDIS_MINIPORT_WORK_ITEM Item;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
Item = Adapter->WorkQueueHead;
|
||||
|
||||
if (Item)
|
||||
PINTERNAL_NDIS_MINIPORT_WORK_ITEM Item;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
Item = Adapter->WorkQueueHead;
|
||||
|
||||
if (Item)
|
||||
{
|
||||
/* safe due to adapter lock held */
|
||||
Adapter->WorkQueueHead = (PNDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
|
||||
|
||||
if (Item == Adapter->WorkQueueTail)
|
||||
Adapter->WorkQueueTail = NULL;
|
||||
|
||||
*WorkItemType = Item->WorkItemType;
|
||||
*WorkItemContext = Item->WorkItemContext;
|
||||
|
||||
ExFreePool(Item);
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
/* safe due to adapter lock held */
|
||||
Adapter->WorkQueueHead = (PINTERNAL_NDIS_MINIPORT_WORK_ITEM)Item->Link.Next;
|
||||
|
||||
if (Item == Adapter->WorkQueueTail)
|
||||
Adapter->WorkQueueTail = NULL;
|
||||
|
||||
*AdapterBinding = Item->AdapterBinding;
|
||||
*WorkItemType = Item->RealWorkItem.WorkItemType;
|
||||
*WorkItemContext = Item->RealWorkItem.WorkItemContext;
|
||||
|
||||
ExFreePool(Item);
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return NDIS_STATUS_FAILURE;
|
||||
|
||||
return NDIS_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
NDIS_STATUS
|
||||
MiniDoRequest(
|
||||
PLOGICAL_ADAPTER Adapter,
|
||||
PADAPTER_BINDING AdapterBinding,
|
||||
PNDIS_REQUEST NdisRequest)
|
||||
/*
|
||||
* FUNCTION: Sends a request to a miniport
|
||||
* ARGUMENTS:
|
||||
* Adapter = Pointer to logical adapter object
|
||||
* NdisRequest = Pointer to NDIS request structure describing request
|
||||
* AdapterBinding = Pointer to binding used in the request
|
||||
* NdisRequest = Pointer to NDIS request structure describing request
|
||||
* RETURNS:
|
||||
* Status of operation
|
||||
*/
|
||||
{
|
||||
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
|
||||
PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter;
|
||||
|
||||
Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
|
||||
|
||||
switch (NdisRequest->RequestType)
|
||||
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
|
||||
|
||||
Adapter->NdisMiniportBlock.MediaRequest = NdisRequest;
|
||||
|
||||
switch (NdisRequest->RequestType)
|
||||
{
|
||||
case NdisRequestQueryInformation:
|
||||
case NdisRequestQueryInformation:
|
||||
return (*Adapter->Miniport->Chars.QueryInformationHandler)(
|
||||
Adapter->NdisMiniportBlock.MiniportAdapterContext,
|
||||
NdisRequest->DATA.QUERY_INFORMATION.Oid,
|
||||
|
@ -748,8 +772,8 @@ MiniDoRequest(
|
|||
(PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesWritten,
|
||||
(PULONG)&NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded);
|
||||
break;
|
||||
|
||||
case NdisRequestSetInformation:
|
||||
|
||||
case NdisRequestSetInformation:
|
||||
return (*Adapter->Miniport->Chars.SetInformationHandler)(
|
||||
Adapter->NdisMiniportBlock.MiniportAdapterContext,
|
||||
NdisRequest->DATA.SET_INFORMATION.Oid,
|
||||
|
@ -758,8 +782,8 @@ MiniDoRequest(
|
|||
(PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesRead,
|
||||
(PULONG)&NdisRequest->DATA.SET_INFORMATION.BytesNeeded);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
default:
|
||||
return NDIS_STATUS_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -800,11 +824,14 @@ VOID STDCALL MiniportDpc(
|
|||
NDIS_STATUS NdisStatus;
|
||||
PVOID WorkItemContext;
|
||||
NDIS_WORK_ITEM_TYPE WorkItemType;
|
||||
PADAPTER_BINDING AdapterBinding;
|
||||
PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
|
||||
|
||||
NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
|
||||
|
||||
NdisStatus = MiniDequeueWorkItem(Adapter, &WorkItemType, &WorkItemContext);
|
||||
NdisStatus =
|
||||
MiniDequeueWorkItem
|
||||
(Adapter, &AdapterBinding, &WorkItemType, &WorkItemContext);
|
||||
|
||||
if (NdisStatus == NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
|
@ -873,7 +900,7 @@ VOID STDCALL MiniportDpc(
|
|||
break;
|
||||
|
||||
case NdisWorkItemRequest:
|
||||
NdisStatus = MiniDoRequest(Adapter, (PNDIS_REQUEST)WorkItemContext);
|
||||
NdisStatus = MiniDoRequest(AdapterBinding, (PNDIS_REQUEST)WorkItemContext);
|
||||
|
||||
if (NdisStatus == NDIS_STATUS_PENDING)
|
||||
break;
|
||||
|
@ -882,10 +909,12 @@ VOID STDCALL MiniportDpc(
|
|||
{
|
||||
case NdisRequestQueryInformation:
|
||||
NdisMQueryInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
|
||||
MiniRequestComplete( AdapterBinding, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
|
||||
break;
|
||||
|
||||
case NdisRequestSetInformation:
|
||||
NdisMSetInformationComplete((NDIS_HANDLE)Adapter, NdisStatus);
|
||||
MiniRequestComplete( AdapterBinding, (PNDIS_REQUEST)WorkItemContext, NdisStatus );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -158,7 +158,7 @@ ProRequest(
|
|||
/* MiniQueueWorkItem must be called at IRQL >= DISPATCH_LEVEL */
|
||||
if (QueueWorkItem)
|
||||
{
|
||||
MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest);
|
||||
MiniQueueWorkItem(AdapterBinding, NdisWorkItemRequest, (PVOID)NdisRequest);
|
||||
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
|
||||
return NDIS_STATUS_PENDING;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ ProRequest(
|
|||
/* TODO (?): move the irql raise into MiniDoRequest */
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
{
|
||||
NdisStatus = MiniDoRequest(Adapter, NdisRequest);
|
||||
NdisStatus = MiniDoRequest(AdapterBinding, NdisRequest);
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
|
||||
KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
|
||||
|
@ -278,7 +278,7 @@ ProSend(
|
|||
|
||||
if (QueueWorkItem)
|
||||
{
|
||||
MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, (PVOID)Packet);
|
||||
MiniQueueWorkItem(AdapterBinding, NdisWorkItemSendLoopback, (PVOID)Packet);
|
||||
return NDIS_STATUS_PENDING;
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ ProSend(
|
|||
/* This is a normal send packet, not a loopback packet. */
|
||||
if (QueueWorkItem)
|
||||
{
|
||||
MiniQueueWorkItem(Adapter, NdisWorkItemSend, (PVOID)Packet);
|
||||
MiniQueueWorkItem(AdapterBinding, NdisWorkItemSend, (PVOID)Packet);
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Queued a work item and returning\n"));
|
||||
return NDIS_STATUS_PENDING;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
#include "precomp.h"
|
||||
|
||||
//#define NDEBUG
|
||||
#define NDEBUG
|
||||
|
||||
#ifndef NDEBUG
|
||||
DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER);
|
||||
|
|
|
@ -391,17 +391,10 @@ static VOID
|
|||
CdromClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN ULONG DeviceNumber)
|
||||
{
|
||||
WCHAR NameBuffer[MAX_PATH];
|
||||
UNICODE_STRING Name;
|
||||
|
||||
swprintf (NameBuffer,
|
||||
L"\\Device\\MediaChangeEvent%lu",
|
||||
DeviceNumber);
|
||||
RtlInitUnicodeString (&Name,
|
||||
NameBuffer);
|
||||
|
||||
DeviceExtension->MediaChangeEvent =
|
||||
IoCreateSynchronizationEvent (&Name,
|
||||
IoCreateSynchronizationEvent (NULL,
|
||||
&DeviceExtension->MediaChangeEventHandle);
|
||||
|
||||
KeClearEvent (DeviceExtension->MediaChangeEvent);
|
||||
|
|
|
@ -315,17 +315,8 @@ static VOID
|
|||
DiskClassCreateMediaChangeEvent(IN PDEVICE_EXTENSION DeviceExtension,
|
||||
IN ULONG DeviceNumber)
|
||||
{
|
||||
WCHAR NameBuffer[MAX_PATH];
|
||||
UNICODE_STRING Name;
|
||||
|
||||
swprintf (NameBuffer,
|
||||
L"\\Device\\MediaChangeEvent%lu",
|
||||
DeviceNumber);
|
||||
RtlInitUnicodeString (&Name,
|
||||
NameBuffer);
|
||||
|
||||
DeviceExtension->MediaChangeEvent =
|
||||
IoCreateSynchronizationEvent (&Name,
|
||||
IoCreateSynchronizationEvent (NULL,
|
||||
&DeviceExtension->MediaChangeEventHandle);
|
||||
|
||||
KeClearEvent (DeviceExtension->MediaChangeEvent);
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
#
|
||||
# ReactOS USB Drivers
|
||||
#
|
||||
|
||||
PATH_TO_TOP = ../..
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
DRIVERS = usbport miniport/usbuhci miniport/usbehci miniport/usbohci usbhub usbd
|
||||
|
||||
all: $(DRIVERS)
|
||||
|
||||
depends:
|
||||
|
||||
implib: $(DRIVERS:%=%_implib)
|
||||
|
||||
clean: $(DRIVERS:%=%_clean)
|
||||
|
||||
install: $(DRIVERS:%=%_install)
|
||||
|
||||
bootcd: $(DRIVERS:%=%_bootcd)
|
||||
|
||||
.PHONY: all depends implib clean install bootcd
|
||||
|
||||
|
||||
#
|
||||
# USB DRIVERS
|
||||
#
|
||||
$(DRIVERS): %:
|
||||
$(MAKE) -C $*
|
||||
|
||||
$(DRIVERS:%=%_implib): %_implib:
|
||||
$(MAKE) -C $* implib
|
||||
|
||||
$(DRIVERS:%=%_clean): %_clean:
|
||||
$(MAKE) -C $* clean
|
||||
|
||||
$(DRIVERS:%=%_install): %_install:
|
||||
$(MAKE) -C $* install
|
||||
|
||||
$(DRIVERS:%=%_bootcd): %_bootcd:
|
||||
$(MAKE) -C $* bootcd
|
||||
|
||||
.PHONY: $(DRIVERS) $(DRIVERS:%=%_implib) $(DRIVERS:%=%_clean) $(DRIVERS:%=%_install) $(DRIVERS:%=%_bootcd)
|
||||
|
||||
|
||||
etags:
|
||||
find . -name "*.[ch]" -print | etags --language=c -
|
||||
|
||||
# EOF
|
||||
#
|
||||
# ReactOS USB Drivers
|
||||
#
|
||||
|
||||
PATH_TO_TOP = ../..
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
DRIVERS = usbport miniport/usbuhci miniport/usbehci miniport/usbohci usbhub usbd cromwell
|
||||
|
||||
all: $(DRIVERS)
|
||||
|
||||
depends:
|
||||
|
||||
implib: $(DRIVERS:%=%_implib)
|
||||
|
||||
clean: $(DRIVERS:%=%_clean)
|
||||
|
||||
install: $(DRIVERS:%=%_install)
|
||||
|
||||
bootcd: $(DRIVERS:%=%_bootcd)
|
||||
|
||||
.PHONY: all depends implib clean install bootcd
|
||||
|
||||
|
||||
#
|
||||
# USB DRIVERS
|
||||
#
|
||||
$(DRIVERS): %:
|
||||
$(MAKE) -C $*
|
||||
|
||||
$(DRIVERS:%=%_implib): %_implib:
|
||||
$(MAKE) -C $* implib
|
||||
|
||||
$(DRIVERS:%=%_clean): %_clean:
|
||||
$(MAKE) -C $* clean
|
||||
|
||||
$(DRIVERS:%=%_install): %_install:
|
||||
$(MAKE) -C $* install
|
||||
|
||||
$(DRIVERS:%=%_bootcd): %_bootcd:
|
||||
$(MAKE) -C $* bootcd
|
||||
|
||||
.PHONY: $(DRIVERS) $(DRIVERS:%=%_implib) $(DRIVERS:%=%_clean) $(DRIVERS:%=%_install) $(DRIVERS:%=%_bootcd)
|
||||
|
||||
|
||||
etags:
|
||||
find . -name "*.[ch]" -print | etags --language=c -
|
||||
|
||||
# EOF
|
||||
|
|
|
@ -1,50 +1,50 @@
|
|||
#
|
||||
# ReactOS USB-Cromwell Drivers
|
||||
#
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
DRIVERS = core host uhci
|
||||
|
||||
all: $(DRIVERS)
|
||||
|
||||
depends:
|
||||
|
||||
implib: $(DRIVERS:%=%_implib)
|
||||
|
||||
clean: $(DRIVERS:%=%_clean)
|
||||
|
||||
install: $(DRIVERS:%=%_install)
|
||||
|
||||
bootcd: $(DRIVERS:%=%_bootcd)
|
||||
|
||||
.PHONY: all depends implib clean install bootcd
|
||||
|
||||
|
||||
#
|
||||
# USB DRIVERS
|
||||
#
|
||||
$(DRIVERS): %:
|
||||
$(MAKE) -C $*
|
||||
|
||||
$(DRIVERS:%=%_implib): %_implib:
|
||||
$(MAKE) -C $* implib
|
||||
|
||||
$(DRIVERS:%=%_clean): %_clean:
|
||||
$(MAKE) -C $* clean
|
||||
|
||||
$(DRIVERS:%=%_install): %_install:
|
||||
$(MAKE) -C $* install
|
||||
|
||||
$(DRIVERS:%=%_bootcd): %_bootcd:
|
||||
$(MAKE) -C $* bootcd
|
||||
|
||||
.PHONY: $(DRIVERS) $(DRIVERS:%=%_implib) $(DRIVERS:%=%_clean) $(DRIVERS:%=%_install) $(DRIVERS:%=%_bootcd)
|
||||
|
||||
|
||||
etags:
|
||||
find . -name "*.[ch]" -print | etags --language=c -
|
||||
|
||||
# EOF
|
||||
#
|
||||
# ReactOS USB-Cromwell Drivers
|
||||
#
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
DRIVERS = core host uhci
|
||||
|
||||
all: $(DRIVERS)
|
||||
|
||||
depends:
|
||||
|
||||
implib: $(DRIVERS:%=%_implib)
|
||||
|
||||
clean: $(DRIVERS:%=%_clean)
|
||||
|
||||
install: $(DRIVERS:%=%_install)
|
||||
|
||||
bootcd: $(DRIVERS:%=%_bootcd)
|
||||
|
||||
.PHONY: all depends implib clean install bootcd
|
||||
|
||||
|
||||
#
|
||||
# USB DRIVERS
|
||||
#
|
||||
$(DRIVERS): %:
|
||||
$(MAKE) -C $*
|
||||
|
||||
$(DRIVERS:%=%_implib): %_implib:
|
||||
$(MAKE) -C $* implib
|
||||
|
||||
$(DRIVERS:%=%_clean): %_clean:
|
||||
$(MAKE) -C $* clean
|
||||
|
||||
$(DRIVERS:%=%_install): %_install:
|
||||
$(MAKE) -C $* install
|
||||
|
||||
$(DRIVERS:%=%_bootcd): %_bootcd:
|
||||
$(MAKE) -C $* bootcd
|
||||
|
||||
.PHONY: $(DRIVERS) $(DRIVERS:%=%_implib) $(DRIVERS:%=%_clean) $(DRIVERS:%=%_install) $(DRIVERS:%=%_bootcd)
|
||||
|
||||
|
||||
etags:
|
||||
find . -name "*.[ch]" -print | etags --language=c -
|
||||
|
||||
# EOF
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
/*
|
||||
* buffer_simple.c -- replacement for usb/core/buffer.c
|
||||
*
|
||||
* (c) Georg Acher, georg@acher.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
#define __KERNEL__
|
||||
#define CONFIG_PCI
|
||||
#include "hcd.h"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int hcd_buffer_create (struct usb_hcd *hcd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void hcd_buffer_destroy (struct usb_hcd *hcd)
|
||||
{
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void *hcd_buffer_alloc (
|
||||
struct usb_bus *bus,
|
||||
size_t size,
|
||||
int mem_flags,
|
||||
dma_addr_t *dma
|
||||
)
|
||||
{
|
||||
return kmalloc(size,0);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void hcd_buffer_free (
|
||||
struct usb_bus *bus,
|
||||
size_t size,
|
||||
void *addr,
|
||||
dma_addr_t dma
|
||||
)
|
||||
{
|
||||
kfree(addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* buffer_simple.c -- replacement for usb/core/buffer.c
|
||||
*
|
||||
* (c) Georg Acher, georg@acher.org
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
#define __KERNEL__
|
||||
#define CONFIG_PCI
|
||||
#include "hcd.h"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int hcd_buffer_create (struct usb_hcd *hcd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void hcd_buffer_destroy (struct usb_hcd *hcd)
|
||||
{
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void *hcd_buffer_alloc (
|
||||
struct usb_bus *bus,
|
||||
size_t size,
|
||||
int mem_flags,
|
||||
dma_addr_t *dma
|
||||
)
|
||||
{
|
||||
return kmalloc(size,0);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void hcd_buffer_free (
|
||||
struct usb_bus *bus,
|
||||
size_t size,
|
||||
void *addr,
|
||||
dma_addr_t dma
|
||||
)
|
||||
{
|
||||
kfree(addr);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,369 +1,370 @@
|
|||
/*
|
||||
* (C) Copyright David Brownell 2000-2002
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include <linux/config.h>
|
||||
|
||||
#ifdef CONFIG_USB_DEBUG
|
||||
#define DEBUG
|
||||
#else
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/usb.h>
|
||||
#include "hcd.h"
|
||||
#else
|
||||
#define DEBUG
|
||||
#include "../usb_wrapper.h"
|
||||
#include "hcd.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* PCI-based HCs are normal, but custom bus glue should be ok */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* configure so an HC device and id are always provided */
|
||||
/* always called with process context; sleeping is OK */
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_probe - initialize PCI-based HCDs
|
||||
* @dev: USB Host Controller being probed
|
||||
* @id: pci hotplug id connecting controller to HCD framework
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* Allocates basic PCI resources for this USB host controller, and
|
||||
* then invokes the start() method for the HCD associated with it
|
||||
* through the hotplug entry's driver_data.
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as probe().
|
||||
*/
|
||||
int STDCALL usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
struct hc_driver *driver;
|
||||
PHYSICAL_ADDRESS resource;
|
||||
unsigned long len;
|
||||
void *base;
|
||||
struct usb_hcd *hcd;
|
||||
int retval, region;
|
||||
char buf [8];
|
||||
//char *bufp = buf;
|
||||
|
||||
printk("usbcore: usb_hcd_pci_probe() called\n");
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
if (!id || !(driver = (struct hc_driver *) id->driver_data))
|
||||
return -EINVAL;
|
||||
|
||||
if (pci_enable_device (dev) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
if (!dev->irq) {
|
||||
err ("Found HC with no IRQ. Check BIOS/PCI %s setup!",
|
||||
dev->slot_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (driver->flags & HCD_MEMORY) { // EHCI, OHCI
|
||||
region = 0;
|
||||
resource = pci_resource_start (dev, 0);
|
||||
len = pci_resource_len (dev, 0);
|
||||
if (!request_mem_region (resource, len, driver->description)) {
|
||||
dbg ("controller already in use");
|
||||
return -EBUSY;
|
||||
}
|
||||
base = ioremap_nocache (resource, len);
|
||||
if (base == NULL) {
|
||||
dbg ("error mapping memory");
|
||||
retval = -EFAULT;
|
||||
clean_1:
|
||||
release_mem_region (resource, len);
|
||||
err ("init %s fail, %d", dev->slot_name, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
} else { // UHCI
|
||||
//resource = 0;
|
||||
len = 0;
|
||||
for (region = 0; region < PCI_ROM_RESOURCE; region++) {
|
||||
if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
|
||||
continue;
|
||||
|
||||
resource = pci_resource_start (dev, region);
|
||||
len = pci_resource_len (dev, region);
|
||||
if (request_region (resource, len,
|
||||
driver->description))
|
||||
break;
|
||||
}
|
||||
if (region == PCI_ROM_RESOURCE) {
|
||||
dbg ("no i/o regions available");
|
||||
return -EBUSY;
|
||||
}
|
||||
base = NULL; //(void *) resource; // this isn't possible
|
||||
}
|
||||
|
||||
// driver->start(), later on, will transfer device from
|
||||
// control by SMM/BIOS to control by Linux (if needed)
|
||||
|
||||
pci_set_master (dev);
|
||||
|
||||
hcd = driver->hcd_alloc ();
|
||||
if (hcd == NULL){
|
||||
dbg ("hcd alloc fail");
|
||||
retval = -ENOMEM;
|
||||
clean_2:
|
||||
if (driver->flags & HCD_MEMORY) {
|
||||
iounmap (base);
|
||||
goto clean_1;
|
||||
} else {
|
||||
release_region (resource, len);
|
||||
err ("init %s fail, %d", dev->slot_name, retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
pci_set_drvdata (dev, hcd);
|
||||
hcd->driver = driver;
|
||||
hcd->description = driver->description;
|
||||
hcd->pdev = dev;
|
||||
hcd->self.bus_name = dev->slot_name;
|
||||
hcd->product_desc = dev->dev.name;
|
||||
hcd->self.controller = &dev->dev;
|
||||
hcd->controller = hcd->self.controller;
|
||||
|
||||
if ((retval = hcd_buffer_create (hcd)) != 0) {
|
||||
clean_3:
|
||||
driver->hcd_free (hcd);
|
||||
goto clean_2;
|
||||
}
|
||||
|
||||
dev_info (hcd->controller, "%s\n", hcd->product_desc);
|
||||
|
||||
#ifndef __sparc__
|
||||
sprintf (buf, "%d", dev->irq);
|
||||
#else
|
||||
bufp = __irq_itoa(dev->irq);
|
||||
#endif
|
||||
if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd)
|
||||
!= 0) {
|
||||
dev_err (hcd->controller,
|
||||
"request interrupt %s failed\n", buf);
|
||||
retval = -EBUSY;
|
||||
goto clean_3;
|
||||
}
|
||||
hcd->irq = dev->irq;
|
||||
|
||||
hcd->regs = base;
|
||||
hcd->region = region;
|
||||
dev_info (hcd->controller, "irq %s, %s %p\n", buf,
|
||||
(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
|
||||
base);
|
||||
|
||||
usb_bus_init (&hcd->self);
|
||||
hcd->self.op = &usb_hcd_operations;
|
||||
hcd->self.hcpriv = (void *) hcd;
|
||||
|
||||
INIT_LIST_HEAD (&hcd->dev_list);
|
||||
|
||||
usb_register_bus (&hcd->self);
|
||||
|
||||
if ((retval = driver->start (hcd)) < 0)
|
||||
usb_hcd_pci_remove (dev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_probe);
|
||||
|
||||
|
||||
/* may be called without controller electrically present */
|
||||
/* may be called with controller, bus, and devices active */
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
|
||||
* @dev: USB Host Controller being removed
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* Reverses the effect of usb_hcd_pci_probe(), first invoking
|
||||
* the HCD's stop() method. It is always called from a thread
|
||||
* context, normally "rmmod", "apmd", or something similar.
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as remove().
|
||||
*/
|
||||
void STDCALL usb_hcd_pci_remove (struct pci_dev *dev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
struct usb_device *hub;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
if (!hcd)
|
||||
return;
|
||||
dev_info (hcd->controller, "remove, state %x\n", hcd->state);
|
||||
|
||||
if (in_interrupt ())
|
||||
BUG ();
|
||||
|
||||
hub = hcd->self.root_hub;
|
||||
hcd->state = USB_STATE_QUIESCING;
|
||||
|
||||
dev_dbg (hcd->controller, "roothub graceful disconnect\n");
|
||||
usb_disconnect (&hub);
|
||||
|
||||
hcd->driver->stop (hcd);
|
||||
hcd_buffer_destroy (hcd);
|
||||
hcd->state = USB_STATE_HALT;
|
||||
pci_set_drvdata (dev, 0);
|
||||
|
||||
free_irq (hcd->irq, hcd);
|
||||
if (hcd->driver->flags & HCD_MEMORY) {
|
||||
iounmap (hcd->regs);
|
||||
release_mem_region (pci_resource_start (dev, 0),
|
||||
pci_resource_len (dev, 0));
|
||||
} else {
|
||||
release_region (pci_resource_start (dev, hcd->region),
|
||||
pci_resource_len (dev, hcd->region));
|
||||
}
|
||||
|
||||
usb_deregister_bus (&hcd->self);
|
||||
if (atomic_read (&hcd->self.refcnt) != 1) {
|
||||
dev_warn (hcd->controller,
|
||||
"dangling refs (%d) to bus %d!\n",
|
||||
atomic_read (&hcd->self.refcnt) - 1,
|
||||
hcd->self.busnum);
|
||||
}
|
||||
hcd->driver->hcd_free (hcd);
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_remove);
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/*
|
||||
* Some "sleep" power levels imply updating struct usb_driver
|
||||
* to include a callback asking hcds to do their bit by checking
|
||||
* if all the drivers can suspend. Gets involved with remote wakeup.
|
||||
*
|
||||
* If there are pending urbs, then HCs will need to access memory,
|
||||
* causing extra power drain. New sleep()/wakeup() PM calls might
|
||||
* be needed, beyond PCI suspend()/resume(). The root hub timer
|
||||
* still be accessing memory though ...
|
||||
*
|
||||
* FIXME: USB should have some power budgeting support working with
|
||||
* all kinds of hubs.
|
||||
*
|
||||
* FIXME: This assumes only D0->D3 suspend and D3->D0 resume.
|
||||
* D1 and D2 states should do something, yes?
|
||||
*
|
||||
* FIXME: Should provide generic enable_wake(), calling pci_enable_wake()
|
||||
* for all supported states, so that USB remote wakeup can work for any
|
||||
* devices that support it (and are connected via powered hubs).
|
||||
*
|
||||
* FIXME: resume doesn't seem to work right any more...
|
||||
*/
|
||||
|
||||
|
||||
// 2.4 kernels have issued concurrent resumes (w/APM)
|
||||
// we defend against that error; PCI doesn't yet.
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
|
||||
* @dev: USB Host Controller being suspended
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as suspend().
|
||||
*/
|
||||
int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
int retval;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
dev_info (hcd->controller, "suspend to state %d\n", state);
|
||||
|
||||
pci_save_state (dev, hcd->pci_state);
|
||||
|
||||
// FIXME for all connected devices, leaf-to-root:
|
||||
// driver->suspend()
|
||||
// proposed "new 2.5 driver model" will automate that
|
||||
|
||||
/* driver may want to disable DMA etc */
|
||||
retval = hcd->driver->suspend (hcd, state);
|
||||
hcd->state = USB_STATE_SUSPENDED;
|
||||
|
||||
pci_set_power_state (dev, state);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_suspend);
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_resume - power management resume of a PCI-based HCD
|
||||
* @dev: USB Host Controller being resumed
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as resume().
|
||||
*/
|
||||
int usb_hcd_pci_resume (struct pci_dev *dev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
int retval;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
dev_info (hcd->controller, "resume\n");
|
||||
|
||||
/* guard against multiple resumes (APM bug?) */
|
||||
atomic_inc (&hcd->resume_count);
|
||||
if (atomic_read (&hcd->resume_count) != 1) {
|
||||
dev_err (hcd->controller, "concurrent PCI resumes\n");
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
retval = -EBUSY;
|
||||
if (hcd->state != USB_STATE_SUSPENDED) {
|
||||
dev_dbg (hcd->controller, "can't resume, not suspended!\n");
|
||||
goto done;
|
||||
}
|
||||
hcd->state = USB_STATE_RESUMING;
|
||||
|
||||
pci_set_power_state (dev, 0);
|
||||
pci_restore_state (dev, hcd->pci_state);
|
||||
|
||||
retval = hcd->driver->resume (hcd);
|
||||
if (!HCD_IS_RUNNING (hcd->state)) {
|
||||
dev_dbg (hcd->controller, "resume fail, retval %d\n", retval);
|
||||
usb_hc_died (hcd);
|
||||
// FIXME: recover, reset etc.
|
||||
} else {
|
||||
// FIXME for all connected devices, root-to-leaf:
|
||||
// driver->resume ();
|
||||
// proposed "new 2.5 driver model" will automate that
|
||||
}
|
||||
|
||||
done:
|
||||
atomic_dec (&hcd->resume_count);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_resume);
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
/*
|
||||
* (C) Copyright David Brownell 2000-2002
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include <linux/config.h>
|
||||
|
||||
#ifdef CONFIG_USB_DEBUG
|
||||
#define DEBUG
|
||||
#else
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/usb.h>
|
||||
#include "hcd.h"
|
||||
#else
|
||||
#define DEBUG
|
||||
#include "../usb_wrapper.h"
|
||||
#include "hcd.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* PCI-based HCs are normal, but custom bus glue should be ok */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* configure so an HC device and id are always provided */
|
||||
/* always called with process context; sleeping is OK */
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_probe - initialize PCI-based HCDs
|
||||
* @dev: USB Host Controller being probed
|
||||
* @id: pci hotplug id connecting controller to HCD framework
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* Allocates basic PCI resources for this USB host controller, and
|
||||
* then invokes the start() method for the HCD associated with it
|
||||
* through the hotplug entry's driver_data.
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as probe().
|
||||
*/
|
||||
int STDCALL
|
||||
usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
struct hc_driver *driver;
|
||||
PHYSICAL_ADDRESS resource;
|
||||
unsigned long len;
|
||||
void *base;
|
||||
struct usb_hcd *hcd;
|
||||
int retval, region;
|
||||
char buf [8];
|
||||
//char *bufp = buf;
|
||||
|
||||
printk("usbcore: usb_hcd_pci_probe() called\n");
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
if (!id || !(driver = (struct hc_driver *) id->driver_data))
|
||||
return -EINVAL;
|
||||
|
||||
if (pci_enable_device (dev) < 0)
|
||||
return -ENODEV;
|
||||
|
||||
if (!dev->irq) {
|
||||
err ("Found HC with no IRQ. Check BIOS/PCI %s setup!",
|
||||
dev->slot_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (driver->flags & HCD_MEMORY) { // EHCI, OHCI
|
||||
region = 0;
|
||||
resource = pci_resource_start (dev, 0);
|
||||
len = pci_resource_len (dev, 0);
|
||||
if (!request_mem_region (resource, len, driver->description)) {
|
||||
dbg ("controller already in use");
|
||||
return -EBUSY;
|
||||
}
|
||||
base = ioremap_nocache (resource, len);
|
||||
if (base == NULL) {
|
||||
dbg ("error mapping memory");
|
||||
retval = -EFAULT;
|
||||
clean_1:
|
||||
release_mem_region (resource, len);
|
||||
err ("init %s fail, %d", dev->slot_name, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
} else { // UHCI
|
||||
//resource = 0;
|
||||
len = 0;
|
||||
for (region = 0; region < PCI_ROM_RESOURCE; region++) {
|
||||
if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
|
||||
continue;
|
||||
|
||||
resource = pci_resource_start (dev, region);
|
||||
len = pci_resource_len (dev, region);
|
||||
if (request_region (resource, len,
|
||||
driver->description))
|
||||
break;
|
||||
}
|
||||
if (region == PCI_ROM_RESOURCE) {
|
||||
dbg ("no i/o regions available");
|
||||
return -EBUSY;
|
||||
}
|
||||
base = (void *) (ULONG_PTR)resource.u.LowPart;
|
||||
}
|
||||
|
||||
// driver->start(), later on, will transfer device from
|
||||
// control by SMM/BIOS to control by Linux (if needed)
|
||||
|
||||
pci_set_master (dev);
|
||||
|
||||
hcd = driver->hcd_alloc ();
|
||||
if (hcd == NULL){
|
||||
dbg ("hcd alloc fail");
|
||||
retval = -ENOMEM;
|
||||
clean_2:
|
||||
if (driver->flags & HCD_MEMORY) {
|
||||
iounmap (base);
|
||||
goto clean_1;
|
||||
} else {
|
||||
release_region (resource, len);
|
||||
err ("init %s fail, %d", dev->slot_name, retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
pci_set_drvdata (dev, hcd);
|
||||
hcd->driver = driver;
|
||||
hcd->description = driver->description;
|
||||
hcd->pdev = dev;
|
||||
hcd->self.bus_name = dev->slot_name;
|
||||
hcd->product_desc = dev->dev.name;
|
||||
hcd->self.controller = &dev->dev;
|
||||
hcd->controller = hcd->self.controller;
|
||||
|
||||
if ((retval = hcd_buffer_create (hcd)) != 0) {
|
||||
clean_3:
|
||||
driver->hcd_free (hcd);
|
||||
goto clean_2;
|
||||
}
|
||||
|
||||
dev_info (hcd->controller, "%s\n", hcd->product_desc);
|
||||
|
||||
#ifndef __sparc__
|
||||
sprintf (buf, "%d", dev->irq);
|
||||
#else
|
||||
bufp = __irq_itoa(dev->irq);
|
||||
#endif
|
||||
if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd)
|
||||
!= 0) {
|
||||
dev_err (hcd->controller,
|
||||
"request interrupt %s failed\n", buf);
|
||||
retval = -EBUSY;
|
||||
goto clean_3;
|
||||
}
|
||||
hcd->irq = dev->irq;
|
||||
|
||||
hcd->regs = base;
|
||||
hcd->region = region;
|
||||
dev_info (hcd->controller, "irq %s, %s %p\n", buf,
|
||||
(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
|
||||
base);
|
||||
|
||||
usb_bus_init (&hcd->self);
|
||||
hcd->self.op = &usb_hcd_operations;
|
||||
hcd->self.hcpriv = (void *) hcd;
|
||||
|
||||
INIT_LIST_HEAD (&hcd->dev_list);
|
||||
|
||||
usb_register_bus (&hcd->self);
|
||||
|
||||
if ((retval = driver->start (hcd)) < 0)
|
||||
usb_hcd_pci_remove (dev);
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_probe);
|
||||
|
||||
|
||||
/* may be called without controller electrically present */
|
||||
/* may be called with controller, bus, and devices active */
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
|
||||
* @dev: USB Host Controller being removed
|
||||
* Context: !in_interrupt()
|
||||
*
|
||||
* Reverses the effect of usb_hcd_pci_probe(), first invoking
|
||||
* the HCD's stop() method. It is always called from a thread
|
||||
* context, normally "rmmod", "apmd", or something similar.
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as remove().
|
||||
*/
|
||||
void STDCALL usb_hcd_pci_remove (struct pci_dev *dev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
struct usb_device *hub;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
if (!hcd)
|
||||
return;
|
||||
dev_info (hcd->controller, "remove, state %x\n", hcd->state);
|
||||
|
||||
if (in_interrupt ())
|
||||
BUG ();
|
||||
|
||||
hub = hcd->self.root_hub;
|
||||
hcd->state = USB_STATE_QUIESCING;
|
||||
|
||||
dev_dbg (hcd->controller, "roothub graceful disconnect\n");
|
||||
usb_disconnect (&hub);
|
||||
|
||||
hcd->driver->stop (hcd);
|
||||
hcd_buffer_destroy (hcd);
|
||||
hcd->state = USB_STATE_HALT;
|
||||
pci_set_drvdata (dev, 0);
|
||||
|
||||
free_irq (hcd->irq, hcd);
|
||||
if (hcd->driver->flags & HCD_MEMORY) {
|
||||
iounmap (hcd->regs);
|
||||
release_mem_region (pci_resource_start (dev, 0),
|
||||
pci_resource_len (dev, 0));
|
||||
} else {
|
||||
release_region (pci_resource_start (dev, hcd->region),
|
||||
pci_resource_len (dev, hcd->region));
|
||||
}
|
||||
|
||||
usb_deregister_bus (&hcd->self);
|
||||
if (atomic_read (&hcd->self.refcnt) != 1) {
|
||||
dev_warn (hcd->controller,
|
||||
"dangling refs (%d) to bus %d!\n",
|
||||
atomic_read (&hcd->self.refcnt) - 1,
|
||||
hcd->self.busnum);
|
||||
}
|
||||
hcd->driver->hcd_free (hcd);
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_remove);
|
||||
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/*
|
||||
* Some "sleep" power levels imply updating struct usb_driver
|
||||
* to include a callback asking hcds to do their bit by checking
|
||||
* if all the drivers can suspend. Gets involved with remote wakeup.
|
||||
*
|
||||
* If there are pending urbs, then HCs will need to access memory,
|
||||
* causing extra power drain. New sleep()/wakeup() PM calls might
|
||||
* be needed, beyond PCI suspend()/resume(). The root hub timer
|
||||
* still be accessing memory though ...
|
||||
*
|
||||
* FIXME: USB should have some power budgeting support working with
|
||||
* all kinds of hubs.
|
||||
*
|
||||
* FIXME: This assumes only D0->D3 suspend and D3->D0 resume.
|
||||
* D1 and D2 states should do something, yes?
|
||||
*
|
||||
* FIXME: Should provide generic enable_wake(), calling pci_enable_wake()
|
||||
* for all supported states, so that USB remote wakeup can work for any
|
||||
* devices that support it (and are connected via powered hubs).
|
||||
*
|
||||
* FIXME: resume doesn't seem to work right any more...
|
||||
*/
|
||||
|
||||
|
||||
// 2.4 kernels have issued concurrent resumes (w/APM)
|
||||
// we defend against that error; PCI doesn't yet.
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_suspend - power management suspend of a PCI-based HCD
|
||||
* @dev: USB Host Controller being suspended
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as suspend().
|
||||
*/
|
||||
int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
int retval;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
dev_info (hcd->controller, "suspend to state %d\n", state);
|
||||
|
||||
pci_save_state (dev, hcd->pci_state);
|
||||
|
||||
// FIXME for all connected devices, leaf-to-root:
|
||||
// driver->suspend()
|
||||
// proposed "new 2.5 driver model" will automate that
|
||||
|
||||
/* driver may want to disable DMA etc */
|
||||
retval = hcd->driver->suspend (hcd, state);
|
||||
hcd->state = USB_STATE_SUSPENDED;
|
||||
|
||||
pci_set_power_state (dev, state);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_suspend);
|
||||
|
||||
/**
|
||||
* usb_hcd_pci_resume - power management resume of a PCI-based HCD
|
||||
* @dev: USB Host Controller being resumed
|
||||
*
|
||||
* Store this function in the HCD's struct pci_driver as resume().
|
||||
*/
|
||||
int usb_hcd_pci_resume (struct pci_dev *dev)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
int retval;
|
||||
|
||||
hcd = pci_get_drvdata(dev);
|
||||
dev_info (hcd->controller, "resume\n");
|
||||
|
||||
/* guard against multiple resumes (APM bug?) */
|
||||
atomic_inc (&hcd->resume_count);
|
||||
if (atomic_read (&hcd->resume_count) != 1) {
|
||||
dev_err (hcd->controller, "concurrent PCI resumes\n");
|
||||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
retval = -EBUSY;
|
||||
if (hcd->state != USB_STATE_SUSPENDED) {
|
||||
dev_dbg (hcd->controller, "can't resume, not suspended!\n");
|
||||
goto done;
|
||||
}
|
||||
hcd->state = USB_STATE_RESUMING;
|
||||
|
||||
pci_set_power_state (dev, 0);
|
||||
pci_restore_state (dev, hcd->pci_state);
|
||||
|
||||
retval = hcd->driver->resume (hcd);
|
||||
if (!HCD_IS_RUNNING (hcd->state)) {
|
||||
dev_dbg (hcd->controller, "resume fail, retval %d\n", retval);
|
||||
usb_hc_died (hcd);
|
||||
// FIXME: recover, reset etc.
|
||||
} else {
|
||||
// FIXME for all connected devices, root-to-leaf:
|
||||
// driver->resume ();
|
||||
// proposed "new 2.5 driver model" will automate that
|
||||
}
|
||||
|
||||
done:
|
||||
atomic_dec (&hcd->resume_count);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL (usb_hcd_pci_resume);
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,481 +1,481 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2002 by David Brownell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* This file contains declarations of usbcore internals that are mostly
|
||||
* used or exposed by Host Controller Drivers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* USB Packet IDs (PIDs)
|
||||
*/
|
||||
#define USB_PID_UNDEF_0 0xf0
|
||||
#define USB_PID_OUT 0xe1
|
||||
#define USB_PID_ACK 0xd2
|
||||
#define USB_PID_DATA0 0xc3
|
||||
#define USB_PID_PING 0xb4 /* USB 2.0 */
|
||||
#define USB_PID_SOF 0xa5
|
||||
#define USB_PID_NYET 0x96 /* USB 2.0 */
|
||||
#define USB_PID_DATA2 0x87 /* USB 2.0 */
|
||||
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
|
||||
#define USB_PID_IN 0x69
|
||||
#define USB_PID_NAK 0x5a
|
||||
#define USB_PID_DATA1 0x4b
|
||||
#define USB_PID_PREAMBLE 0x3c /* Token mode */
|
||||
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
|
||||
#define USB_PID_SETUP 0x2d
|
||||
#define USB_PID_STALL 0x1e
|
||||
#define USB_PID_MDATA 0x0f /* USB 2.0 */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* USB Host Controller Driver (usb_hcd) framework
|
||||
*
|
||||
* Since "struct usb_bus" is so thin, you can't share much code in it.
|
||||
* This framework is a layer over that, and should be more sharable.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct usb_hcd { /* usb_bus.hcpriv points to this */
|
||||
|
||||
/*
|
||||
* housekeeping
|
||||
*/
|
||||
struct usb_bus self; /* hcd is-a bus */
|
||||
|
||||
const char *product_desc; /* product/vendor string */
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
struct timer_list rh_timer; /* drives root hub */
|
||||
struct list_head dev_list; /* devices on this bus */
|
||||
struct work_struct work;
|
||||
|
||||
/*
|
||||
* hardware info/state
|
||||
*/
|
||||
struct hc_driver *driver; /* hw-specific hooks */
|
||||
int irq; /* irq allocated */
|
||||
void *regs; /* device memory/io */
|
||||
struct device *controller; /* handle to hardware */
|
||||
|
||||
/* a few non-PCI controllers exist, mostly for OHCI */
|
||||
struct pci_dev *pdev; /* pci is typical */
|
||||
#ifdef CONFIG_PCI
|
||||
int region; /* pci region for regs */
|
||||
u32 pci_state [16]; /* for PM state save */
|
||||
atomic_t resume_count; /* multiple resumes issue */
|
||||
#endif
|
||||
|
||||
#define HCD_BUFFER_POOLS 4
|
||||
struct pci_pool *pool [HCD_BUFFER_POOLS];
|
||||
|
||||
int state;
|
||||
# define __ACTIVE 0x01
|
||||
# define __SLEEPY 0x02
|
||||
# define __SUSPEND 0x04
|
||||
# define __TRANSIENT 0x80
|
||||
|
||||
# define USB_STATE_HALT 0
|
||||
# define USB_STATE_RUNNING (__ACTIVE)
|
||||
# define USB_STATE_READY (__ACTIVE|__SLEEPY)
|
||||
# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
|
||||
# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
|
||||
# define USB_STATE_SUSPENDED (__SUSPEND)
|
||||
|
||||
#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
|
||||
#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
|
||||
|
||||
/* more shared queuing code would be good; it should support
|
||||
* smarter scheduling, handle transaction translators, etc;
|
||||
* input size of periodic table to an interrupt scheduler.
|
||||
* (ohci 32, uhci 1024, ehci 256/512/1024).
|
||||
*/
|
||||
};
|
||||
|
||||
/* 2.4 does this a bit differently ... */
|
||||
static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
|
||||
{
|
||||
return &hcd->self;
|
||||
}
|
||||
|
||||
|
||||
struct hcd_dev { /* usb_device.hcpriv points to this */
|
||||
struct list_head dev_list; /* on this hcd */
|
||||
struct list_head urb_list; /* pending on this dev */
|
||||
|
||||
/* per-configuration HC/HCD state, such as QH or ED */
|
||||
void *ep[32];
|
||||
};
|
||||
|
||||
// urb.hcpriv is really hardware-specific
|
||||
|
||||
struct hcd_timeout { /* timeouts we allocate */
|
||||
struct list_head timeout_list;
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FIXME usb_operations should vanish or become hc_driver,
|
||||
* when usb_bus and usb_hcd become the same thing.
|
||||
*/
|
||||
|
||||
struct usb_operations {
|
||||
int (*allocate)(struct usb_device *);
|
||||
int (*deallocate)(struct usb_device *);
|
||||
int (*get_frame_number) (struct usb_device *usb_dev);
|
||||
int (*submit_urb) (struct urb *urb, int mem_flags);
|
||||
int (*unlink_urb) (struct urb *urb);
|
||||
|
||||
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
|
||||
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
|
||||
int mem_flags,
|
||||
dma_addr_t *dma);
|
||||
void (*buffer_free)(struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
void (*disable)(struct usb_device *udev, int bEndpointAddress);
|
||||
};
|
||||
|
||||
/* each driver provides one of these, and hardware init support */
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
// new struct from 2.6
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
/* irq handler */
|
||||
irqreturn_t (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
|
||||
|
||||
int flags;
|
||||
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
||||
#define HCD_USB11 0x0010 /* USB 1.1 */
|
||||
#define HCD_USB2 0x0020 /* USB 2.0 */
|
||||
|
||||
/* called to init HCD and root hub */
|
||||
int (*reset) (struct usb_hcd *hcd);
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* called after all devices were suspended */
|
||||
int (*suspend) (struct usb_hcd *hcd, u32 state);
|
||||
|
||||
/* called before any devices get resumed */
|
||||
int (*resume) (struct usb_hcd *hcd);
|
||||
|
||||
/* cleanly make HCD stop writing memory and doing I/O */
|
||||
void (*stop) (struct usb_hcd *hcd);
|
||||
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* memory lifecycle */
|
||||
struct usb_hcd *(*hcd_alloc) (void);
|
||||
void (*hcd_free) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
|
||||
int mem_flags);
|
||||
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct hcd_dev *dev, int bEndpointAddress);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
};
|
||||
|
||||
// old version, "just in case"
|
||||
#if 0
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
/* irq handler */
|
||||
void (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
|
||||
|
||||
int flags;
|
||||
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
||||
#define HCD_USB11 0x0010 /* USB 1.1 */
|
||||
#define HCD_USB2 0x0020 /* USB 2.0 */
|
||||
|
||||
/* called to init HCD and root hub */
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* called after all devices were suspended */
|
||||
int (*suspend) (struct usb_hcd *hcd, u32 state);
|
||||
|
||||
/* called before any devices get resumed */
|
||||
int (*resume) (struct usb_hcd *hcd);
|
||||
|
||||
/* cleanly make HCD stop writing memory and doing I/O */
|
||||
void (*stop) (struct usb_hcd *hcd);
|
||||
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* memory lifecycle */
|
||||
struct usb_hcd *(*hcd_alloc) (void);
|
||||
void (*hcd_free) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
|
||||
int mem_flags);
|
||||
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct hcd_dev *dev, int bEndpointAddress);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
};
|
||||
#endif
|
||||
|
||||
extern void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
|
||||
extern void STDCALL usb_bus_init (struct usb_bus *bus);
|
||||
extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
struct pci_dev;
|
||||
struct pci_device_id;
|
||||
extern int STDCALL usb_hcd_pci_probe (struct pci_dev *dev,
|
||||
const struct pci_device_id *id);
|
||||
extern void STDCALL usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
// FIXME: see Documentation/power/pci.txt (2.4.6 and later?)
|
||||
// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_resume (struct pci_dev *dev);
|
||||
// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
|
||||
int hcd_buffer_create (struct usb_hcd *hcd);
|
||||
void hcd_buffer_destroy (struct usb_hcd *hcd);
|
||||
|
||||
void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
|
||||
int mem_flags, dma_addr_t *dma);
|
||||
void hcd_buffer_free (struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
/* generic bus glue, needed for host controllers that don't use PCI */
|
||||
extern struct usb_operations usb_hcd_operations;
|
||||
extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
|
||||
extern void STDCALL usb_hc_died (struct usb_hcd *hcd);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
|
||||
extern int usb_new_device(struct usb_device *dev, struct device *parent);
|
||||
extern void STDCALL usb_connect(struct usb_device *dev);
|
||||
extern void usb_disconnect(struct usb_device **);
|
||||
|
||||
/* exported to hub driver ONLY to support usb_reset_device () */
|
||||
extern int usb_get_configuration(struct usb_device *dev);
|
||||
extern void usb_set_maxpacket(struct usb_device *dev);
|
||||
extern void usb_destroy_configuration(struct usb_device *dev);
|
||||
extern int usb_set_address(struct usb_device *dev);
|
||||
|
||||
/* use these only before the device's address has been set */
|
||||
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
|
||||
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* HCD Root Hub support
|
||||
*/
|
||||
|
||||
#include "hub.h"
|
||||
|
||||
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
|
||||
#define DeviceRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
||||
#define DeviceOutRequest \
|
||||
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
||||
|
||||
#define InterfaceRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
|
||||
#define EndpointRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
#define EndpointOutRequest \
|
||||
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
|
||||
/* table 9.6 standard features */
|
||||
#define DEVICE_REMOTE_WAKEUP 1
|
||||
#define ENDPOINT_HALT 0
|
||||
|
||||
/* class requests from the USB 2.0 hub spec, table 11-15 */
|
||||
/* GetBusState and SetHubDescriptor are optional, omitted */
|
||||
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
|
||||
#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
|
||||
#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
|
||||
#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
|
||||
#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
|
||||
#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
|
||||
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Generic bandwidth allocation constants/support
|
||||
*/
|
||||
#define FRAME_TIME_USECS 1000L
|
||||
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
|
||||
/* Trying not to use worst-case bit-stuffing
|
||||
of (7/6 * 8 * bytecount) = 9.33 * bytecount */
|
||||
/* bytecount = data payload byte count */
|
||||
|
||||
#define NS_TO_US(ns) ((ns + 500L) / 1000L)
|
||||
/* convert & round nanoseconds to microseconds */
|
||||
|
||||
extern void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
|
||||
int bustime, int isoc);
|
||||
extern void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
|
||||
int isoc);
|
||||
|
||||
/*
|
||||
* Full/low speed bandwidth allocation constants/support.
|
||||
*/
|
||||
#define BW_HOST_DELAY 1000L /* nanoseconds */
|
||||
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
|
||||
/* 4 full-speed bit times (est.) */
|
||||
|
||||
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
|
||||
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
|
||||
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
|
||||
|
||||
extern int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
|
||||
|
||||
/*
|
||||
* Ceiling microseconds (typical) for that many bytes at high speed
|
||||
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
|
||||
* to preallocate bandwidth)
|
||||
*/
|
||||
#define USB2_HOST_DELAY 5 /* nsec, guess */
|
||||
#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
+ USB2_HOST_DELAY)
|
||||
#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
+ USB2_HOST_DELAY)
|
||||
|
||||
extern long STDCALL usb_calc_bus_time (int speed, int is_input,
|
||||
int isoc, int bytecount);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
extern struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *);
|
||||
extern void STDCALL usb_free_bus (struct usb_bus *);
|
||||
|
||||
extern void STDCALL usb_register_bus (struct usb_bus *);
|
||||
extern void STDCALL usb_deregister_bus (struct usb_bus *);
|
||||
|
||||
extern int STDCALL usb_register_root_hub (struct usb_device *usb_dev,
|
||||
struct device *parent_dev);
|
||||
|
||||
/* for portability to 2.4, hcds should call this */
|
||||
static inline int hcd_register_root (struct usb_hcd *hcd)
|
||||
{
|
||||
return usb_register_root_hub (
|
||||
hcd_to_bus (hcd)->root_hub, hcd->controller);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* exported only within usbcore */
|
||||
|
||||
extern struct list_head usb_bus_list;
|
||||
extern struct semaphore usb_bus_list_lock;
|
||||
|
||||
extern void usb_bus_get (struct usb_bus *bus);
|
||||
extern void usb_bus_put (struct usb_bus *bus);
|
||||
|
||||
extern int usb_find_interface_driver (struct usb_device *dev,
|
||||
struct usb_interface *interface);
|
||||
|
||||
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
|
||||
|
||||
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
|
||||
|
||||
/*
|
||||
* USB device fs stuff
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USB_DEVICEFS
|
||||
|
||||
/*
|
||||
* these are expected to be called from the USB core/hub thread
|
||||
* with the kernel lock held
|
||||
*/
|
||||
extern void usbfs_add_bus(struct usb_bus *bus);
|
||||
extern void usbfs_remove_bus(struct usb_bus *bus);
|
||||
extern void usbfs_add_device(struct usb_device *dev);
|
||||
extern void usbfs_remove_device(struct usb_device *dev);
|
||||
extern void usbfs_update_special (void);
|
||||
|
||||
extern int usbfs_init(void);
|
||||
extern void usbfs_cleanup(void);
|
||||
|
||||
#else /* CONFIG_USB_DEVICEFS */
|
||||
|
||||
static inline void usbfs_add_bus(struct usb_bus *bus) {}
|
||||
static inline void usbfs_remove_bus(struct usb_bus *bus) {}
|
||||
static inline void usbfs_add_device(struct usb_device *dev) {}
|
||||
static inline void usbfs_remove_device(struct usb_device *dev) {}
|
||||
static inline void usbfs_update_special (void) {}
|
||||
|
||||
static inline int usbfs_init(void) { return 0; }
|
||||
static inline void usbfs_cleanup(void) { }
|
||||
|
||||
#endif /* CONFIG_USB_DEVICEFS */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
|
||||
// bleech -- resurfaced in 2.4.11 or 2.4.12
|
||||
#define bitmap DeviceRemovable
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* random stuff */
|
||||
|
||||
#define RUN_CONTEXT (in_irq () ? "in_irq" \
|
||||
: (in_interrupt () ? "in_interrupt" : "can sleep"))
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2002 by David Brownell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* This file contains declarations of usbcore internals that are mostly
|
||||
* used or exposed by Host Controller Drivers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* USB Packet IDs (PIDs)
|
||||
*/
|
||||
#define USB_PID_UNDEF_0 0xf0
|
||||
#define USB_PID_OUT 0xe1
|
||||
#define USB_PID_ACK 0xd2
|
||||
#define USB_PID_DATA0 0xc3
|
||||
#define USB_PID_PING 0xb4 /* USB 2.0 */
|
||||
#define USB_PID_SOF 0xa5
|
||||
#define USB_PID_NYET 0x96 /* USB 2.0 */
|
||||
#define USB_PID_DATA2 0x87 /* USB 2.0 */
|
||||
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
|
||||
#define USB_PID_IN 0x69
|
||||
#define USB_PID_NAK 0x5a
|
||||
#define USB_PID_DATA1 0x4b
|
||||
#define USB_PID_PREAMBLE 0x3c /* Token mode */
|
||||
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
|
||||
#define USB_PID_SETUP 0x2d
|
||||
#define USB_PID_STALL 0x1e
|
||||
#define USB_PID_MDATA 0x0f /* USB 2.0 */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* USB Host Controller Driver (usb_hcd) framework
|
||||
*
|
||||
* Since "struct usb_bus" is so thin, you can't share much code in it.
|
||||
* This framework is a layer over that, and should be more sharable.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct usb_hcd { /* usb_bus.hcpriv points to this */
|
||||
|
||||
/*
|
||||
* housekeeping
|
||||
*/
|
||||
struct usb_bus self; /* hcd is-a bus */
|
||||
|
||||
const char *product_desc; /* product/vendor string */
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
struct timer_list rh_timer; /* drives root hub */
|
||||
struct list_head dev_list; /* devices on this bus */
|
||||
struct work_struct work;
|
||||
|
||||
/*
|
||||
* hardware info/state
|
||||
*/
|
||||
struct hc_driver *driver; /* hw-specific hooks */
|
||||
int irq; /* irq allocated */
|
||||
void *regs; /* device memory/io */
|
||||
struct device *controller; /* handle to hardware */
|
||||
|
||||
/* a few non-PCI controllers exist, mostly for OHCI */
|
||||
struct pci_dev *pdev; /* pci is typical */
|
||||
#ifdef CONFIG_PCI
|
||||
int region; /* pci region for regs */
|
||||
u32 pci_state [16]; /* for PM state save */
|
||||
atomic_t resume_count; /* multiple resumes issue */
|
||||
#endif
|
||||
|
||||
#define HCD_BUFFER_POOLS 4
|
||||
struct pci_pool *pool [HCD_BUFFER_POOLS];
|
||||
|
||||
int state;
|
||||
# define __ACTIVE 0x01
|
||||
# define __SLEEPY 0x02
|
||||
# define __SUSPEND 0x04
|
||||
# define __TRANSIENT 0x80
|
||||
|
||||
# define USB_STATE_HALT 0
|
||||
# define USB_STATE_RUNNING (__ACTIVE)
|
||||
# define USB_STATE_READY (__ACTIVE|__SLEEPY)
|
||||
# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
|
||||
# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
|
||||
# define USB_STATE_SUSPENDED (__SUSPEND)
|
||||
|
||||
#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
|
||||
#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
|
||||
|
||||
/* more shared queuing code would be good; it should support
|
||||
* smarter scheduling, handle transaction translators, etc;
|
||||
* input size of periodic table to an interrupt scheduler.
|
||||
* (ohci 32, uhci 1024, ehci 256/512/1024).
|
||||
*/
|
||||
};
|
||||
|
||||
/* 2.4 does this a bit differently ... */
|
||||
static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
|
||||
{
|
||||
return &hcd->self;
|
||||
}
|
||||
|
||||
|
||||
struct hcd_dev { /* usb_device.hcpriv points to this */
|
||||
struct list_head dev_list; /* on this hcd */
|
||||
struct list_head urb_list; /* pending on this dev */
|
||||
|
||||
/* per-configuration HC/HCD state, such as QH or ED */
|
||||
void *ep[32];
|
||||
};
|
||||
|
||||
// urb.hcpriv is really hardware-specific
|
||||
|
||||
struct hcd_timeout { /* timeouts we allocate */
|
||||
struct list_head timeout_list;
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FIXME usb_operations should vanish or become hc_driver,
|
||||
* when usb_bus and usb_hcd become the same thing.
|
||||
*/
|
||||
|
||||
struct usb_operations {
|
||||
int (*allocate)(struct usb_device *);
|
||||
int (*deallocate)(struct usb_device *);
|
||||
int (*get_frame_number) (struct usb_device *usb_dev);
|
||||
int (*submit_urb) (struct urb *urb, int mem_flags);
|
||||
int (*unlink_urb) (struct urb *urb);
|
||||
|
||||
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
|
||||
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
|
||||
int mem_flags,
|
||||
dma_addr_t *dma);
|
||||
void (*buffer_free)(struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
void (*disable)(struct usb_device *udev, int bEndpointAddress);
|
||||
};
|
||||
|
||||
/* each driver provides one of these, and hardware init support */
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
// new struct from 2.6
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
/* irq handler */
|
||||
irqreturn_t (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
|
||||
|
||||
int flags;
|
||||
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
||||
#define HCD_USB11 0x0010 /* USB 1.1 */
|
||||
#define HCD_USB2 0x0020 /* USB 2.0 */
|
||||
|
||||
/* called to init HCD and root hub */
|
||||
int (*reset) (struct usb_hcd *hcd);
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* called after all devices were suspended */
|
||||
int (*suspend) (struct usb_hcd *hcd, u32 state);
|
||||
|
||||
/* called before any devices get resumed */
|
||||
int (*resume) (struct usb_hcd *hcd);
|
||||
|
||||
/* cleanly make HCD stop writing memory and doing I/O */
|
||||
void (*stop) (struct usb_hcd *hcd);
|
||||
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* memory lifecycle */
|
||||
struct usb_hcd *(*hcd_alloc) (void);
|
||||
void (*hcd_free) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
|
||||
int mem_flags);
|
||||
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct hcd_dev *dev, int bEndpointAddress);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
};
|
||||
|
||||
// old version, "just in case"
|
||||
#if 0
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
/* irq handler */
|
||||
int (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
|
||||
|
||||
int flags;
|
||||
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
||||
#define HCD_USB11 0x0010 /* USB 1.1 */
|
||||
#define HCD_USB2 0x0020 /* USB 2.0 */
|
||||
|
||||
/* called to init HCD and root hub */
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* called after all devices were suspended */
|
||||
int (*suspend) (struct usb_hcd *hcd, u32 state);
|
||||
|
||||
/* called before any devices get resumed */
|
||||
int (*resume) (struct usb_hcd *hcd);
|
||||
|
||||
/* cleanly make HCD stop writing memory and doing I/O */
|
||||
void (*stop) (struct usb_hcd *hcd);
|
||||
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* memory lifecycle */
|
||||
struct usb_hcd *(*hcd_alloc) (void);
|
||||
void (*hcd_free) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
|
||||
int mem_flags);
|
||||
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct hcd_dev *dev, int bEndpointAddress);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
};
|
||||
#endif
|
||||
|
||||
extern void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
|
||||
extern void STDCALL usb_bus_init (struct usb_bus *bus);
|
||||
extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
struct pci_dev;
|
||||
struct pci_device_id;
|
||||
extern int STDCALL usb_hcd_pci_probe (struct pci_dev *dev,
|
||||
const struct pci_device_id *id);
|
||||
extern void STDCALL usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
// FIXME: see Documentation/power/pci.txt (2.4.6 and later?)
|
||||
// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_resume (struct pci_dev *dev);
|
||||
// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
|
||||
int hcd_buffer_create (struct usb_hcd *hcd);
|
||||
void hcd_buffer_destroy (struct usb_hcd *hcd);
|
||||
|
||||
void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
|
||||
int mem_flags, dma_addr_t *dma);
|
||||
void hcd_buffer_free (struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
/* generic bus glue, needed for host controllers that don't use PCI */
|
||||
extern struct usb_operations usb_hcd_operations;
|
||||
extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
|
||||
extern void STDCALL usb_hc_died (struct usb_hcd *hcd);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
|
||||
extern int usb_new_device(struct usb_device *dev, struct device *parent);
|
||||
extern void STDCALL usb_connect(struct usb_device *dev);
|
||||
extern void usb_disconnect(struct usb_device **);
|
||||
|
||||
/* exported to hub driver ONLY to support usb_reset_device () */
|
||||
extern int usb_get_configuration(struct usb_device *dev);
|
||||
extern void usb_set_maxpacket(struct usb_device *dev);
|
||||
extern void usb_destroy_configuration(struct usb_device *dev);
|
||||
extern int usb_set_address(struct usb_device *dev);
|
||||
|
||||
/* use these only before the device's address has been set */
|
||||
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
|
||||
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* HCD Root Hub support
|
||||
*/
|
||||
|
||||
#include "hub.h"
|
||||
|
||||
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
|
||||
#define DeviceRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
||||
#define DeviceOutRequest \
|
||||
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
||||
|
||||
#define InterfaceRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
|
||||
#define EndpointRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
#define EndpointOutRequest \
|
||||
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
|
||||
/* table 9.6 standard features */
|
||||
#define DEVICE_REMOTE_WAKEUP 1
|
||||
#define ENDPOINT_HALT 0
|
||||
|
||||
/* class requests from the USB 2.0 hub spec, table 11-15 */
|
||||
/* GetBusState and SetHubDescriptor are optional, omitted */
|
||||
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
|
||||
#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
|
||||
#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
|
||||
#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
|
||||
#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
|
||||
#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
|
||||
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Generic bandwidth allocation constants/support
|
||||
*/
|
||||
#define FRAME_TIME_USECS 1000L
|
||||
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
|
||||
/* Trying not to use worst-case bit-stuffing
|
||||
of (7/6 * 8 * bytecount) = 9.33 * bytecount */
|
||||
/* bytecount = data payload byte count */
|
||||
|
||||
#define NS_TO_US(ns) ((ns + 500L) / 1000L)
|
||||
/* convert & round nanoseconds to microseconds */
|
||||
|
||||
extern void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
|
||||
int bustime, int isoc);
|
||||
extern void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
|
||||
int isoc);
|
||||
|
||||
/*
|
||||
* Full/low speed bandwidth allocation constants/support.
|
||||
*/
|
||||
#define BW_HOST_DELAY 1000L /* nanoseconds */
|
||||
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
|
||||
/* 4 full-speed bit times (est.) */
|
||||
|
||||
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
|
||||
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
|
||||
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
|
||||
|
||||
extern int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
|
||||
|
||||
/*
|
||||
* Ceiling microseconds (typical) for that many bytes at high speed
|
||||
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
|
||||
* to preallocate bandwidth)
|
||||
*/
|
||||
#define USB2_HOST_DELAY 5 /* nsec, guess */
|
||||
#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
+ USB2_HOST_DELAY)
|
||||
#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
+ USB2_HOST_DELAY)
|
||||
|
||||
extern long STDCALL usb_calc_bus_time (int speed, int is_input,
|
||||
int isoc, int bytecount);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
extern struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *);
|
||||
extern void STDCALL usb_free_bus (struct usb_bus *);
|
||||
|
||||
extern void STDCALL usb_register_bus (struct usb_bus *);
|
||||
extern void STDCALL usb_deregister_bus (struct usb_bus *);
|
||||
|
||||
extern int STDCALL usb_register_root_hub (struct usb_device *usb_dev,
|
||||
struct device *parent_dev);
|
||||
|
||||
/* for portability to 2.4, hcds should call this */
|
||||
static inline int hcd_register_root (struct usb_hcd *hcd)
|
||||
{
|
||||
return usb_register_root_hub (
|
||||
hcd_to_bus (hcd)->root_hub, hcd->controller);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* exported only within usbcore */
|
||||
|
||||
extern struct list_head usb_bus_list;
|
||||
extern struct semaphore usb_bus_list_lock;
|
||||
|
||||
extern void usb_bus_get (struct usb_bus *bus);
|
||||
extern void usb_bus_put (struct usb_bus *bus);
|
||||
|
||||
extern int usb_find_interface_driver (struct usb_device *dev,
|
||||
struct usb_interface *interface);
|
||||
|
||||
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
|
||||
|
||||
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
|
||||
|
||||
/*
|
||||
* USB device fs stuff
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USB_DEVICEFS
|
||||
|
||||
/*
|
||||
* these are expected to be called from the USB core/hub thread
|
||||
* with the kernel lock held
|
||||
*/
|
||||
extern void usbfs_add_bus(struct usb_bus *bus);
|
||||
extern void usbfs_remove_bus(struct usb_bus *bus);
|
||||
extern void usbfs_add_device(struct usb_device *dev);
|
||||
extern void usbfs_remove_device(struct usb_device *dev);
|
||||
extern void usbfs_update_special (void);
|
||||
|
||||
extern int usbfs_init(void);
|
||||
extern void usbfs_cleanup(void);
|
||||
|
||||
#else /* CONFIG_USB_DEVICEFS */
|
||||
|
||||
static inline void usbfs_add_bus(struct usb_bus *bus) {}
|
||||
static inline void usbfs_remove_bus(struct usb_bus *bus) {}
|
||||
static inline void usbfs_add_device(struct usb_device *dev) {}
|
||||
static inline void usbfs_remove_device(struct usb_device *dev) {}
|
||||
static inline void usbfs_update_special (void) {}
|
||||
|
||||
static inline int usbfs_init(void) { return 0; }
|
||||
static inline void usbfs_cleanup(void) { }
|
||||
|
||||
#endif /* CONFIG_USB_DEVICEFS */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
|
||||
// bleech -- resurfaced in 2.4.11 or 2.4.12
|
||||
#define bitmap DeviceRemovable
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* random stuff */
|
||||
|
||||
#define RUN_CONTEXT (in_irq () ? "in_irq" \
|
||||
: (in_interrupt () ? "in_interrupt" : "can sleep"))
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,195 +1,195 @@
|
|||
#ifndef __LINUX_HUB_H
|
||||
#define __LINUX_HUB_H
|
||||
|
||||
/*
|
||||
* Hub protocol and driver data structures.
|
||||
*
|
||||
* Some of these are known to the "virtual root hub" code
|
||||
* in host controller drivers.
|
||||
*/
|
||||
#if 0
|
||||
#include <linux/list.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/compiler.h> /* likely()/unlikely() */
|
||||
#endif
|
||||
/*
|
||||
* Hub request types
|
||||
*/
|
||||
|
||||
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
|
||||
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
|
||||
|
||||
/*
|
||||
* Hub class requests
|
||||
* See USB 2.0 spec Table 11-16
|
||||
*/
|
||||
#define HUB_CLEAR_TT_BUFFER 8
|
||||
#define HUB_RESET_TT 9
|
||||
#define HUB_GET_TT_STATE 10
|
||||
#define HUB_STOP_TT 11
|
||||
|
||||
/*
|
||||
* Hub Class feature numbers
|
||||
* See USB 2.0 spec Table 11-17
|
||||
*/
|
||||
#define C_HUB_LOCAL_POWER 0
|
||||
#define C_HUB_OVER_CURRENT 1
|
||||
|
||||
/*
|
||||
* Port feature numbers
|
||||
* See USB 2.0 spec Table 11-17
|
||||
*/
|
||||
#define USB_PORT_FEAT_CONNECTION 0
|
||||
#define USB_PORT_FEAT_ENABLE 1
|
||||
#define USB_PORT_FEAT_SUSPEND 2
|
||||
#define USB_PORT_FEAT_OVER_CURRENT 3
|
||||
#define USB_PORT_FEAT_RESET 4
|
||||
#define USB_PORT_FEAT_POWER 8
|
||||
#define USB_PORT_FEAT_LOWSPEED 9
|
||||
#define USB_PORT_FEAT_HIGHSPEED 10
|
||||
#define USB_PORT_FEAT_C_CONNECTION 16
|
||||
#define USB_PORT_FEAT_C_ENABLE 17
|
||||
#define USB_PORT_FEAT_C_SUSPEND 18
|
||||
#define USB_PORT_FEAT_C_OVER_CURRENT 19
|
||||
#define USB_PORT_FEAT_C_RESET 20
|
||||
#define USB_PORT_FEAT_TEST 21
|
||||
#define USB_PORT_FEAT_INDICATOR 22
|
||||
|
||||
/*
|
||||
* Hub Status and Hub Change results
|
||||
* See USB 2.0 spec Table 11-19 and Table 11-20
|
||||
*/
|
||||
struct usb_port_status {
|
||||
__u16 wPortStatus;
|
||||
__u16 wPortChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* wPortStatus bit field
|
||||
* See USB 2.0 spec Table 11-21
|
||||
*/
|
||||
#define USB_PORT_STAT_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_RESET 0x0010
|
||||
/* bits 5 to 7 are reserved */
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_LOW_SPEED 0x0200
|
||||
#define USB_PORT_STAT_HIGH_SPEED 0x0400
|
||||
#define USB_PORT_STAT_TEST 0x0800
|
||||
#define USB_PORT_STAT_INDICATOR 0x1000
|
||||
/* bits 13 to 15 are reserved */
|
||||
|
||||
/*
|
||||
* wPortChange bit field
|
||||
* See USB 2.0 spec Table 11-22
|
||||
* Bits 0 to 4 shown, bits 5 to 15 are reserved
|
||||
*/
|
||||
#define USB_PORT_STAT_C_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_C_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_C_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_C_RESET 0x0010
|
||||
|
||||
/*
|
||||
* wHubCharacteristics (masks)
|
||||
* See USB 2.0 spec Table 11-13, offset 3
|
||||
*/
|
||||
#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */
|
||||
#define HUB_CHAR_COMPOUND 0x0004 /* D2 */
|
||||
#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */
|
||||
#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */
|
||||
#define HUB_CHAR_PORTIND 0x0080 /* D7 */
|
||||
|
||||
struct usb_hub_status {
|
||||
__u16 wHubStatus;
|
||||
__u16 wHubChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* Hub Status & Hub Change bit masks
|
||||
* See USB 2.0 spec Table 11-19 and Table 11-20
|
||||
* Bits 0 and 1 for wHubStatus and wHubChange
|
||||
* Bits 2 to 15 are reserved for both
|
||||
*/
|
||||
#define HUB_STATUS_LOCAL_POWER 0x0001
|
||||
#define HUB_STATUS_OVERCURRENT 0x0002
|
||||
#define HUB_CHANGE_LOCAL_POWER 0x0001
|
||||
#define HUB_CHANGE_OVERCURRENT 0x0002
|
||||
|
||||
|
||||
/*
|
||||
* Hub descriptor
|
||||
* See USB 2.0 spec Table 11-13
|
||||
*/
|
||||
|
||||
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
||||
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||
|
||||
struct usb_hub_descriptor {
|
||||
__u8 bDescLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bNbrPorts;
|
||||
__u16 wHubCharacteristics;
|
||||
__u8 bPwrOn2PwrGood;
|
||||
__u8 bHubContrCurrent;
|
||||
/* add 1 bit for hub status change; round to bytes */
|
||||
__u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
__u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_device;
|
||||
|
||||
/*
|
||||
* As of USB 2.0, full/low speed devices are segregated into trees.
|
||||
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
|
||||
* The other type grows from high speed hubs when they connect to
|
||||
* full/low speed devices using "Transaction Translators" (TTs).
|
||||
*
|
||||
* TTs should only be known to the hub driver, and high speed bus
|
||||
* drivers (only EHCI for now). They affect periodic scheduling and
|
||||
* sometimes control/bulk error recovery.
|
||||
*/
|
||||
struct usb_tt {
|
||||
struct usb_device *hub; /* upstream highspeed hub */
|
||||
int multi; /* true means one TT per port */
|
||||
|
||||
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
|
||||
spinlock_t lock;
|
||||
struct list_head clear_list; /* of usb_tt_clear */
|
||||
struct work_struct kevent;
|
||||
};
|
||||
|
||||
struct usb_tt_clear {
|
||||
struct list_head clear_list;
|
||||
unsigned tt;
|
||||
u16 devinfo;
|
||||
};
|
||||
|
||||
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
|
||||
|
||||
struct usb_hub {
|
||||
struct usb_interface *intf; /* the "real" device */
|
||||
struct urb *urb; /* for interrupt polling pipe */
|
||||
|
||||
/* buffer for urb ... 1 bit each for hub and children, rounded up */
|
||||
char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
dma_addr_t buffer_dma; /* DMA address for buffer */
|
||||
union {
|
||||
struct usb_hub_status hub;
|
||||
struct usb_port_status port;
|
||||
} *status; /* buffer for status reports */
|
||||
|
||||
int error; /* last reported error */
|
||||
int nerrors; /* track consecutive errors */
|
||||
|
||||
struct list_head hub_list; /* all hubs */
|
||||
struct list_head event_list; /* hubs w/data or errs ready */
|
||||
|
||||
struct usb_hub_descriptor *descriptor; /* class descriptor */
|
||||
struct semaphore khubd_sem;
|
||||
struct usb_tt tt; /* Transaction Translator */
|
||||
};
|
||||
|
||||
#endif /* __LINUX_HUB_H */
|
||||
#ifndef __LINUX_HUB_H
|
||||
#define __LINUX_HUB_H
|
||||
|
||||
/*
|
||||
* Hub protocol and driver data structures.
|
||||
*
|
||||
* Some of these are known to the "virtual root hub" code
|
||||
* in host controller drivers.
|
||||
*/
|
||||
#if 0
|
||||
#include <linux/list.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/compiler.h> /* likely()/unlikely() */
|
||||
#endif
|
||||
/*
|
||||
* Hub request types
|
||||
*/
|
||||
|
||||
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
|
||||
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
|
||||
|
||||
/*
|
||||
* Hub class requests
|
||||
* See USB 2.0 spec Table 11-16
|
||||
*/
|
||||
#define HUB_CLEAR_TT_BUFFER 8
|
||||
#define HUB_RESET_TT 9
|
||||
#define HUB_GET_TT_STATE 10
|
||||
#define HUB_STOP_TT 11
|
||||
|
||||
/*
|
||||
* Hub Class feature numbers
|
||||
* See USB 2.0 spec Table 11-17
|
||||
*/
|
||||
#define C_HUB_LOCAL_POWER 0
|
||||
#define C_HUB_OVER_CURRENT 1
|
||||
|
||||
/*
|
||||
* Port feature numbers
|
||||
* See USB 2.0 spec Table 11-17
|
||||
*/
|
||||
#define USB_PORT_FEAT_CONNECTION 0
|
||||
#define USB_PORT_FEAT_ENABLE 1
|
||||
#define USB_PORT_FEAT_SUSPEND 2
|
||||
#define USB_PORT_FEAT_OVER_CURRENT 3
|
||||
#define USB_PORT_FEAT_RESET 4
|
||||
#define USB_PORT_FEAT_POWER 8
|
||||
#define USB_PORT_FEAT_LOWSPEED 9
|
||||
#define USB_PORT_FEAT_HIGHSPEED 10
|
||||
#define USB_PORT_FEAT_C_CONNECTION 16
|
||||
#define USB_PORT_FEAT_C_ENABLE 17
|
||||
#define USB_PORT_FEAT_C_SUSPEND 18
|
||||
#define USB_PORT_FEAT_C_OVER_CURRENT 19
|
||||
#define USB_PORT_FEAT_C_RESET 20
|
||||
#define USB_PORT_FEAT_TEST 21
|
||||
#define USB_PORT_FEAT_INDICATOR 22
|
||||
|
||||
/*
|
||||
* Hub Status and Hub Change results
|
||||
* See USB 2.0 spec Table 11-19 and Table 11-20
|
||||
*/
|
||||
struct usb_port_status {
|
||||
__u16 wPortStatus;
|
||||
__u16 wPortChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* wPortStatus bit field
|
||||
* See USB 2.0 spec Table 11-21
|
||||
*/
|
||||
#define USB_PORT_STAT_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_RESET 0x0010
|
||||
/* bits 5 to 7 are reserved */
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_LOW_SPEED 0x0200
|
||||
#define USB_PORT_STAT_HIGH_SPEED 0x0400
|
||||
#define USB_PORT_STAT_TEST 0x0800
|
||||
#define USB_PORT_STAT_INDICATOR 0x1000
|
||||
/* bits 13 to 15 are reserved */
|
||||
|
||||
/*
|
||||
* wPortChange bit field
|
||||
* See USB 2.0 spec Table 11-22
|
||||
* Bits 0 to 4 shown, bits 5 to 15 are reserved
|
||||
*/
|
||||
#define USB_PORT_STAT_C_CONNECTION 0x0001
|
||||
#define USB_PORT_STAT_C_ENABLE 0x0002
|
||||
#define USB_PORT_STAT_C_SUSPEND 0x0004
|
||||
#define USB_PORT_STAT_C_OVERCURRENT 0x0008
|
||||
#define USB_PORT_STAT_C_RESET 0x0010
|
||||
|
||||
/*
|
||||
* wHubCharacteristics (masks)
|
||||
* See USB 2.0 spec Table 11-13, offset 3
|
||||
*/
|
||||
#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */
|
||||
#define HUB_CHAR_COMPOUND 0x0004 /* D2 */
|
||||
#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */
|
||||
#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */
|
||||
#define HUB_CHAR_PORTIND 0x0080 /* D7 */
|
||||
|
||||
struct usb_hub_status {
|
||||
__u16 wHubStatus;
|
||||
__u16 wHubChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* Hub Status & Hub Change bit masks
|
||||
* See USB 2.0 spec Table 11-19 and Table 11-20
|
||||
* Bits 0 and 1 for wHubStatus and wHubChange
|
||||
* Bits 2 to 15 are reserved for both
|
||||
*/
|
||||
#define HUB_STATUS_LOCAL_POWER 0x0001
|
||||
#define HUB_STATUS_OVERCURRENT 0x0002
|
||||
#define HUB_CHANGE_LOCAL_POWER 0x0001
|
||||
#define HUB_CHANGE_OVERCURRENT 0x0002
|
||||
|
||||
|
||||
/*
|
||||
* Hub descriptor
|
||||
* See USB 2.0 spec Table 11-13
|
||||
*/
|
||||
|
||||
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
||||
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||
|
||||
struct usb_hub_descriptor {
|
||||
__u8 bDescLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bNbrPorts;
|
||||
__u16 wHubCharacteristics;
|
||||
__u8 bPwrOn2PwrGood;
|
||||
__u8 bHubContrCurrent;
|
||||
/* add 1 bit for hub status change; round to bytes */
|
||||
__u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
__u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_device;
|
||||
|
||||
/*
|
||||
* As of USB 2.0, full/low speed devices are segregated into trees.
|
||||
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
|
||||
* The other type grows from high speed hubs when they connect to
|
||||
* full/low speed devices using "Transaction Translators" (TTs).
|
||||
*
|
||||
* TTs should only be known to the hub driver, and high speed bus
|
||||
* drivers (only EHCI for now). They affect periodic scheduling and
|
||||
* sometimes control/bulk error recovery.
|
||||
*/
|
||||
struct usb_tt {
|
||||
struct usb_device *hub; /* upstream highspeed hub */
|
||||
int multi; /* true means one TT per port */
|
||||
|
||||
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
|
||||
spinlock_t lock;
|
||||
struct list_head clear_list; /* of usb_tt_clear */
|
||||
struct work_struct kevent;
|
||||
};
|
||||
|
||||
struct usb_tt_clear {
|
||||
struct list_head clear_list;
|
||||
unsigned tt;
|
||||
u16 devinfo;
|
||||
};
|
||||
|
||||
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
|
||||
|
||||
struct usb_hub {
|
||||
struct usb_interface *intf; /* the "real" device */
|
||||
struct urb *urb; /* for interrupt polling pipe */
|
||||
|
||||
/* buffer for urb ... 1 bit each for hub and children, rounded up */
|
||||
char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
dma_addr_t buffer_dma; /* DMA address for buffer */
|
||||
union {
|
||||
struct usb_hub_status hub;
|
||||
struct usb_port_status port;
|
||||
} *status; /* buffer for status reports */
|
||||
|
||||
int error; /* last reported error */
|
||||
int nerrors; /* track consecutive errors */
|
||||
|
||||
struct list_head hub_list; /* all hubs */
|
||||
struct list_head event_list; /* hubs w/data or errs ready */
|
||||
|
||||
struct usb_hub_descriptor *descriptor; /* class descriptor */
|
||||
struct semaphore khubd_sem;
|
||||
struct usb_tt tt; /* Transaction Translator */
|
||||
};
|
||||
|
||||
#endif /* __LINUX_HUB_H */
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = usbcore
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -DDEBUG_MODE
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o \
|
||||
buffer_simple.o usb-debug.o ../sys/ros_wrapper.o \
|
||||
../sys/linuxwrapper.o usbcore.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
||||
# Automatic dependency tracking
|
||||
DEP_OBJECTS := $(TARGET_OBJECTS)
|
||||
include $(PATH_TO_TOP)/tools/depend.mk
|
||||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = usbcore
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -DDEBUG_MODE
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o \
|
||||
buffer_simple.o usb-debug.o ../sys/ros_wrapper.o \
|
||||
../sys/linuxwrapper.o usbcore.o
|
||||
|
||||
TARGET_LIBS = \
|
||||
$(PATH_TO_TOP)/dk/nkm/lib/libusbcore.a
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
||||
# Automatic dependency tracking
|
||||
DEP_OBJECTS := $(TARGET_OBJECTS)
|
||||
include $(PATH_TO_TOP)/tools/depend.mk
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
O_TARGET := message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o buffer_simple.o urb.o usb-debug.o
|
||||
|
||||
#O_TARGET := urb.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
||||
O_TARGET := message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o buffer_simple.o urb.o usb-debug.o
|
||||
|
||||
#O_TARGET := urb.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,398 +1,398 @@
|
|||
#include "../usb_wrapper.h"
|
||||
#include "hcd.h"
|
||||
|
||||
/**
|
||||
* usb_init_urb - initializes a urb so that it can be used by a USB driver
|
||||
* @urb: pointer to the urb to initialize
|
||||
*
|
||||
* Initializes a urb so that the USB subsystem can use it properly.
|
||||
*
|
||||
* If a urb is created with a call to usb_alloc_urb() it is not
|
||||
* necessary to call this function. Only use this if you allocate the
|
||||
* space for a struct urb on your own. If you call this function, be
|
||||
* careful when freeing the memory for your urb that it is no longer in
|
||||
* use by the USB core.
|
||||
*
|
||||
* Only use this function if you _really_ understand what you are doing.
|
||||
*/
|
||||
void STDCALL usb_init_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
memset(urb, 0, sizeof(*urb));
|
||||
urb->count = (atomic_t)ATOMIC_INIT(1);
|
||||
spin_lock_init(&urb->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_alloc_urb - creates a new urb for a USB driver to use
|
||||
* @iso_packets: number of iso packets for this urb
|
||||
* @mem_flags: the type of memory to allocate, see kmalloc() for a list of
|
||||
* valid options for this.
|
||||
*
|
||||
* Creates an urb for the USB driver to use, initializes a few internal
|
||||
* structures, incrementes the usage counter, and returns a pointer to it.
|
||||
*
|
||||
* If no memory is available, NULL is returned.
|
||||
*
|
||||
* If the driver want to use this urb for interrupt, control, or bulk
|
||||
* endpoints, pass '0' as the number of iso packets.
|
||||
*
|
||||
* The driver must call usb_free_urb() when it is finished with the urb.
|
||||
*/
|
||||
struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags)
|
||||
{
|
||||
struct urb *urb;
|
||||
|
||||
urb = (struct urb *)kmalloc(sizeof(struct urb) +
|
||||
iso_packets * sizeof(struct usb_iso_packet_descriptor),
|
||||
mem_flags);
|
||||
if (!urb) {
|
||||
err("alloc_urb: kmalloc failed");
|
||||
return NULL;
|
||||
}
|
||||
usb_init_urb(urb);
|
||||
return urb;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_free_urb - frees the memory used by a urb when all users of it are finished
|
||||
* @urb: pointer to the urb to free
|
||||
*
|
||||
* Must be called when a user of a urb is finished with it. When the last user
|
||||
* of the urb calls this function, the memory of the urb is freed.
|
||||
*
|
||||
* Note: The transfer buffer associated with the urb is not freed, that must be
|
||||
* done elsewhere.
|
||||
*/
|
||||
void STDCALL usb_free_urb(struct urb *urb)
|
||||
{
|
||||
if (urb)
|
||||
if (atomic_dec_and_test(&urb->count))
|
||||
{
|
||||
kfree(urb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_get_urb - increments the reference count of the urb
|
||||
* @urb: pointer to the urb to modify
|
||||
*
|
||||
* This must be called whenever a urb is transferred from a device driver to a
|
||||
* host controller driver. This allows proper reference counting to happen
|
||||
* for urbs.
|
||||
*
|
||||
* A pointer to the urb with the incremented reference counter is returned.
|
||||
*/
|
||||
struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
atomic_inc(&urb->count);
|
||||
return urb;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_submit_urb - issue an asynchronous transfer request for an endpoint
|
||||
* @urb: pointer to the urb describing the request
|
||||
* @mem_flags: the type of memory to allocate, see kmalloc() for a list
|
||||
* of valid options for this.
|
||||
*
|
||||
* This submits a transfer request, and transfers control of the URB
|
||||
* describing that request to the USB subsystem. Request completion will
|
||||
* be indicated later, asynchronously, by calling the completion handler.
|
||||
* The three types of completion are success, error, and unlink
|
||||
* (also called "request cancellation").
|
||||
* URBs may be submitted in interrupt context.
|
||||
*
|
||||
* The caller must have correctly initialized the URB before submitting
|
||||
* it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
|
||||
* available to ensure that most fields are correctly initialized, for
|
||||
* the particular kind of transfer, although they will not initialize
|
||||
* any transfer flags.
|
||||
*
|
||||
* Successful submissions return 0; otherwise this routine returns a
|
||||
* negative error number. If the submission is successful, the complete()
|
||||
* callback from the urb will be called exactly once, when the USB core and
|
||||
* host controller driver are finished with the urb. When the completion
|
||||
* function is called, control of the URB is returned to the device
|
||||
* driver which issued the request. The completion handler may then
|
||||
* immediately free or reuse that URB.
|
||||
*
|
||||
* For control endpoints, the synchronous usb_control_msg() call is
|
||||
* often used (in non-interrupt context) instead of this call.
|
||||
* That is often used through convenience wrappers, for the requests
|
||||
* that are standardized in the USB 2.0 specification. For bulk
|
||||
* endpoints, a synchronous usb_bulk_msg() call is available.
|
||||
*
|
||||
* Request Queuing:
|
||||
*
|
||||
* URBs may be submitted to endpoints before previous ones complete, to
|
||||
* minimize the impact of interrupt latencies and system overhead on data
|
||||
* throughput. This is required for continuous isochronous data streams,
|
||||
* and may also be required for some kinds of interrupt transfers. Such
|
||||
* queueing also maximizes bandwidth utilization by letting USB controllers
|
||||
* start work on later requests before driver software has finished the
|
||||
* completion processing for earlier requests.
|
||||
*
|
||||
* Bulk and Isochronous URBs may always be queued. At this writing, all
|
||||
* mainstream host controller drivers support queueing for control and
|
||||
* interrupt transfer requests.
|
||||
*
|
||||
* Reserved Bandwidth Transfers:
|
||||
*
|
||||
* Periodic transfers (interrupt or isochronous) are performed repeatedly,
|
||||
* using the interval specified in the urb. Submitting the first urb to
|
||||
* the endpoint reserves the bandwidth necessary to make those transfers.
|
||||
* If the USB subsystem can't allocate sufficient bandwidth to perform
|
||||
* the periodic request, submitting such a periodic request should fail.
|
||||
*
|
||||
* Device drivers must explicitly request that repetition, by ensuring that
|
||||
* some URB is always on the endpoint's queue (except possibly for short
|
||||
* periods during completion callacks). When there is no longer an urb
|
||||
* queued, the endpoint's bandwidth reservation is canceled. This means
|
||||
* drivers can use their completion handlers to ensure they keep bandwidth
|
||||
* they need, by reinitializing and resubmitting the just-completed urb
|
||||
* until the driver longer needs that periodic bandwidth.
|
||||
*
|
||||
* Memory Flags:
|
||||
*
|
||||
* The general rules for how to decide which mem_flags to use
|
||||
* are the same as for kmalloc. There are four
|
||||
* different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
|
||||
* GFP_ATOMIC.
|
||||
*
|
||||
* GFP_NOFS is not ever used, as it has not been implemented yet.
|
||||
*
|
||||
* GFP_ATOMIC is used when
|
||||
* (a) you are inside a completion handler, an interrupt, bottom half,
|
||||
* tasklet or timer, or
|
||||
* (b) you are holding a spinlock or rwlock (does not apply to
|
||||
* semaphores), or
|
||||
* (c) current->state != TASK_RUNNING, this is the case only after
|
||||
* you've changed it.
|
||||
*
|
||||
* GFP_NOIO is used in the block io path and error handling of storage
|
||||
* devices.
|
||||
*
|
||||
* All other situations use GFP_KERNEL.
|
||||
*
|
||||
* Some more specific rules for mem_flags can be inferred, such as
|
||||
* (1) start_xmit, timeout, and receive methods of network drivers must
|
||||
* use GFP_ATOMIC (they are called with a spinlock held);
|
||||
* (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also
|
||||
* called with a spinlock held);
|
||||
* (3) If you use a kernel thread with a network driver you must use
|
||||
* GFP_NOIO, unless (b) or (c) apply;
|
||||
* (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c)
|
||||
* apply or your are in a storage driver's block io path;
|
||||
* (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and
|
||||
* (6) changing firmware on a running storage or net device uses
|
||||
* GFP_NOIO, unless b) or c) apply
|
||||
*
|
||||
*/
|
||||
int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
{
|
||||
int pipe, temp, max;
|
||||
struct usb_device *dev;
|
||||
struct usb_operations *op;
|
||||
int is_out;
|
||||
// printk("sub dev %p bus %p num %i op %p sub %p\n",
|
||||
// urb->dev, urb->dev->bus,urb->dev->devnum,urb->dev->bus->op, urb->dev->bus->op->submit_urb);
|
||||
if (!urb || urb->hcpriv || !urb->complete)
|
||||
return -EINVAL;
|
||||
if (!(dev = urb->dev) ||
|
||||
(dev->state < USB_STATE_DEFAULT) ||
|
||||
(!dev->bus) || (dev->devnum <= 0))
|
||||
return -ENODEV;
|
||||
if (!(op = dev->bus->op) || !op->submit_urb)
|
||||
return -ENODEV;
|
||||
|
||||
urb->status = -EINPROGRESS;
|
||||
urb->actual_length = 0;
|
||||
urb->bandwidth = 0;
|
||||
|
||||
/* Lots of sanity checks, so HCDs can rely on clean data
|
||||
* and don't need to duplicate tests
|
||||
*/
|
||||
pipe = urb->pipe;
|
||||
temp = usb_pipetype (pipe);
|
||||
is_out = usb_pipeout (pipe);
|
||||
|
||||
if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
|
||||
return -ENODEV;
|
||||
|
||||
/* (actually HCDs may need to duplicate this, endpoint might yet
|
||||
* stall due to queued bulk/intr transactions that complete after
|
||||
* we check)
|
||||
*/
|
||||
if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
|
||||
return -EPIPE;
|
||||
|
||||
/* FIXME there should be a sharable lock protecting us against
|
||||
* config/altsetting changes and disconnects, kicking in here.
|
||||
* (here == before maxpacket, and eventually endpoint type,
|
||||
* checks get made.)
|
||||
*/
|
||||
|
||||
max = usb_maxpacket (dev, pipe, is_out);
|
||||
if (max <= 0) {
|
||||
dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)",
|
||||
__FUNCTION__,
|
||||
usb_pipeendpoint (pipe), is_out ? "OUT" : "IN",
|
||||
dev->bus->bus_name, dev->devpath,
|
||||
max);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* periodic transfers limit size per frame/uframe,
|
||||
* but drivers only control those sizes for ISO.
|
||||
* while we're checking, initialize return status.
|
||||
*/
|
||||
if (temp == PIPE_ISOCHRONOUS) {
|
||||
int n, len;
|
||||
|
||||
/* "high bandwidth" mode, 1-3 packets/uframe? */
|
||||
if (dev->speed == USB_SPEED_HIGH) {
|
||||
int mult = 1 + ((max >> 11) & 0x03);
|
||||
max &= 0x03ff;
|
||||
max *= mult;
|
||||
}
|
||||
|
||||
if (urb->number_of_packets <= 0)
|
||||
return -EINVAL;
|
||||
for (n = 0; n < urb->number_of_packets; n++) {
|
||||
len = urb->iso_frame_desc [n].length;
|
||||
if (len < 0 || len > max)
|
||||
return -EMSGSIZE;
|
||||
urb->iso_frame_desc [n].status = -EXDEV;
|
||||
urb->iso_frame_desc [n].actual_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* the I/O buffer must be mapped/unmapped, except when length=0 */
|
||||
if (urb->transfer_buffer_length < 0)
|
||||
return -EMSGSIZE;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* stuff that drivers shouldn't do, but which shouldn't
|
||||
* cause problems in HCDs if they get it wrong.
|
||||
*/
|
||||
{
|
||||
unsigned int orig_flags = urb->transfer_flags;
|
||||
unsigned int allowed;
|
||||
|
||||
/* enforce simple/standard policy */
|
||||
allowed = URB_ASYNC_UNLINK; // affects later unlinks
|
||||
allowed |= URB_NO_DMA_MAP;
|
||||
allowed |= URB_NO_INTERRUPT;
|
||||
switch (temp) {
|
||||
case PIPE_BULK:
|
||||
if (is_out)
|
||||
allowed |= URB_ZERO_PACKET;
|
||||
/* FALLTHROUGH */
|
||||
case PIPE_CONTROL:
|
||||
allowed |= URB_NO_FSBR; /* only affects UHCI */
|
||||
/* FALLTHROUGH */
|
||||
default: /* all non-iso endpoints */
|
||||
if (!is_out)
|
||||
allowed |= URB_SHORT_NOT_OK;
|
||||
break;
|
||||
case PIPE_ISOCHRONOUS:
|
||||
allowed |= URB_ISO_ASAP;
|
||||
break;
|
||||
}
|
||||
urb->transfer_flags &= allowed;
|
||||
|
||||
/* fail if submitter gave bogus flags */
|
||||
if (urb->transfer_flags != orig_flags) {
|
||||
err ("BOGUS urb flags, %x --> %x",
|
||||
orig_flags, urb->transfer_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Force periodic transfer intervals to be legal values that are
|
||||
* a power of two (so HCDs don't need to).
|
||||
*
|
||||
* FIXME want bus->{intr,iso}_sched_horizon values here. Each HC
|
||||
* supports different values... this uses EHCI/UHCI defaults (and
|
||||
* EHCI can use smaller non-default values).
|
||||
*/
|
||||
switch (temp) {
|
||||
case PIPE_ISOCHRONOUS:
|
||||
case PIPE_INTERRUPT:
|
||||
/* too small? */
|
||||
if (urb->interval <= 0)
|
||||
return -EINVAL;
|
||||
/* too big? */
|
||||
switch (dev->speed) {
|
||||
case USB_SPEED_HIGH: /* units are microframes */
|
||||
// NOTE usb handles 2^15
|
||||
if (urb->interval > (1024 * 8))
|
||||
urb->interval = 1024 * 8;
|
||||
temp = 1024 * 8;
|
||||
break;
|
||||
case USB_SPEED_FULL: /* units are frames/msec */
|
||||
case USB_SPEED_LOW:
|
||||
if (temp == PIPE_INTERRUPT) {
|
||||
if (urb->interval > 255)
|
||||
return -EINVAL;
|
||||
// NOTE ohci only handles up to 32
|
||||
temp = 128;
|
||||
} else {
|
||||
if (urb->interval > 1024)
|
||||
urb->interval = 1024;
|
||||
// NOTE usb and ohci handle up to 2^15
|
||||
temp = 1024;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
/* power of two? */
|
||||
while (temp > urb->interval)
|
||||
temp >>= 1;
|
||||
urb->interval = temp;
|
||||
}
|
||||
|
||||
return op->submit_urb (urb, mem_flags);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_unlink_urb - abort/cancel a transfer request for an endpoint
|
||||
* @urb: pointer to urb describing a previously submitted request
|
||||
*
|
||||
* This routine cancels an in-progress request. The requests's
|
||||
* completion handler will be called with a status code indicating
|
||||
* that the request has been canceled, and that control of the URB
|
||||
* has been returned to that device driver.
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this
|
||||
* request is synchronous. Success is indicated by returning zero,
|
||||
* at which time the urb will have been unlinked,
|
||||
* and the completion function will see status -ENOENT. Failure is
|
||||
* indicated by any other return value. This mode may not be used
|
||||
* when unlinking an urb from an interrupt context, such as a bottom
|
||||
* half or a completion handler,
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
|
||||
* request is asynchronous. Success is indicated by returning -EINPROGRESS,
|
||||
* at which time the urb will normally not have been unlinked,
|
||||
* and the completion function will see status -ECONNRESET. Failure is
|
||||
* indicated by any other return value.
|
||||
*/
|
||||
int STDCALL usb_unlink_urb(struct urb *urb)
|
||||
{
|
||||
if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
|
||||
return urb->dev->bus->op->unlink_urb(urb);
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
#include "../usb_wrapper.h"
|
||||
#include "hcd.h"
|
||||
|
||||
/**
|
||||
* usb_init_urb - initializes a urb so that it can be used by a USB driver
|
||||
* @urb: pointer to the urb to initialize
|
||||
*
|
||||
* Initializes a urb so that the USB subsystem can use it properly.
|
||||
*
|
||||
* If a urb is created with a call to usb_alloc_urb() it is not
|
||||
* necessary to call this function. Only use this if you allocate the
|
||||
* space for a struct urb on your own. If you call this function, be
|
||||
* careful when freeing the memory for your urb that it is no longer in
|
||||
* use by the USB core.
|
||||
*
|
||||
* Only use this function if you _really_ understand what you are doing.
|
||||
*/
|
||||
void STDCALL usb_init_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
memset(urb, 0, sizeof(*urb));
|
||||
urb->count = (atomic_t)ATOMIC_INIT(1);
|
||||
spin_lock_init(&urb->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_alloc_urb - creates a new urb for a USB driver to use
|
||||
* @iso_packets: number of iso packets for this urb
|
||||
* @mem_flags: the type of memory to allocate, see kmalloc() for a list of
|
||||
* valid options for this.
|
||||
*
|
||||
* Creates an urb for the USB driver to use, initializes a few internal
|
||||
* structures, incrementes the usage counter, and returns a pointer to it.
|
||||
*
|
||||
* If no memory is available, NULL is returned.
|
||||
*
|
||||
* If the driver want to use this urb for interrupt, control, or bulk
|
||||
* endpoints, pass '0' as the number of iso packets.
|
||||
*
|
||||
* The driver must call usb_free_urb() when it is finished with the urb.
|
||||
*/
|
||||
struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags)
|
||||
{
|
||||
struct urb *urb;
|
||||
|
||||
urb = (struct urb *)kmalloc(sizeof(struct urb) +
|
||||
iso_packets * sizeof(struct usb_iso_packet_descriptor),
|
||||
mem_flags);
|
||||
if (!urb) {
|
||||
err("alloc_urb: kmalloc failed");
|
||||
return NULL;
|
||||
}
|
||||
usb_init_urb(urb);
|
||||
return urb;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_free_urb - frees the memory used by a urb when all users of it are finished
|
||||
* @urb: pointer to the urb to free
|
||||
*
|
||||
* Must be called when a user of a urb is finished with it. When the last user
|
||||
* of the urb calls this function, the memory of the urb is freed.
|
||||
*
|
||||
* Note: The transfer buffer associated with the urb is not freed, that must be
|
||||
* done elsewhere.
|
||||
*/
|
||||
void STDCALL usb_free_urb(struct urb *urb)
|
||||
{
|
||||
if (urb)
|
||||
if (atomic_dec_and_test(&urb->count))
|
||||
{
|
||||
kfree(urb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_get_urb - increments the reference count of the urb
|
||||
* @urb: pointer to the urb to modify
|
||||
*
|
||||
* This must be called whenever a urb is transferred from a device driver to a
|
||||
* host controller driver. This allows proper reference counting to happen
|
||||
* for urbs.
|
||||
*
|
||||
* A pointer to the urb with the incremented reference counter is returned.
|
||||
*/
|
||||
struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
atomic_inc(&urb->count);
|
||||
return urb;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_submit_urb - issue an asynchronous transfer request for an endpoint
|
||||
* @urb: pointer to the urb describing the request
|
||||
* @mem_flags: the type of memory to allocate, see kmalloc() for a list
|
||||
* of valid options for this.
|
||||
*
|
||||
* This submits a transfer request, and transfers control of the URB
|
||||
* describing that request to the USB subsystem. Request completion will
|
||||
* be indicated later, asynchronously, by calling the completion handler.
|
||||
* The three types of completion are success, error, and unlink
|
||||
* (also called "request cancellation").
|
||||
* URBs may be submitted in interrupt context.
|
||||
*
|
||||
* The caller must have correctly initialized the URB before submitting
|
||||
* it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
|
||||
* available to ensure that most fields are correctly initialized, for
|
||||
* the particular kind of transfer, although they will not initialize
|
||||
* any transfer flags.
|
||||
*
|
||||
* Successful submissions return 0; otherwise this routine returns a
|
||||
* negative error number. If the submission is successful, the complete()
|
||||
* callback from the urb will be called exactly once, when the USB core and
|
||||
* host controller driver are finished with the urb. When the completion
|
||||
* function is called, control of the URB is returned to the device
|
||||
* driver which issued the request. The completion handler may then
|
||||
* immediately free or reuse that URB.
|
||||
*
|
||||
* For control endpoints, the synchronous usb_control_msg() call is
|
||||
* often used (in non-interrupt context) instead of this call.
|
||||
* That is often used through convenience wrappers, for the requests
|
||||
* that are standardized in the USB 2.0 specification. For bulk
|
||||
* endpoints, a synchronous usb_bulk_msg() call is available.
|
||||
*
|
||||
* Request Queuing:
|
||||
*
|
||||
* URBs may be submitted to endpoints before previous ones complete, to
|
||||
* minimize the impact of interrupt latencies and system overhead on data
|
||||
* throughput. This is required for continuous isochronous data streams,
|
||||
* and may also be required for some kinds of interrupt transfers. Such
|
||||
* queueing also maximizes bandwidth utilization by letting USB controllers
|
||||
* start work on later requests before driver software has finished the
|
||||
* completion processing for earlier requests.
|
||||
*
|
||||
* Bulk and Isochronous URBs may always be queued. At this writing, all
|
||||
* mainstream host controller drivers support queueing for control and
|
||||
* interrupt transfer requests.
|
||||
*
|
||||
* Reserved Bandwidth Transfers:
|
||||
*
|
||||
* Periodic transfers (interrupt or isochronous) are performed repeatedly,
|
||||
* using the interval specified in the urb. Submitting the first urb to
|
||||
* the endpoint reserves the bandwidth necessary to make those transfers.
|
||||
* If the USB subsystem can't allocate sufficient bandwidth to perform
|
||||
* the periodic request, submitting such a periodic request should fail.
|
||||
*
|
||||
* Device drivers must explicitly request that repetition, by ensuring that
|
||||
* some URB is always on the endpoint's queue (except possibly for short
|
||||
* periods during completion callacks). When there is no longer an urb
|
||||
* queued, the endpoint's bandwidth reservation is canceled. This means
|
||||
* drivers can use their completion handlers to ensure they keep bandwidth
|
||||
* they need, by reinitializing and resubmitting the just-completed urb
|
||||
* until the driver longer needs that periodic bandwidth.
|
||||
*
|
||||
* Memory Flags:
|
||||
*
|
||||
* The general rules for how to decide which mem_flags to use
|
||||
* are the same as for kmalloc. There are four
|
||||
* different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
|
||||
* GFP_ATOMIC.
|
||||
*
|
||||
* GFP_NOFS is not ever used, as it has not been implemented yet.
|
||||
*
|
||||
* GFP_ATOMIC is used when
|
||||
* (a) you are inside a completion handler, an interrupt, bottom half,
|
||||
* tasklet or timer, or
|
||||
* (b) you are holding a spinlock or rwlock (does not apply to
|
||||
* semaphores), or
|
||||
* (c) current->state != TASK_RUNNING, this is the case only after
|
||||
* you've changed it.
|
||||
*
|
||||
* GFP_NOIO is used in the block io path and error handling of storage
|
||||
* devices.
|
||||
*
|
||||
* All other situations use GFP_KERNEL.
|
||||
*
|
||||
* Some more specific rules for mem_flags can be inferred, such as
|
||||
* (1) start_xmit, timeout, and receive methods of network drivers must
|
||||
* use GFP_ATOMIC (they are called with a spinlock held);
|
||||
* (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also
|
||||
* called with a spinlock held);
|
||||
* (3) If you use a kernel thread with a network driver you must use
|
||||
* GFP_NOIO, unless (b) or (c) apply;
|
||||
* (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c)
|
||||
* apply or your are in a storage driver's block io path;
|
||||
* (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and
|
||||
* (6) changing firmware on a running storage or net device uses
|
||||
* GFP_NOIO, unless b) or c) apply
|
||||
*
|
||||
*/
|
||||
int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
{
|
||||
int pipe, temp, max;
|
||||
struct usb_device *dev;
|
||||
struct usb_operations *op;
|
||||
int is_out;
|
||||
// printk("sub dev %p bus %p num %i op %p sub %p\n",
|
||||
// urb->dev, urb->dev->bus,urb->dev->devnum,urb->dev->bus->op, urb->dev->bus->op->submit_urb);
|
||||
if (!urb || urb->hcpriv || !urb->complete)
|
||||
return -EINVAL;
|
||||
if (!(dev = urb->dev) ||
|
||||
(dev->state < USB_STATE_DEFAULT) ||
|
||||
(!dev->bus) || (dev->devnum <= 0))
|
||||
return -ENODEV;
|
||||
if (!(op = dev->bus->op) || !op->submit_urb)
|
||||
return -ENODEV;
|
||||
|
||||
urb->status = -EINPROGRESS;
|
||||
urb->actual_length = 0;
|
||||
urb->bandwidth = 0;
|
||||
|
||||
/* Lots of sanity checks, so HCDs can rely on clean data
|
||||
* and don't need to duplicate tests
|
||||
*/
|
||||
pipe = urb->pipe;
|
||||
temp = usb_pipetype (pipe);
|
||||
is_out = usb_pipeout (pipe);
|
||||
|
||||
if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
|
||||
return -ENODEV;
|
||||
|
||||
/* (actually HCDs may need to duplicate this, endpoint might yet
|
||||
* stall due to queued bulk/intr transactions that complete after
|
||||
* we check)
|
||||
*/
|
||||
if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
|
||||
return -EPIPE;
|
||||
|
||||
/* FIXME there should be a sharable lock protecting us against
|
||||
* config/altsetting changes and disconnects, kicking in here.
|
||||
* (here == before maxpacket, and eventually endpoint type,
|
||||
* checks get made.)
|
||||
*/
|
||||
|
||||
max = usb_maxpacket (dev, pipe, is_out);
|
||||
if (max <= 0) {
|
||||
dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)",
|
||||
__FUNCTION__,
|
||||
usb_pipeendpoint (pipe), is_out ? "OUT" : "IN",
|
||||
dev->bus->bus_name, dev->devpath,
|
||||
max);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* periodic transfers limit size per frame/uframe,
|
||||
* but drivers only control those sizes for ISO.
|
||||
* while we're checking, initialize return status.
|
||||
*/
|
||||
if (temp == PIPE_ISOCHRONOUS) {
|
||||
int n, len;
|
||||
|
||||
/* "high bandwidth" mode, 1-3 packets/uframe? */
|
||||
if (dev->speed == USB_SPEED_HIGH) {
|
||||
int mult = 1 + ((max >> 11) & 0x03);
|
||||
max &= 0x03ff;
|
||||
max *= mult;
|
||||
}
|
||||
|
||||
if (urb->number_of_packets <= 0)
|
||||
return -EINVAL;
|
||||
for (n = 0; n < urb->number_of_packets; n++) {
|
||||
len = urb->iso_frame_desc [n].length;
|
||||
if (len < 0 || len > max)
|
||||
return -EMSGSIZE;
|
||||
urb->iso_frame_desc [n].status = -EXDEV;
|
||||
urb->iso_frame_desc [n].actual_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* the I/O buffer must be mapped/unmapped, except when length=0 */
|
||||
if (urb->transfer_buffer_length < 0)
|
||||
return -EMSGSIZE;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* stuff that drivers shouldn't do, but which shouldn't
|
||||
* cause problems in HCDs if they get it wrong.
|
||||
*/
|
||||
{
|
||||
unsigned int orig_flags = urb->transfer_flags;
|
||||
unsigned int allowed;
|
||||
|
||||
/* enforce simple/standard policy */
|
||||
allowed = URB_ASYNC_UNLINK; // affects later unlinks
|
||||
allowed |= URB_NO_DMA_MAP;
|
||||
allowed |= URB_NO_INTERRUPT;
|
||||
switch (temp) {
|
||||
case PIPE_BULK:
|
||||
if (is_out)
|
||||
allowed |= URB_ZERO_PACKET;
|
||||
/* FALLTHROUGH */
|
||||
case PIPE_CONTROL:
|
||||
allowed |= URB_NO_FSBR; /* only affects UHCI */
|
||||
/* FALLTHROUGH */
|
||||
default: /* all non-iso endpoints */
|
||||
if (!is_out)
|
||||
allowed |= URB_SHORT_NOT_OK;
|
||||
break;
|
||||
case PIPE_ISOCHRONOUS:
|
||||
allowed |= URB_ISO_ASAP;
|
||||
break;
|
||||
}
|
||||
urb->transfer_flags &= allowed;
|
||||
|
||||
/* fail if submitter gave bogus flags */
|
||||
if (urb->transfer_flags != orig_flags) {
|
||||
err ("BOGUS urb flags, %x --> %x",
|
||||
orig_flags, urb->transfer_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Force periodic transfer intervals to be legal values that are
|
||||
* a power of two (so HCDs don't need to).
|
||||
*
|
||||
* FIXME want bus->{intr,iso}_sched_horizon values here. Each HC
|
||||
* supports different values... this uses EHCI/UHCI defaults (and
|
||||
* EHCI can use smaller non-default values).
|
||||
*/
|
||||
switch (temp) {
|
||||
case PIPE_ISOCHRONOUS:
|
||||
case PIPE_INTERRUPT:
|
||||
/* too small? */
|
||||
if (urb->interval <= 0)
|
||||
return -EINVAL;
|
||||
/* too big? */
|
||||
switch (dev->speed) {
|
||||
case USB_SPEED_HIGH: /* units are microframes */
|
||||
// NOTE usb handles 2^15
|
||||
if (urb->interval > (1024 * 8))
|
||||
urb->interval = 1024 * 8;
|
||||
temp = 1024 * 8;
|
||||
break;
|
||||
case USB_SPEED_FULL: /* units are frames/msec */
|
||||
case USB_SPEED_LOW:
|
||||
if (temp == PIPE_INTERRUPT) {
|
||||
if (urb->interval > 255)
|
||||
return -EINVAL;
|
||||
// NOTE ohci only handles up to 32
|
||||
temp = 128;
|
||||
} else {
|
||||
if (urb->interval > 1024)
|
||||
urb->interval = 1024;
|
||||
// NOTE usb and ohci handle up to 2^15
|
||||
temp = 1024;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
/* power of two? */
|
||||
while (temp > urb->interval)
|
||||
temp >>= 1;
|
||||
urb->interval = temp;
|
||||
}
|
||||
|
||||
return op->submit_urb (urb, mem_flags);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_unlink_urb - abort/cancel a transfer request for an endpoint
|
||||
* @urb: pointer to urb describing a previously submitted request
|
||||
*
|
||||
* This routine cancels an in-progress request. The requests's
|
||||
* completion handler will be called with a status code indicating
|
||||
* that the request has been canceled, and that control of the URB
|
||||
* has been returned to that device driver.
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this
|
||||
* request is synchronous. Success is indicated by returning zero,
|
||||
* at which time the urb will have been unlinked,
|
||||
* and the completion function will see status -ENOENT. Failure is
|
||||
* indicated by any other return value. This mode may not be used
|
||||
* when unlinking an urb from an interrupt context, such as a bottom
|
||||
* half or a completion handler,
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
|
||||
* request is asynchronous. Success is indicated by returning -EINPROGRESS,
|
||||
* at which time the urb will normally not have been unlinked,
|
||||
* and the completion function will see status -ECONNRESET. Failure is
|
||||
* indicated by any other return value.
|
||||
*/
|
||||
int STDCALL usb_unlink_urb(struct urb *urb)
|
||||
{
|
||||
if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
|
||||
return urb->dev->bus->op->unlink_urb(urb);
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -1,206 +1,206 @@
|
|||
/*
|
||||
* debug.c - USB debug helper routines.
|
||||
*
|
||||
* I just want these out of the way where they aren't in your
|
||||
* face, but so that you can still use them..
|
||||
*/
|
||||
#define CONFIG_USB_DEBUG
|
||||
#if 0
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#ifdef CONFIG_USB_DEBUG
|
||||
#define DEBUG
|
||||
#else
|
||||
#undef DEBUG
|
||||
#endif
|
||||
#include <linux/usb.h>
|
||||
#else
|
||||
#include "../usb_wrapper.h"
|
||||
#endif
|
||||
|
||||
static void usb_show_endpoint(struct usb_host_endpoint *endpoint)
|
||||
{
|
||||
usb_show_endpoint_descriptor(&endpoint->desc);
|
||||
}
|
||||
|
||||
static void usb_show_interface(struct usb_host_interface *altsetting)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_show_interface_descriptor(&altsetting->desc);
|
||||
|
||||
for (i = 0; i < altsetting->desc.bNumEndpoints; i++)
|
||||
usb_show_endpoint(altsetting->endpoint + i);
|
||||
}
|
||||
|
||||
static void usb_show_config(struct usb_host_config *config)
|
||||
{
|
||||
int i, j;
|
||||
struct usb_interface *ifp;
|
||||
|
||||
usb_show_config_descriptor(&config->desc);
|
||||
for (i = 0; i < config->desc.bNumInterfaces; i++) {
|
||||
ifp = config->interface + i;
|
||||
|
||||
if (!ifp)
|
||||
break;
|
||||
|
||||
printk("\n Interface: %d\n", i);
|
||||
for (j = 0; j < ifp->num_altsetting; j++)
|
||||
usb_show_interface(ifp->altsetting + j);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_device(struct usb_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_show_device_descriptor(&dev->descriptor);
|
||||
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
|
||||
usb_show_config(dev->config + i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and show the different USB descriptors.
|
||||
*/
|
||||
void usb_show_device_descriptor(struct usb_device_descriptor *desc)
|
||||
{
|
||||
if (!desc)
|
||||
{
|
||||
printk("Invalid USB device descriptor (NULL POINTER)\n");
|
||||
return;
|
||||
}
|
||||
printk(" Length = %2d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)");
|
||||
printk(" DescriptorType = %02x\n", desc->bDescriptorType);
|
||||
|
||||
printk(" USB version = %x.%02x\n",
|
||||
desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
|
||||
printk(" Vendor:Product = %04x:%04x\n",
|
||||
desc->idVendor, desc->idProduct);
|
||||
printk(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0);
|
||||
printk(" NumConfigurations = %d\n", desc->bNumConfigurations);
|
||||
printk(" Device version = %x.%02x\n",
|
||||
desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
|
||||
|
||||
printk(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
|
||||
desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
|
||||
switch (desc->bDeviceClass) {
|
||||
case 0:
|
||||
printk(" Per-interface classes\n");
|
||||
break;
|
||||
case USB_CLASS_AUDIO:
|
||||
printk(" Audio device class\n");
|
||||
break;
|
||||
case USB_CLASS_COMM:
|
||||
printk(" Communications class\n");
|
||||
break;
|
||||
case USB_CLASS_HID:
|
||||
printk(" Human Interface Devices class\n");
|
||||
break;
|
||||
case USB_CLASS_PRINTER:
|
||||
printk(" Printer device class\n");
|
||||
break;
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
printk(" Mass Storage device class\n");
|
||||
break;
|
||||
case USB_CLASS_HUB:
|
||||
printk(" Hub device class\n");
|
||||
break;
|
||||
case USB_CLASS_VENDOR_SPEC:
|
||||
printk(" Vendor class\n");
|
||||
break;
|
||||
default:
|
||||
printk(" Unknown class\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_config_descriptor(struct usb_config_descriptor *desc)
|
||||
{
|
||||
printk("Configuration:\n");
|
||||
printk(" bLength = %4d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)");
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" wTotalLength = %04x\n", desc->wTotalLength);
|
||||
printk(" bNumInterfaces = %02x\n", desc->bNumInterfaces);
|
||||
printk(" bConfigurationValue = %02x\n", desc->bConfigurationValue);
|
||||
printk(" iConfiguration = %02x\n", desc->iConfiguration);
|
||||
printk(" bmAttributes = %02x\n", desc->bmAttributes);
|
||||
printk(" bMaxPower = %4dmA\n", desc->bMaxPower * 2);
|
||||
}
|
||||
|
||||
void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
|
||||
{
|
||||
printk(" Alternate Setting: %2d\n", desc->bAlternateSetting);
|
||||
printk(" bLength = %4d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)");
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber);
|
||||
printk(" bAlternateSetting = %02x\n", desc->bAlternateSetting);
|
||||
printk(" bNumEndpoints = %02x\n", desc->bNumEndpoints);
|
||||
printk(" bInterface Class:SubClass:Protocol = %02x:%02x:%02x\n",
|
||||
desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol);
|
||||
printk(" iInterface = %02x\n", desc->iInterface);
|
||||
}
|
||||
|
||||
void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
|
||||
{
|
||||
char *LengthCommentString = (desc->bLength ==
|
||||
USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength ==
|
||||
USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)";
|
||||
char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
|
||||
|
||||
printk(" Endpoint:\n");
|
||||
printk(" bLength = %4d%s\n",
|
||||
desc->bLength, LengthCommentString);
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress,
|
||||
(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_CONTROL ? "i/o" :
|
||||
(desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out");
|
||||
printk(" bmAttributes = %02x (%s)\n", desc->bmAttributes,
|
||||
EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]);
|
||||
printk(" wMaxPacketSize = %04x\n", desc->wMaxPacketSize);
|
||||
printk(" bInterval = %02x\n", desc->bInterval);
|
||||
|
||||
/* Audio extensions to the endpoint descriptor */
|
||||
if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) {
|
||||
printk(" bRefresh = %02x\n", desc->bRefresh);
|
||||
printk(" bSynchAddress = %02x\n", desc->bSynchAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_string(struct usb_device *dev, char *id, int index)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if (!index)
|
||||
return;
|
||||
if (!(buf = kmalloc(256, GFP_KERNEL)))
|
||||
return;
|
||||
if (usb_string(dev, index, buf, 256) > 0)
|
||||
dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
void usb_dump_urb (struct urb *urb)
|
||||
{
|
||||
printk ("urb :%p\n", urb);
|
||||
printk ("dev :%p\n", urb->dev);
|
||||
printk ("pipe :%08X\n", urb->pipe);
|
||||
printk ("status :%d\n", urb->status);
|
||||
printk ("transfer_flags :%08X\n", urb->transfer_flags);
|
||||
printk ("transfer_buffer :%p\n", urb->transfer_buffer);
|
||||
printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
|
||||
printk ("actual_length :%d\n", urb->actual_length);
|
||||
printk ("setup_packet :%p\n", urb->setup_packet);
|
||||
printk ("start_frame :%d\n", urb->start_frame);
|
||||
printk ("number_of_packets :%d\n", urb->number_of_packets);
|
||||
printk ("interval :%d\n", urb->interval);
|
||||
printk ("error_count :%d\n", urb->error_count);
|
||||
printk ("context :%p\n", urb->context);
|
||||
printk ("complete :%p\n", urb->complete);
|
||||
}
|
||||
|
||||
/*
|
||||
* debug.c - USB debug helper routines.
|
||||
*
|
||||
* I just want these out of the way where they aren't in your
|
||||
* face, but so that you can still use them..
|
||||
*/
|
||||
#define CONFIG_USB_DEBUG
|
||||
#if 0
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#ifdef CONFIG_USB_DEBUG
|
||||
#define DEBUG
|
||||
#else
|
||||
#undef DEBUG
|
||||
#endif
|
||||
#include <linux/usb.h>
|
||||
#else
|
||||
#include "../usb_wrapper.h"
|
||||
#endif
|
||||
|
||||
static void usb_show_endpoint(struct usb_host_endpoint *endpoint)
|
||||
{
|
||||
usb_show_endpoint_descriptor(&endpoint->desc);
|
||||
}
|
||||
|
||||
static void usb_show_interface(struct usb_host_interface *altsetting)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_show_interface_descriptor(&altsetting->desc);
|
||||
|
||||
for (i = 0; i < altsetting->desc.bNumEndpoints; i++)
|
||||
usb_show_endpoint(altsetting->endpoint + i);
|
||||
}
|
||||
|
||||
static void usb_show_config(struct usb_host_config *config)
|
||||
{
|
||||
int i, j;
|
||||
struct usb_interface *ifp;
|
||||
|
||||
usb_show_config_descriptor(&config->desc);
|
||||
for (i = 0; i < config->desc.bNumInterfaces; i++) {
|
||||
ifp = config->interface + i;
|
||||
|
||||
if (!ifp)
|
||||
break;
|
||||
|
||||
printk("\n Interface: %d\n", i);
|
||||
for (j = 0; j < ifp->num_altsetting; j++)
|
||||
usb_show_interface(ifp->altsetting + j);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_device(struct usb_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_show_device_descriptor(&dev->descriptor);
|
||||
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
|
||||
usb_show_config(dev->config + i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and show the different USB descriptors.
|
||||
*/
|
||||
void usb_show_device_descriptor(struct usb_device_descriptor *desc)
|
||||
{
|
||||
if (!desc)
|
||||
{
|
||||
printk("Invalid USB device descriptor (NULL POINTER)\n");
|
||||
return;
|
||||
}
|
||||
printk(" Length = %2d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)");
|
||||
printk(" DescriptorType = %02x\n", desc->bDescriptorType);
|
||||
|
||||
printk(" USB version = %x.%02x\n",
|
||||
desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
|
||||
printk(" Vendor:Product = %04x:%04x\n",
|
||||
desc->idVendor, desc->idProduct);
|
||||
printk(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0);
|
||||
printk(" NumConfigurations = %d\n", desc->bNumConfigurations);
|
||||
printk(" Device version = %x.%02x\n",
|
||||
desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
|
||||
|
||||
printk(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
|
||||
desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
|
||||
switch (desc->bDeviceClass) {
|
||||
case 0:
|
||||
printk(" Per-interface classes\n");
|
||||
break;
|
||||
case USB_CLASS_AUDIO:
|
||||
printk(" Audio device class\n");
|
||||
break;
|
||||
case USB_CLASS_COMM:
|
||||
printk(" Communications class\n");
|
||||
break;
|
||||
case USB_CLASS_HID:
|
||||
printk(" Human Interface Devices class\n");
|
||||
break;
|
||||
case USB_CLASS_PRINTER:
|
||||
printk(" Printer device class\n");
|
||||
break;
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
printk(" Mass Storage device class\n");
|
||||
break;
|
||||
case USB_CLASS_HUB:
|
||||
printk(" Hub device class\n");
|
||||
break;
|
||||
case USB_CLASS_VENDOR_SPEC:
|
||||
printk(" Vendor class\n");
|
||||
break;
|
||||
default:
|
||||
printk(" Unknown class\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_config_descriptor(struct usb_config_descriptor *desc)
|
||||
{
|
||||
printk("Configuration:\n");
|
||||
printk(" bLength = %4d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)");
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" wTotalLength = %04x\n", desc->wTotalLength);
|
||||
printk(" bNumInterfaces = %02x\n", desc->bNumInterfaces);
|
||||
printk(" bConfigurationValue = %02x\n", desc->bConfigurationValue);
|
||||
printk(" iConfiguration = %02x\n", desc->iConfiguration);
|
||||
printk(" bmAttributes = %02x\n", desc->bmAttributes);
|
||||
printk(" bMaxPower = %4dmA\n", desc->bMaxPower * 2);
|
||||
}
|
||||
|
||||
void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
|
||||
{
|
||||
printk(" Alternate Setting: %2d\n", desc->bAlternateSetting);
|
||||
printk(" bLength = %4d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)");
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber);
|
||||
printk(" bAlternateSetting = %02x\n", desc->bAlternateSetting);
|
||||
printk(" bNumEndpoints = %02x\n", desc->bNumEndpoints);
|
||||
printk(" bInterface Class:SubClass:Protocol = %02x:%02x:%02x\n",
|
||||
desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol);
|
||||
printk(" iInterface = %02x\n", desc->iInterface);
|
||||
}
|
||||
|
||||
void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
|
||||
{
|
||||
char *LengthCommentString = (desc->bLength ==
|
||||
USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength ==
|
||||
USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)";
|
||||
char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
|
||||
|
||||
printk(" Endpoint:\n");
|
||||
printk(" bLength = %4d%s\n",
|
||||
desc->bLength, LengthCommentString);
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress,
|
||||
(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_CONTROL ? "i/o" :
|
||||
(desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out");
|
||||
printk(" bmAttributes = %02x (%s)\n", desc->bmAttributes,
|
||||
EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]);
|
||||
printk(" wMaxPacketSize = %04x\n", desc->wMaxPacketSize);
|
||||
printk(" bInterval = %02x\n", desc->bInterval);
|
||||
|
||||
/* Audio extensions to the endpoint descriptor */
|
||||
if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) {
|
||||
printk(" bRefresh = %02x\n", desc->bRefresh);
|
||||
printk(" bSynchAddress = %02x\n", desc->bSynchAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_string(struct usb_device *dev, char *id, int index)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if (!index)
|
||||
return;
|
||||
if (!(buf = kmalloc(256, GFP_KERNEL)))
|
||||
return;
|
||||
if (usb_string(dev, index, buf, 256) > 0)
|
||||
dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
void usb_dump_urb (struct urb *urb)
|
||||
{
|
||||
printk ("urb :%p\n", urb);
|
||||
printk ("dev :%p\n", urb->dev);
|
||||
printk ("pipe :%08X\n", urb->pipe);
|
||||
printk ("status :%d\n", urb->status);
|
||||
printk ("transfer_flags :%08X\n", urb->transfer_flags);
|
||||
printk ("transfer_buffer :%p\n", urb->transfer_buffer);
|
||||
printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
|
||||
printk ("actual_length :%d\n", urb->actual_length);
|
||||
printk ("setup_packet :%p\n", urb->setup_packet);
|
||||
printk ("start_frame :%d\n", urb->start_frame);
|
||||
printk ("number_of_packets :%d\n", urb->number_of_packets);
|
||||
printk ("interval :%d\n", urb->interval);
|
||||
printk ("error_count :%d\n", urb->error_count);
|
||||
printk ("context :%p\n", urb->context);
|
||||
printk ("complete :%p\n", urb->complete);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
/* Functions local to drivers/usb/core/ */
|
||||
|
||||
extern void usb_create_driverfs_dev_files (struct usb_device *dev);
|
||||
extern void usb_create_driverfs_intf_files (struct usb_interface *intf);
|
||||
|
||||
/* Functions local to drivers/usb/core/ */
|
||||
|
||||
extern void usb_create_driverfs_dev_files (struct usb_device *dev);
|
||||
extern void usb_create_driverfs_intf_files (struct usb_interface *intf);
|
||||
|
||||
|
|
|
@ -1,63 +1,67 @@
|
|||
/*
|
||||
ReactOS specific functions for usbcore module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
|
||||
NTSTATUS AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
|
||||
{
|
||||
DbgPrint("usbcore: AddDevice called\n");
|
||||
|
||||
/* we need to do kind of this stuff here (as usual)
|
||||
PDEVICE_OBJECT fdo;
|
||||
IoCreateDevice(..., &fdo);
|
||||
pdx->LowerDeviceObject =
|
||||
IoAttachDeviceToDeviceStack(fdo, pdo);*/
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
// nothing to do here yet
|
||||
}
|
||||
|
||||
// Dispatch PNP
|
||||
NTSTATUS DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)
|
||||
{
|
||||
ULONG fcn;
|
||||
PIO_STACK_LOCATION stack;
|
||||
|
||||
stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
fcn = stack->MinorFunction;
|
||||
DbgPrint("IRP_MJ_PNP, fcn=%d\n", fcn);
|
||||
|
||||
if (fcn == IRP_MN_REMOVE_DEVICE)
|
||||
{
|
||||
IoDeleteDevice(fdo);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||
{
|
||||
DbgPrint("IRP_MJ_POWER dispatch\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/*
|
||||
ReactOS specific functions for usbcore module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
|
||||
NTSTATUS STDCALL
|
||||
AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
|
||||
{
|
||||
DbgPrint("usbcore: AddDevice called\n");
|
||||
|
||||
/* we need to do kind of this stuff here (as usual)
|
||||
PDEVICE_OBJECT fdo;
|
||||
IoCreateDevice(..., &fdo);
|
||||
pdx->LowerDeviceObject =
|
||||
IoAttachDeviceToDeviceStack(fdo, pdo);*/
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID STDCALL
|
||||
DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
// nothing to do here yet
|
||||
}
|
||||
|
||||
// Dispatch PNP
|
||||
NTSTATUS STDCALL
|
||||
DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp)
|
||||
{
|
||||
ULONG fcn;
|
||||
PIO_STACK_LOCATION stack;
|
||||
|
||||
stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
fcn = stack->MinorFunction;
|
||||
DbgPrint("IRP_MJ_PNP, fcn=%d\n", fcn);
|
||||
|
||||
if (fcn == IRP_MN_REMOVE_DEVICE)
|
||||
{
|
||||
IoDeleteDevice(fdo);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||
{
|
||||
DbgPrint("IRP_MJ_POWER dispatch\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
;
|
||||
; Exports definition file for usbcore.sys
|
||||
;
|
||||
EXPORTS
|
||||
usb_init@0
|
||||
usb_exit@0
|
||||
usb_init_urb@4
|
||||
usb_alloc_urb@8
|
||||
usb_free_urb@4
|
||||
usb_get_urb@4
|
||||
usb_get_dev@4
|
||||
usb_submit_urb@8
|
||||
usb_unlink_urb@4
|
||||
usb_bus_init@4
|
||||
usb_alloc_bus@4
|
||||
usb_free_bus@4
|
||||
usb_register_bus@4
|
||||
usb_deregister_bus@4
|
||||
usb_register_root_hub@8
|
||||
usb_calc_bus_time@16
|
||||
usb_check_bandwidth@8
|
||||
usb_claim_bandwidth@16
|
||||
usb_release_bandwidth@12
|
||||
usb_hcd_giveback_urb@12
|
||||
;usb_hcd_irq@12
|
||||
usb_hc_died@4
|
||||
usb_alloc_dev@8
|
||||
usb_connect@4
|
||||
usb_put_dev@4
|
||||
usb_disabled@0
|
||||
usb_hcd_pci_probe@8
|
||||
;
|
||||
; Exports definition file for usbcore.sys
|
||||
;
|
||||
EXPORTS
|
||||
usb_init@0
|
||||
usb_exit@0
|
||||
usb_init_urb@4
|
||||
usb_alloc_urb@8
|
||||
usb_free_urb@4
|
||||
usb_get_urb@4
|
||||
usb_get_dev@4
|
||||
usb_submit_urb@8
|
||||
usb_unlink_urb@4
|
||||
usb_bus_init@4
|
||||
usb_alloc_bus@4
|
||||
usb_free_bus@4
|
||||
usb_register_bus@4
|
||||
usb_deregister_bus@4
|
||||
usb_register_root_hub@8
|
||||
usb_calc_bus_time@16
|
||||
usb_check_bandwidth@8
|
||||
usb_claim_bandwidth@16
|
||||
usb_release_bandwidth@12
|
||||
usb_hcd_giveback_urb@12
|
||||
;usb_hcd_irq@12
|
||||
usb_hc_died@4
|
||||
usb_alloc_dev@8
|
||||
usb_connect@4
|
||||
usb_put_dev@4
|
||||
usb_disabled@0
|
||||
usb_hcd_pci_probe@8
|
||||
usb_hcd_pci_remove@4
|
|
@ -1,5 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB Core Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "usbcore\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "usbcore.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB Core Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "usbcore\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "usbcore.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = ohci
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a usbcore.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -DDEBUG_MODE
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
ohci-hcd.o ohci_main.o ../sys/ros_wrapper.o ../sys/linuxwrapper.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
||||
# Automatic dependency tracking
|
||||
DEP_OBJECTS := $(TARGET_OBJECTS)
|
||||
include $(PATH_TO_TOP)/tools/depend.mk
|
||||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = ohci
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a usbcore.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -DDEBUG_MODE
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
ohci-hcd.o ohci_main.o ../sys/ros_wrapper.o ../sys/linuxwrapper.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
||||
# Automatic dependency tracking
|
||||
DEP_OBJECTS := $(TARGET_OBJECTS)
|
||||
include $(PATH_TO_TOP)/tools/depend.mk
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
O_TARGET := ohci-hcd.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
O_TARGET := ohci-hcd.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,271 +1,271 @@
|
|||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under GPL
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* OHCI Root Hub ... the nonsharable stuff
|
||||
*
|
||||
* Registers don't need cpu_to_le32, that happens transparently
|
||||
*/
|
||||
|
||||
/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
|
||||
* The erratum (#4) description is incorrect. AMD's workaround waits
|
||||
* till some bits (mostly reserved) are clear; ok for all revs.
|
||||
*/
|
||||
#define read_roothub(hc, register, mask) ({ \
|
||||
u32 temp = readl (&hc->regs->roothub.register); \
|
||||
if (temp == -1) \
|
||||
disable (hc); \
|
||||
else if (hc->flags & OHCI_QUIRK_AMD756) \
|
||||
while (temp & mask) \
|
||||
temp = readl (&hc->regs->roothub.register); \
|
||||
temp; })
|
||||
|
||||
static u32 roothub_a (struct ohci_hcd *hc)
|
||||
{ return read_roothub (hc, a, 0xfc0fe000); }
|
||||
static inline u32 roothub_b (struct ohci_hcd *hc)
|
||||
{ return readl (&hc->regs->roothub.b); }
|
||||
static inline u32 roothub_status (struct ohci_hcd *hc)
|
||||
{ return readl (&hc->regs->roothub.status); }
|
||||
static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
|
||||
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define dbg_port(hc,label,num,value) \
|
||||
ohci_dbg (hc, \
|
||||
"%s roothub.portstatus [%d] " \
|
||||
"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
|
||||
label, num, temp, \
|
||||
(temp & RH_PS_PRSC) ? " PRSC" : "", \
|
||||
(temp & RH_PS_OCIC) ? " OCIC" : "", \
|
||||
(temp & RH_PS_PSSC) ? " PSSC" : "", \
|
||||
(temp & RH_PS_PESC) ? " PESC" : "", \
|
||||
(temp & RH_PS_CSC) ? " CSC" : "", \
|
||||
\
|
||||
(temp & RH_PS_LSDA) ? " LSDA" : "", \
|
||||
(temp & RH_PS_PPS) ? " PPS" : "", \
|
||||
(temp & RH_PS_PRS) ? " PRS" : "", \
|
||||
(temp & RH_PS_POCI) ? " POCI" : "", \
|
||||
(temp & RH_PS_PSS) ? " PSS" : "", \
|
||||
\
|
||||
(temp & RH_PS_PES) ? " PES" : "", \
|
||||
(temp & RH_PS_CCS) ? " CCS" : "" \
|
||||
);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* build "status change" packet (one or two bytes) from HC registers */
|
||||
|
||||
static int
|
||||
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ports, i, changed = 0, length = 1;
|
||||
|
||||
ports = roothub_a (ohci) & RH_A_NDP;
|
||||
if (ports > MAX_ROOT_PORTS) {
|
||||
if (ohci->disabled)
|
||||
return -ESHUTDOWN;
|
||||
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
|
||||
ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
|
||||
/* retry later; "should not happen" */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init status */
|
||||
if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
|
||||
buf [0] = changed = 1;
|
||||
else
|
||||
buf [0] = 0;
|
||||
if (ports > 7) {
|
||||
buf [1] = 0;
|
||||
length++;
|
||||
}
|
||||
|
||||
/* look at each port */
|
||||
for (i = 0; i < ports; i++) {
|
||||
u32 status = roothub_portstatus (ohci, i);
|
||||
|
||||
status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
|
||||
| RH_PS_OCIC | RH_PS_PRSC;
|
||||
if (status) {
|
||||
changed = 1;
|
||||
if (i < 7)
|
||||
buf [0] |= 1 << (i + 1);
|
||||
else
|
||||
buf [1] |= 1 << (i - 7);
|
||||
}
|
||||
}
|
||||
return changed ? length : 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
ohci_hub_descriptor (
|
||||
struct ohci_hcd *ohci,
|
||||
struct usb_hub_descriptor *desc
|
||||
) {
|
||||
u32 rh = roothub_a (ohci);
|
||||
int ports = rh & RH_A_NDP;
|
||||
u16 temp;
|
||||
|
||||
desc->bDescriptorType = 0x29;
|
||||
desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
|
||||
desc->bHubContrCurrent = 0;
|
||||
|
||||
desc->bNbrPorts = ports;
|
||||
temp = 1 + (ports / 8);
|
||||
desc->bDescLength = 7 + 2 * temp;
|
||||
|
||||
temp = 0;
|
||||
if (rh & RH_A_PSM) /* per-port power switching? */
|
||||
temp |= 0x0001;
|
||||
if (rh & RH_A_NOCP) /* no overcurrent reporting? */
|
||||
temp |= 0x0010;
|
||||
else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */
|
||||
temp |= 0x0008;
|
||||
desc->wHubCharacteristics = cpu_to_le16 (temp);
|
||||
|
||||
/* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
|
||||
rh = roothub_b (ohci);
|
||||
desc->bitmap [0] = rh & RH_B_DR;
|
||||
if (ports > 7) {
|
||||
desc->bitmap [1] = (rh & RH_B_DR) >> 8;
|
||||
desc->bitmap [2] = desc->bitmap [3] = 0xff;
|
||||
} else
|
||||
desc->bitmap [1] = 0xff;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_hub_control (
|
||||
struct usb_hcd *hcd,
|
||||
u16 typeReq,
|
||||
u16 wValue,
|
||||
u16 wIndex,
|
||||
char *buf,
|
||||
u16 wLength
|
||||
) {
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ports = hcd_to_bus (hcd)->root_hub->maxchild;
|
||||
u32 temp;
|
||||
int retval = 0;
|
||||
|
||||
switch (typeReq) {
|
||||
case ClearHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
writel (RH_HS_OCIC, &ohci->regs->roothub.status);
|
||||
case C_HUB_LOCAL_POWER:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case ClearPortFeature:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_ENABLE:
|
||||
temp = RH_PS_CCS;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
temp = RH_PS_PESC;
|
||||
break;
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
temp = RH_PS_POCI;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_SUSPEND:
|
||||
temp = RH_PS_PSSC;
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
temp = RH_PS_LSDA;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
temp = RH_PS_CSC;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_OVER_CURRENT:
|
||||
temp = RH_PS_OCIC;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
temp = RH_PS_PRSC;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
|
||||
// readl (&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case GetHubDescriptor:
|
||||
ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
|
||||
break;
|
||||
case GetHubStatus:
|
||||
temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
|
||||
*(u32 *) buf = cpu_to_le32 (temp);
|
||||
break;
|
||||
case GetPortStatus:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
temp = roothub_portstatus (ohci, wIndex);
|
||||
*(u32 *) buf = cpu_to_le32 (temp);
|
||||
|
||||
#ifndef OHCI_VERBOSE_DEBUG
|
||||
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
|
||||
#endif
|
||||
dbg_port (ohci, "GetStatus", wIndex + 1, temp);
|
||||
break;
|
||||
case SetHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
// FIXME: this can be cleared, yes?
|
||||
case C_HUB_LOCAL_POWER:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SetPortFeature:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
writel (RH_PS_PSS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
writel (RH_PS_PPS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case USB_PORT_FEAT_RESET:
|
||||
temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
|
||||
if (temp & RH_PS_CCS)
|
||||
writel (RH_PS_PRS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error:
|
||||
/* "protocol stall" on error */
|
||||
retval = -EPIPE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under GPL
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* OHCI Root Hub ... the nonsharable stuff
|
||||
*
|
||||
* Registers don't need cpu_to_le32, that happens transparently
|
||||
*/
|
||||
|
||||
/* AMD-756 (D2 rev) reports corrupt register contents in some cases.
|
||||
* The erratum (#4) description is incorrect. AMD's workaround waits
|
||||
* till some bits (mostly reserved) are clear; ok for all revs.
|
||||
*/
|
||||
#define read_roothub(hc, register, mask) ({ \
|
||||
u32 temp = readl (&hc->regs->roothub.register); \
|
||||
if (temp == -1) \
|
||||
disable (hc); \
|
||||
else if (hc->flags & OHCI_QUIRK_AMD756) \
|
||||
while (temp & mask) \
|
||||
temp = readl (&hc->regs->roothub.register); \
|
||||
temp; })
|
||||
|
||||
static u32 roothub_a (struct ohci_hcd *hc)
|
||||
{ return read_roothub (hc, a, 0xfc0fe000); }
|
||||
static inline u32 roothub_b (struct ohci_hcd *hc)
|
||||
{ return readl (&hc->regs->roothub.b); }
|
||||
static inline u32 roothub_status (struct ohci_hcd *hc)
|
||||
{ return readl (&hc->regs->roothub.status); }
|
||||
static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
|
||||
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define dbg_port(hc,label,num,value) \
|
||||
ohci_dbg (hc, \
|
||||
"%s roothub.portstatus [%d] " \
|
||||
"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
|
||||
label, num, temp, \
|
||||
(temp & RH_PS_PRSC) ? " PRSC" : "", \
|
||||
(temp & RH_PS_OCIC) ? " OCIC" : "", \
|
||||
(temp & RH_PS_PSSC) ? " PSSC" : "", \
|
||||
(temp & RH_PS_PESC) ? " PESC" : "", \
|
||||
(temp & RH_PS_CSC) ? " CSC" : "", \
|
||||
\
|
||||
(temp & RH_PS_LSDA) ? " LSDA" : "", \
|
||||
(temp & RH_PS_PPS) ? " PPS" : "", \
|
||||
(temp & RH_PS_PRS) ? " PRS" : "", \
|
||||
(temp & RH_PS_POCI) ? " POCI" : "", \
|
||||
(temp & RH_PS_PSS) ? " PSS" : "", \
|
||||
\
|
||||
(temp & RH_PS_PES) ? " PES" : "", \
|
||||
(temp & RH_PS_CCS) ? " CCS" : "" \
|
||||
);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* build "status change" packet (one or two bytes) from HC registers */
|
||||
|
||||
static int
|
||||
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ports, i, changed = 0, length = 1;
|
||||
|
||||
ports = roothub_a (ohci) & RH_A_NDP;
|
||||
if (ports > MAX_ROOT_PORTS) {
|
||||
if (ohci->disabled)
|
||||
return -ESHUTDOWN;
|
||||
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
|
||||
ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
|
||||
/* retry later; "should not happen" */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init status */
|
||||
if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
|
||||
buf [0] = changed = 1;
|
||||
else
|
||||
buf [0] = 0;
|
||||
if (ports > 7) {
|
||||
buf [1] = 0;
|
||||
length++;
|
||||
}
|
||||
|
||||
/* look at each port */
|
||||
for (i = 0; i < ports; i++) {
|
||||
u32 status = roothub_portstatus (ohci, i);
|
||||
|
||||
status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
|
||||
| RH_PS_OCIC | RH_PS_PRSC;
|
||||
if (status) {
|
||||
changed = 1;
|
||||
if (i < 7)
|
||||
buf [0] |= 1 << (i + 1);
|
||||
else
|
||||
buf [1] |= 1 << (i - 7);
|
||||
}
|
||||
}
|
||||
return changed ? length : 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
ohci_hub_descriptor (
|
||||
struct ohci_hcd *ohci,
|
||||
struct usb_hub_descriptor *desc
|
||||
) {
|
||||
u32 rh = roothub_a (ohci);
|
||||
int ports = rh & RH_A_NDP;
|
||||
u16 temp;
|
||||
|
||||
desc->bDescriptorType = 0x29;
|
||||
desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
|
||||
desc->bHubContrCurrent = 0;
|
||||
|
||||
desc->bNbrPorts = ports;
|
||||
temp = 1 + (ports / 8);
|
||||
desc->bDescLength = 7 + 2 * temp;
|
||||
|
||||
temp = 0;
|
||||
if (rh & RH_A_PSM) /* per-port power switching? */
|
||||
temp |= 0x0001;
|
||||
if (rh & RH_A_NOCP) /* no overcurrent reporting? */
|
||||
temp |= 0x0010;
|
||||
else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */
|
||||
temp |= 0x0008;
|
||||
desc->wHubCharacteristics = cpu_to_le16 (temp);
|
||||
|
||||
/* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
|
||||
rh = roothub_b (ohci);
|
||||
desc->bitmap [0] = rh & RH_B_DR;
|
||||
if (ports > 7) {
|
||||
desc->bitmap [1] = (rh & RH_B_DR) >> 8;
|
||||
desc->bitmap [2] = desc->bitmap [3] = 0xff;
|
||||
} else
|
||||
desc->bitmap [1] = 0xff;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_hub_control (
|
||||
struct usb_hcd *hcd,
|
||||
u16 typeReq,
|
||||
u16 wValue,
|
||||
u16 wIndex,
|
||||
char *buf,
|
||||
u16 wLength
|
||||
) {
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ports = hcd_to_bus (hcd)->root_hub->maxchild;
|
||||
u32 temp;
|
||||
int retval = 0;
|
||||
|
||||
switch (typeReq) {
|
||||
case ClearHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
writel (RH_HS_OCIC, &ohci->regs->roothub.status);
|
||||
case C_HUB_LOCAL_POWER:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case ClearPortFeature:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_ENABLE:
|
||||
temp = RH_PS_CCS;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
temp = RH_PS_PESC;
|
||||
break;
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
temp = RH_PS_POCI;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_SUSPEND:
|
||||
temp = RH_PS_PSSC;
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
temp = RH_PS_LSDA;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
temp = RH_PS_CSC;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_OVER_CURRENT:
|
||||
temp = RH_PS_OCIC;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
temp = RH_PS_PRSC;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
|
||||
// readl (&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case GetHubDescriptor:
|
||||
ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
|
||||
break;
|
||||
case GetHubStatus:
|
||||
temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
|
||||
*(u32 *) buf = cpu_to_le32 (temp);
|
||||
break;
|
||||
case GetPortStatus:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
temp = roothub_portstatus (ohci, wIndex);
|
||||
*(u32 *) buf = cpu_to_le32 (temp);
|
||||
|
||||
#ifndef OHCI_VERBOSE_DEBUG
|
||||
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
|
||||
#endif
|
||||
dbg_port (ohci, "GetStatus", wIndex + 1, temp);
|
||||
break;
|
||||
case SetHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
// FIXME: this can be cleared, yes?
|
||||
case C_HUB_LOCAL_POWER:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SetPortFeature:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
writel (RH_PS_PSS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
writel (RH_PS_PPS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case USB_PORT_FEAT_RESET:
|
||||
temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
|
||||
if (temp & RH_PS_CCS)
|
||||
writel (RH_PS_PRS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error:
|
||||
/* "protocol stall" on error */
|
||||
retval = -EPIPE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,146 +1,146 @@
|
|||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* There's basically three types of memory:
|
||||
* - data used only by the HCD ... kmalloc is fine
|
||||
* - async and periodic schedules, shared by HC and HCD ... these
|
||||
* need to use pci_pool or pci_alloc_consistent
|
||||
* - driver buffers, read/written by HC ... the hcd glue or the
|
||||
* device driver provides us with dma addresses
|
||||
*
|
||||
* There's also PCI "register" data, which is memory mapped.
|
||||
* No memory seen by this driver is pagable.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct usb_hcd *ohci_hcd_alloc (void)
|
||||
{
|
||||
struct ohci_hcd *ohci;
|
||||
|
||||
ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL);
|
||||
if (ohci != 0) {
|
||||
memset (ohci, 0, sizeof (struct ohci_hcd));
|
||||
return &ohci->hcd;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ohci_hcd_free (struct usb_hcd *hcd)
|
||||
{
|
||||
kfree (hcd_to_ohci (hcd));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_mem_init (struct ohci_hcd *ohci)
|
||||
{
|
||||
ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
|
||||
sizeof (struct td),
|
||||
32 /* byte alignment */,
|
||||
0 /* no page-crossing issues */);
|
||||
if (!ohci->td_cache)
|
||||
return -ENOMEM;
|
||||
ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev,
|
||||
sizeof (struct ed),
|
||||
16 /* byte alignment */,
|
||||
0 /* no page-crossing issues */);
|
||||
if (!ohci->ed_cache) {
|
||||
pci_pool_destroy (ohci->td_cache);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ohci_mem_cleanup (struct ohci_hcd *ohci)
|
||||
{
|
||||
if (ohci->td_cache) {
|
||||
pci_pool_destroy (ohci->td_cache);
|
||||
ohci->td_cache = 0;
|
||||
}
|
||||
if (ohci->ed_cache) {
|
||||
pci_pool_destroy (ohci->ed_cache);
|
||||
ohci->ed_cache = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* ohci "done list" processing needs this mapping */
|
||||
static inline struct td *
|
||||
dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
|
||||
{
|
||||
struct td *td;
|
||||
|
||||
td_dma &= TD_MASK;
|
||||
td = hc->td_hash [TD_HASH_FUNC(td_dma)];
|
||||
while (td && td->td_dma != td_dma)
|
||||
td = td->td_hash;
|
||||
return td;
|
||||
}
|
||||
|
||||
/* TDs ... */
|
||||
static struct td *
|
||||
td_alloc (struct ohci_hcd *hc, int mem_flags)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
struct td *td;
|
||||
|
||||
td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
|
||||
if (td) {
|
||||
/* in case hc fetches it, make it look dead */
|
||||
memset (td, 0, sizeof *td);
|
||||
td->hwNextTD = cpu_to_le32 (dma);
|
||||
td->td_dma = dma;
|
||||
/* hashed in td_fill */
|
||||
}
|
||||
return td;
|
||||
}
|
||||
|
||||
static void
|
||||
td_free (struct ohci_hcd *hc, struct td *td)
|
||||
{
|
||||
struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
|
||||
|
||||
while (*prev && *prev != td)
|
||||
prev = &(*prev)->td_hash;
|
||||
if (*prev)
|
||||
*prev = td->td_hash;
|
||||
else if ((td->hwINFO & TD_DONE) != 0)
|
||||
ohci_dbg (hc, "no hash for td %p\n", td);
|
||||
pci_pool_free (hc->td_cache, td, td->td_dma);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* EDs ... */
|
||||
static struct ed *
|
||||
ed_alloc (struct ohci_hcd *hc, int mem_flags)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
struct ed *ed;
|
||||
|
||||
ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma);
|
||||
if (ed) {
|
||||
memset (ed, 0, sizeof (*ed));
|
||||
INIT_LIST_HEAD (&ed->td_list);
|
||||
ed->dma = dma;
|
||||
}
|
||||
return ed;
|
||||
}
|
||||
|
||||
static void
|
||||
ed_free (struct ohci_hcd *hc, struct ed *ed)
|
||||
{
|
||||
pci_pool_free (hc->ed_cache, ed, ed->dma);
|
||||
}
|
||||
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* There's basically three types of memory:
|
||||
* - data used only by the HCD ... kmalloc is fine
|
||||
* - async and periodic schedules, shared by HC and HCD ... these
|
||||
* need to use pci_pool or pci_alloc_consistent
|
||||
* - driver buffers, read/written by HC ... the hcd glue or the
|
||||
* device driver provides us with dma addresses
|
||||
*
|
||||
* There's also PCI "register" data, which is memory mapped.
|
||||
* No memory seen by this driver is pagable.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct usb_hcd *ohci_hcd_alloc (void)
|
||||
{
|
||||
struct ohci_hcd *ohci;
|
||||
|
||||
ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL);
|
||||
if (ohci != 0) {
|
||||
memset (ohci, 0, sizeof (struct ohci_hcd));
|
||||
return &ohci->hcd;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ohci_hcd_free (struct usb_hcd *hcd)
|
||||
{
|
||||
kfree (hcd_to_ohci (hcd));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_mem_init (struct ohci_hcd *ohci)
|
||||
{
|
||||
ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
|
||||
sizeof (struct td),
|
||||
32 /* byte alignment */,
|
||||
0 /* no page-crossing issues */);
|
||||
if (!ohci->td_cache)
|
||||
return -ENOMEM;
|
||||
ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev,
|
||||
sizeof (struct ed),
|
||||
16 /* byte alignment */,
|
||||
0 /* no page-crossing issues */);
|
||||
if (!ohci->ed_cache) {
|
||||
pci_pool_destroy (ohci->td_cache);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ohci_mem_cleanup (struct ohci_hcd *ohci)
|
||||
{
|
||||
if (ohci->td_cache) {
|
||||
pci_pool_destroy (ohci->td_cache);
|
||||
ohci->td_cache = 0;
|
||||
}
|
||||
if (ohci->ed_cache) {
|
||||
pci_pool_destroy (ohci->ed_cache);
|
||||
ohci->ed_cache = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* ohci "done list" processing needs this mapping */
|
||||
static inline struct td *
|
||||
dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
|
||||
{
|
||||
struct td *td;
|
||||
|
||||
td_dma &= TD_MASK;
|
||||
td = hc->td_hash [TD_HASH_FUNC(td_dma)];
|
||||
while (td && td->td_dma != td_dma)
|
||||
td = td->td_hash;
|
||||
return td;
|
||||
}
|
||||
|
||||
/* TDs ... */
|
||||
static struct td *
|
||||
td_alloc (struct ohci_hcd *hc, int mem_flags)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
struct td *td;
|
||||
|
||||
td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
|
||||
if (td) {
|
||||
/* in case hc fetches it, make it look dead */
|
||||
memset (td, 0, sizeof *td);
|
||||
td->hwNextTD = cpu_to_le32 (dma);
|
||||
td->td_dma = dma;
|
||||
/* hashed in td_fill */
|
||||
}
|
||||
return td;
|
||||
}
|
||||
|
||||
static void
|
||||
td_free (struct ohci_hcd *hc, struct td *td)
|
||||
{
|
||||
struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
|
||||
|
||||
while (*prev && *prev != td)
|
||||
prev = &(*prev)->td_hash;
|
||||
if (*prev)
|
||||
*prev = td->td_hash;
|
||||
else if ((td->hwINFO & TD_DONE) != 0)
|
||||
ohci_dbg (hc, "no hash for td %p\n", td);
|
||||
pci_pool_free (hc->td_cache, td, td->td_dma);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* EDs ... */
|
||||
static struct ed *
|
||||
ed_alloc (struct ohci_hcd *hc, int mem_flags)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
struct ed *ed;
|
||||
|
||||
ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma);
|
||||
if (ed) {
|
||||
memset (ed, 0, sizeof (*ed));
|
||||
INIT_LIST_HEAD (&ed->td_list);
|
||||
ed->dma = dma;
|
||||
}
|
||||
return ed;
|
||||
}
|
||||
|
||||
static void
|
||||
ed_free (struct ohci_hcd *hc, struct ed *ed)
|
||||
{
|
||||
pci_pool_free (hc->ed_cache, ed, ed->dma);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,412 +1,412 @@
|
|||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* [ Initialisation is based on Linus' ]
|
||||
* [ uhci code and gregs ohci fragments ]
|
||||
* [ (C) Copyright 1999 Linus Torvalds ]
|
||||
* [ (C) Copyright 1999 Gregory P. Smith]
|
||||
*
|
||||
* PCI Bus Glue
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/prom.h>
|
||||
#ifndef CONFIG_PM
|
||||
# define CONFIG_PM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PCI
|
||||
#error "This file is PCI bus glue. CONFIG_PCI must be defined."
|
||||
#endif
|
||||
|
||||
#include "../linux/pci_ids.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int __devinit
|
||||
ohci_pci_start (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ret;
|
||||
|
||||
DPRINT("ohci_pci_start()\n");
|
||||
|
||||
if (hcd->pdev) {
|
||||
ohci->hcca = pci_alloc_consistent (hcd->pdev,
|
||||
sizeof *ohci->hcca, &ohci->hcca_dma);
|
||||
if (!ohci->hcca)
|
||||
return -ENOMEM;
|
||||
|
||||
/* AMD 756, for most chips (early revs), corrupts register
|
||||
* values on read ... so enable the vendor workaround.
|
||||
*/
|
||||
if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD
|
||||
&& hcd->pdev->device == 0x740c) {
|
||||
ohci->flags = OHCI_QUIRK_AMD756;
|
||||
ohci_info (ohci, "AMD756 erratum 4 workaround\n");
|
||||
}
|
||||
|
||||
/* FIXME for some of the early AMD 760 southbridges, OHCI
|
||||
* won't work at all. blacklist them.
|
||||
*/
|
||||
|
||||
/* Apple's OHCI driver has a lot of bizarre workarounds
|
||||
* for this chip. Evidently control and bulk lists
|
||||
* can get confused. (B&W G3 models, and ...)
|
||||
*/
|
||||
else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI
|
||||
&& hcd->pdev->device == 0xc861) {
|
||||
ohci_info (ohci,
|
||||
"WARNING: OPTi workarounds unavailable\n");
|
||||
}
|
||||
|
||||
/* Check for NSC87560. We have to look at the bridge (fn1) to
|
||||
* identify the USB (fn2). This quirk might apply to more or
|
||||
* even all NSC stuff.
|
||||
*/
|
||||
else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) {
|
||||
struct pci_dev *b, *hc;
|
||||
|
||||
hc = hcd->pdev;
|
||||
b = pci_find_slot (hc->bus->number,
|
||||
PCI_DEVFN (PCI_SLOT (hc->devfn), 1));
|
||||
if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
|
||||
&& b->vendor == PCI_VENDOR_ID_NS) {
|
||||
ohci->flags |= OHCI_QUIRK_SUPERIO;
|
||||
ohci_info (ohci, "Using NSC SuperIO setup\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
|
||||
if ((ret = ohci_mem_init (ohci)) < 0) {
|
||||
ohci_stop (hcd);
|
||||
return ret;
|
||||
}
|
||||
ohci->regs = hcd->regs;
|
||||
|
||||
DPRINT("Controller memory init done\n");
|
||||
|
||||
if (hc_reset (ohci) < 0) {
|
||||
ohci_stop (hcd);
|
||||
return -ENODEV;
|
||||
}
|
||||
DPRINT("Controller reset done\n");
|
||||
|
||||
if (hc_start (ohci) < 0) {
|
||||
ohci_err (ohci, "can't start\n");
|
||||
ohci_stop (hcd);
|
||||
return -EBUSY;
|
||||
}
|
||||
DPRINT("Controller start done\n");
|
||||
|
||||
#ifdef DEBUG
|
||||
ohci_dump (ohci, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
unsigned long flags;
|
||||
u16 cmd;
|
||||
|
||||
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
|
||||
ohci_dbg (ohci, "can't suspend (state is %s)\n",
|
||||
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* act as if usb suspend can always be used */
|
||||
ohci_dbg (ohci, "suspend to %d\n", state);
|
||||
ohci->sleeping = 1;
|
||||
|
||||
/* First stop processing */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
ohci->hc_control &=
|
||||
~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
|
||||
(void) readl (&ohci->regs->intrstatus);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
/* Wait a frame or two */
|
||||
mdelay (1);
|
||||
if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
|
||||
mdelay (1);
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
if (_machine == _MACH_Pmac)
|
||||
disable_irq (hcd->pdev->irq);
|
||||
/* else, 2.4 assumes shared irqs -- don't disable */
|
||||
#endif
|
||||
|
||||
/* Enable remote wakeup */
|
||||
writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,
|
||||
&ohci->regs->intrenable);
|
||||
|
||||
/* Suspend chip and let things settle down a bit */
|
||||
ohci->hc_control = OHCI_USB_SUSPEND;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (500); /* No schedule here ! */
|
||||
|
||||
switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
|
||||
case OHCI_USB_RESET:
|
||||
ohci_dbg (ohci, "suspend->reset ?\n");
|
||||
break;
|
||||
case OHCI_USB_RESUME:
|
||||
ohci_dbg (ohci, "suspend->resume ?\n");
|
||||
break;
|
||||
case OHCI_USB_OPER:
|
||||
ohci_dbg (ohci, "suspend->operational ?\n");
|
||||
break;
|
||||
case OHCI_USB_SUSPEND:
|
||||
ohci_dbg (ohci, "suspended\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* In some rare situations, Apple's OHCI have happily trashed
|
||||
* memory during sleep. We disable its bus master bit during
|
||||
* suspend
|
||||
*/
|
||||
pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);
|
||||
cmd &= ~PCI_COMMAND_MASTER;
|
||||
pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
{
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Disable USB PAD & cell clock */
|
||||
of_node = pci_device_to_OF_node (hcd->pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ohci_pci_resume (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int temp;
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
{
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Re-enable USB PAD & cell clock */
|
||||
of_node = pci_device_to_OF_node (hcd->pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
|
||||
}
|
||||
#endif
|
||||
/* did we suspend, or were we powered off? */
|
||||
ohci->hc_control = readl (&ohci->regs->control);
|
||||
temp = ohci->hc_control & OHCI_CTRL_HCFS;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* the registers may look crazy here */
|
||||
ohci_dump_status (ohci, 0, 0);
|
||||
#endif
|
||||
|
||||
/* Re-enable bus mastering */
|
||||
pci_set_master (ohci->hcd.pdev);
|
||||
|
||||
switch (temp) {
|
||||
|
||||
case OHCI_USB_RESET: // lost power
|
||||
ohci_info (ohci, "USB restart\n");
|
||||
retval = hc_restart (ohci);
|
||||
break;
|
||||
|
||||
case OHCI_USB_SUSPEND: // host wakeup
|
||||
case OHCI_USB_RESUME: // remote wakeup
|
||||
ohci_info (ohci, "USB continue from %s wakeup\n",
|
||||
(temp == OHCI_USB_SUSPEND)
|
||||
? "host" : "remote");
|
||||
ohci->hc_control = OHCI_USB_RESUME;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (20); /* no schedule here ! */
|
||||
/* Some controllers (lucent) need a longer delay here */
|
||||
mdelay (15);
|
||||
|
||||
temp = readl (&ohci->regs->control);
|
||||
temp = ohci->hc_control & OHCI_CTRL_HCFS;
|
||||
if (temp != OHCI_USB_RESUME) {
|
||||
ohci_err (ohci, "controller won't resume\n");
|
||||
ohci->disabled = 1;
|
||||
retval = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Some chips likes being resumed first */
|
||||
writel (OHCI_USB_OPER, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (3);
|
||||
|
||||
/* Then re-enable operations */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
ohci->disabled = 0;
|
||||
ohci->sleeping = 0;
|
||||
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
|
||||
if (!ohci->ed_rm_list) {
|
||||
if (ohci->ed_controltail)
|
||||
ohci->hc_control |= OHCI_CTRL_CLE;
|
||||
if (ohci->ed_bulktail)
|
||||
ohci->hc_control |= OHCI_CTRL_BLE;
|
||||
}
|
||||
hcd->state = USB_STATE_READY;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
|
||||
/* trigger a start-frame interrupt (why?) */
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrenable);
|
||||
|
||||
/* Check for a pending done list */
|
||||
writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
|
||||
(void) readl (&ohci->regs->intrdisable);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
if (_machine == _MACH_Pmac)
|
||||
enable_irq (hcd->pdev->irq);
|
||||
#endif
|
||||
if (ohci->hcca->done_head)
|
||||
dl_done_list (ohci, dl_reverse_done_list (ohci), NULL);
|
||||
writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
|
||||
|
||||
/* assume there are TDs on the bulk and control lists */
|
||||
writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
|
||||
|
||||
// ohci_dump_status (ohci);
|
||||
ohci_dbg (ohci, "sleeping = %d, disabled = %d\n",
|
||||
ohci->sleeping, ohci->disabled);
|
||||
break;
|
||||
|
||||
default:
|
||||
ohci_warn (ohci, "odd PCI resume\n");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static const struct hc_driver ohci_pci_hc_driver = {
|
||||
.description = hcd_name,
|
||||
|
||||
/*
|
||||
* generic hardware linkage
|
||||
*/
|
||||
.irq = ohci_irq,
|
||||
.flags = HCD_MEMORY | HCD_USB11,
|
||||
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.start = ohci_pci_start,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ohci_pci_suspend,
|
||||
.resume = ohci_pci_resume,
|
||||
#endif
|
||||
.stop = ohci_stop,
|
||||
|
||||
/*
|
||||
* memory lifecycle (except per-request)
|
||||
*/
|
||||
.hcd_alloc = ohci_hcd_alloc,
|
||||
.hcd_free = ohci_hcd_free,
|
||||
|
||||
/*
|
||||
* managing i/o requests and associated device resources
|
||||
*/
|
||||
.urb_enqueue = ohci_urb_enqueue,
|
||||
.urb_dequeue = ohci_urb_dequeue,
|
||||
.endpoint_disable = ohci_endpoint_disable,
|
||||
|
||||
/*
|
||||
* scheduling support
|
||||
*/
|
||||
.get_frame_number = ohci_get_frame,
|
||||
|
||||
/*
|
||||
* root hub support
|
||||
*/
|
||||
.hub_status_data = ohci_hub_status_data,
|
||||
.hub_control = ohci_hub_control,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
const struct pci_device_id __devinitdata pci_ids [] = { {
|
||||
|
||||
/* handle any USB OHCI controller */
|
||||
.class = (PCI_CLASS_SERIAL_USB << 8) | 0x10,
|
||||
.class_mask = ~0,
|
||||
.driver_data = (unsigned long) &ohci_pci_hc_driver,
|
||||
|
||||
/* no matter who makes it */
|
||||
.vendor = PCI_ANY_ID,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
|
||||
}, { /* end: all zeroes */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE (pci, pci_ids);
|
||||
|
||||
/* pci driver glue; this is a "new style" PCI driver module */
|
||||
struct pci_driver ohci_pci_driver = {
|
||||
.name = (char *) hcd_name,
|
||||
.id_table = pci_ids,
|
||||
|
||||
.probe = usb_hcd_pci_probe,
|
||||
.remove = usb_hcd_pci_remove,
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = usb_hcd_pci_suspend,
|
||||
.resume = usb_hcd_pci_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
int ohci_hcd_pci_init (void)
|
||||
{
|
||||
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
// causes page fault in reactos
|
||||
//printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name,
|
||||
// sizeof (struct ed), sizeof (struct td));
|
||||
return pci_module_init (&ohci_pci_driver);
|
||||
}
|
||||
/*module_init (ohci_hcd_pci_init);*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
void ohci_hcd_pci_cleanup (void)
|
||||
{
|
||||
pci_unregister_driver (&ohci_pci_driver);
|
||||
}
|
||||
/*module_exit (ohci_hcd_pci_cleanup);*/
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* [ Initialisation is based on Linus' ]
|
||||
* [ uhci code and gregs ohci fragments ]
|
||||
* [ (C) Copyright 1999 Linus Torvalds ]
|
||||
* [ (C) Copyright 1999 Gregory P. Smith]
|
||||
*
|
||||
* PCI Bus Glue
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/prom.h>
|
||||
#ifndef CONFIG_PM
|
||||
# define CONFIG_PM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PCI
|
||||
#error "This file is PCI bus glue. CONFIG_PCI must be defined."
|
||||
#endif
|
||||
|
||||
#include "../linux/pci_ids.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int __devinit
|
||||
ohci_pci_start (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ret;
|
||||
|
||||
DPRINT("ohci_pci_start()\n");
|
||||
|
||||
if (hcd->pdev) {
|
||||
ohci->hcca = pci_alloc_consistent (hcd->pdev,
|
||||
sizeof *ohci->hcca, &ohci->hcca_dma);
|
||||
if (!ohci->hcca)
|
||||
return -ENOMEM;
|
||||
|
||||
/* AMD 756, for most chips (early revs), corrupts register
|
||||
* values on read ... so enable the vendor workaround.
|
||||
*/
|
||||
if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD
|
||||
&& hcd->pdev->device == 0x740c) {
|
||||
ohci->flags = OHCI_QUIRK_AMD756;
|
||||
ohci_info (ohci, "AMD756 erratum 4 workaround\n");
|
||||
}
|
||||
|
||||
/* FIXME for some of the early AMD 760 southbridges, OHCI
|
||||
* won't work at all. blacklist them.
|
||||
*/
|
||||
|
||||
/* Apple's OHCI driver has a lot of bizarre workarounds
|
||||
* for this chip. Evidently control and bulk lists
|
||||
* can get confused. (B&W G3 models, and ...)
|
||||
*/
|
||||
else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI
|
||||
&& hcd->pdev->device == 0xc861) {
|
||||
ohci_info (ohci,
|
||||
"WARNING: OPTi workarounds unavailable\n");
|
||||
}
|
||||
|
||||
/* Check for NSC87560. We have to look at the bridge (fn1) to
|
||||
* identify the USB (fn2). This quirk might apply to more or
|
||||
* even all NSC stuff.
|
||||
*/
|
||||
else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) {
|
||||
struct pci_dev *b, *hc;
|
||||
|
||||
hc = hcd->pdev;
|
||||
b = pci_find_slot (hc->bus->number,
|
||||
PCI_DEVFN (PCI_SLOT (hc->devfn), 1));
|
||||
if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
|
||||
&& b->vendor == PCI_VENDOR_ID_NS) {
|
||||
ohci->flags |= OHCI_QUIRK_SUPERIO;
|
||||
ohci_info (ohci, "Using NSC SuperIO setup\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
|
||||
if ((ret = ohci_mem_init (ohci)) < 0) {
|
||||
ohci_stop (hcd);
|
||||
return ret;
|
||||
}
|
||||
ohci->regs = hcd->regs;
|
||||
|
||||
DPRINT("Controller memory init done\n");
|
||||
|
||||
if (hc_reset (ohci) < 0) {
|
||||
ohci_stop (hcd);
|
||||
return -ENODEV;
|
||||
}
|
||||
DPRINT("Controller reset done\n");
|
||||
|
||||
if (hc_start (ohci) < 0) {
|
||||
ohci_err (ohci, "can't start\n");
|
||||
ohci_stop (hcd);
|
||||
return -EBUSY;
|
||||
}
|
||||
DPRINT("Controller start done\n");
|
||||
|
||||
#ifdef DEBUG
|
||||
ohci_dump (ohci, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
unsigned long flags;
|
||||
u16 cmd;
|
||||
|
||||
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
|
||||
ohci_dbg (ohci, "can't suspend (state is %s)\n",
|
||||
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* act as if usb suspend can always be used */
|
||||
ohci_dbg (ohci, "suspend to %d\n", state);
|
||||
ohci->sleeping = 1;
|
||||
|
||||
/* First stop processing */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
ohci->hc_control &=
|
||||
~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
|
||||
(void) readl (&ohci->regs->intrstatus);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
/* Wait a frame or two */
|
||||
mdelay (1);
|
||||
if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
|
||||
mdelay (1);
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
if (_machine == _MACH_Pmac)
|
||||
disable_irq (hcd->pdev->irq);
|
||||
/* else, 2.4 assumes shared irqs -- don't disable */
|
||||
#endif
|
||||
|
||||
/* Enable remote wakeup */
|
||||
writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,
|
||||
&ohci->regs->intrenable);
|
||||
|
||||
/* Suspend chip and let things settle down a bit */
|
||||
ohci->hc_control = OHCI_USB_SUSPEND;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (500); /* No schedule here ! */
|
||||
|
||||
switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
|
||||
case OHCI_USB_RESET:
|
||||
ohci_dbg (ohci, "suspend->reset ?\n");
|
||||
break;
|
||||
case OHCI_USB_RESUME:
|
||||
ohci_dbg (ohci, "suspend->resume ?\n");
|
||||
break;
|
||||
case OHCI_USB_OPER:
|
||||
ohci_dbg (ohci, "suspend->operational ?\n");
|
||||
break;
|
||||
case OHCI_USB_SUSPEND:
|
||||
ohci_dbg (ohci, "suspended\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* In some rare situations, Apple's OHCI have happily trashed
|
||||
* memory during sleep. We disable its bus master bit during
|
||||
* suspend
|
||||
*/
|
||||
pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);
|
||||
cmd &= ~PCI_COMMAND_MASTER;
|
||||
pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
{
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Disable USB PAD & cell clock */
|
||||
of_node = pci_device_to_OF_node (hcd->pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ohci_pci_resume (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int temp;
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
{
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Re-enable USB PAD & cell clock */
|
||||
of_node = pci_device_to_OF_node (hcd->pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
|
||||
}
|
||||
#endif
|
||||
/* did we suspend, or were we powered off? */
|
||||
ohci->hc_control = readl (&ohci->regs->control);
|
||||
temp = ohci->hc_control & OHCI_CTRL_HCFS;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* the registers may look crazy here */
|
||||
ohci_dump_status (ohci, 0, 0);
|
||||
#endif
|
||||
|
||||
/* Re-enable bus mastering */
|
||||
pci_set_master (ohci->hcd.pdev);
|
||||
|
||||
switch (temp) {
|
||||
|
||||
case OHCI_USB_RESET: // lost power
|
||||
ohci_info (ohci, "USB restart\n");
|
||||
retval = hc_restart (ohci);
|
||||
break;
|
||||
|
||||
case OHCI_USB_SUSPEND: // host wakeup
|
||||
case OHCI_USB_RESUME: // remote wakeup
|
||||
ohci_info (ohci, "USB continue from %s wakeup\n",
|
||||
(temp == OHCI_USB_SUSPEND)
|
||||
? "host" : "remote");
|
||||
ohci->hc_control = OHCI_USB_RESUME;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (20); /* no schedule here ! */
|
||||
/* Some controllers (lucent) need a longer delay here */
|
||||
mdelay (15);
|
||||
|
||||
temp = readl (&ohci->regs->control);
|
||||
temp = ohci->hc_control & OHCI_CTRL_HCFS;
|
||||
if (temp != OHCI_USB_RESUME) {
|
||||
ohci_err (ohci, "controller won't resume\n");
|
||||
ohci->disabled = 1;
|
||||
retval = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Some chips likes being resumed first */
|
||||
writel (OHCI_USB_OPER, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (3);
|
||||
|
||||
/* Then re-enable operations */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
ohci->disabled = 0;
|
||||
ohci->sleeping = 0;
|
||||
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
|
||||
if (!ohci->ed_rm_list) {
|
||||
if (ohci->ed_controltail)
|
||||
ohci->hc_control |= OHCI_CTRL_CLE;
|
||||
if (ohci->ed_bulktail)
|
||||
ohci->hc_control |= OHCI_CTRL_BLE;
|
||||
}
|
||||
hcd->state = USB_STATE_READY;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
|
||||
/* trigger a start-frame interrupt (why?) */
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrenable);
|
||||
|
||||
/* Check for a pending done list */
|
||||
writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
|
||||
(void) readl (&ohci->regs->intrdisable);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
if (_machine == _MACH_Pmac)
|
||||
enable_irq (hcd->pdev->irq);
|
||||
#endif
|
||||
if (ohci->hcca->done_head)
|
||||
dl_done_list (ohci, dl_reverse_done_list (ohci), NULL);
|
||||
writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
|
||||
|
||||
/* assume there are TDs on the bulk and control lists */
|
||||
writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
|
||||
|
||||
// ohci_dump_status (ohci);
|
||||
ohci_dbg (ohci, "sleeping = %d, disabled = %d\n",
|
||||
ohci->sleeping, ohci->disabled);
|
||||
break;
|
||||
|
||||
default:
|
||||
ohci_warn (ohci, "odd PCI resume\n");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static const struct hc_driver ohci_pci_hc_driver = {
|
||||
.description = hcd_name,
|
||||
|
||||
/*
|
||||
* generic hardware linkage
|
||||
*/
|
||||
.irq = ohci_irq,
|
||||
.flags = HCD_MEMORY | HCD_USB11,
|
||||
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.start = ohci_pci_start,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ohci_pci_suspend,
|
||||
.resume = ohci_pci_resume,
|
||||
#endif
|
||||
.stop = ohci_stop,
|
||||
|
||||
/*
|
||||
* memory lifecycle (except per-request)
|
||||
*/
|
||||
.hcd_alloc = ohci_hcd_alloc,
|
||||
.hcd_free = ohci_hcd_free,
|
||||
|
||||
/*
|
||||
* managing i/o requests and associated device resources
|
||||
*/
|
||||
.urb_enqueue = ohci_urb_enqueue,
|
||||
.urb_dequeue = ohci_urb_dequeue,
|
||||
.endpoint_disable = ohci_endpoint_disable,
|
||||
|
||||
/*
|
||||
* scheduling support
|
||||
*/
|
||||
.get_frame_number = ohci_get_frame,
|
||||
|
||||
/*
|
||||
* root hub support
|
||||
*/
|
||||
.hub_status_data = ohci_hub_status_data,
|
||||
.hub_control = ohci_hub_control,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
const struct pci_device_id __devinitdata pci_ids [] = { {
|
||||
|
||||
/* handle any USB OHCI controller */
|
||||
.class = (PCI_CLASS_SERIAL_USB << 8) | 0x10,
|
||||
.class_mask = ~0,
|
||||
.driver_data = (unsigned long) &ohci_pci_hc_driver,
|
||||
|
||||
/* no matter who makes it */
|
||||
.vendor = PCI_ANY_ID,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
|
||||
}, { /* end: all zeroes */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE (pci, pci_ids);
|
||||
|
||||
/* pci driver glue; this is a "new style" PCI driver module */
|
||||
struct pci_driver ohci_pci_driver = {
|
||||
.name = (char *) hcd_name,
|
||||
.id_table = pci_ids,
|
||||
|
||||
.probe = usb_hcd_pci_probe,
|
||||
.remove = usb_hcd_pci_remove,
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = usb_hcd_pci_suspend,
|
||||
.resume = usb_hcd_pci_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
int ohci_hcd_pci_init (void)
|
||||
{
|
||||
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
// causes page fault in reactos
|
||||
//printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name,
|
||||
// sizeof (struct ed), sizeof (struct td));
|
||||
return pci_module_init (&ohci_pci_driver);
|
||||
}
|
||||
/*module_init (ohci_hcd_pci_init);*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
void ohci_hcd_pci_cleanup (void)
|
||||
{
|
||||
pci_unregister_driver (&ohci_pci_driver);
|
||||
}
|
||||
/*module_exit (ohci_hcd_pci_cleanup);*/
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,2 +1,2 @@
|
|||
LIBRARY ohci.sys
|
||||
EXPORTS
|
||||
LIBRARY ohci.sys
|
||||
EXPORTS
|
||||
|
|
|
@ -1,418 +1,418 @@
|
|||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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".
|
||||
*/
|
||||
struct ed {
|
||||
/* first fields are hardware-specified, le32 */
|
||||
__u32 hwINFO; /* endpoint config bitmap */
|
||||
/* info bits defined by hcd */
|
||||
#define ED_DEQUEUE __constant_cpu_to_le32(1 << 27)
|
||||
/* info bits defined by the hardware */
|
||||
#define ED_ISO __constant_cpu_to_le32(1 << 15)
|
||||
#define ED_SKIP __constant_cpu_to_le32(1 << 14)
|
||||
#define ED_LOWSPEED __constant_cpu_to_le32(1 << 13)
|
||||
#define ED_OUT __constant_cpu_to_le32(0x01 << 11)
|
||||
#define ED_IN __constant_cpu_to_le32(0x02 << 11)
|
||||
__u32 hwTailP; /* tail of TD list */
|
||||
__u32 hwHeadP; /* head of TD list (hc r/w) */
|
||||
#define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */
|
||||
#define ED_H __constant_cpu_to_le32(0x01) /* halted */
|
||||
__u32 hwNextED; /* next ED in list */
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
dma_addr_t dma; /* addr of ED */
|
||||
struct td *dummy; /* next TD to activate */
|
||||
|
||||
/* host's view of schedule */
|
||||
struct ed *ed_next; /* on schedule or rm_list */
|
||||
struct 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) --> ...
|
||||
* some special cases : OPER --> IDLE ...
|
||||
*/
|
||||
u8 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 */
|
||||
|
||||
u8 type; /* PIPE_{BULK,...} */
|
||||
|
||||
/* periodic scheduling params (for intr and iso) */
|
||||
u8 branch;
|
||||
u16 interval;
|
||||
u16 load;
|
||||
u16 last_iso; /* iso only */
|
||||
|
||||
/* HC may see EDs on rm_list until next frame (frame_no == tick) */
|
||||
u16 tick;
|
||||
} __attribute__ ((aligned(16)));
|
||||
|
||||
#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)
|
||||
*/
|
||||
struct td {
|
||||
/* first fields are hardware-specified, le32 */
|
||||
__u32 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) */
|
||||
|
||||
__u32 hwCBP; /* Current Buffer Pointer (or 0) */
|
||||
__u32 hwNextTD; /* Next TD Pointer */
|
||||
__u32 hwBE; /* Memory Buffer End Pointer */
|
||||
|
||||
/* PSW is only for ISO */
|
||||
#define MAXPSW 1 /* hardware allows 8 */
|
||||
__u16 hwPSW [MAXPSW];
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
__u8 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 */
|
||||
} __attribute__ ((aligned(32))); /* c/b/i need 16; only iso needs 32 */
|
||||
|
||||
#define TD_MASK ((u32)~0x1f) /* strip hw status in low addr bits */
|
||||
|
||||
/*
|
||||
* Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW
|
||||
*/
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
#define TD_UNEXPECTEDPID 0x07
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
/* 0x0A, 0x0B reserved for hardware */
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
/* 0x0E, 0x0F reserved for HCD */
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
|
||||
/* map OHCI TD status codes (CC) to errno values */
|
||||
static const int cc_to_error [16] = {
|
||||
/* No Error */ 0,
|
||||
/* CRC Error */ -EILSEQ,
|
||||
/* Bit Stuff */ -EPROTO,
|
||||
/* Data Togg */ -EILSEQ,
|
||||
/* Stall */ -EPIPE,
|
||||
/* DevNotResp */ -ETIMEDOUT,
|
||||
/* PIDCheck */ -EPROTO,
|
||||
/* UnExpPID */ -EPROTO,
|
||||
/* DataOver */ -EOVERFLOW,
|
||||
/* DataUnder */ -EREMOTEIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* BufferOver */ -ECOMM,
|
||||
/* BuffUnder */ -ENOSR,
|
||||
/* (for HCD) */ -EALREADY,
|
||||
/* (for HCD) */ -EALREADY
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
struct ohci_hcca {
|
||||
#define NUM_INTS 32
|
||||
__u32 int_table [NUM_INTS]; /* periodic schedule */
|
||||
__u16 frame_no; /* current frame number */
|
||||
__u16 pad1; /* set to 0 on each frame_no change */
|
||||
__u32 done_head; /* info returned for an interrupt */
|
||||
u8 reserved_for_hc [116];
|
||||
u8 what [4]; /* spec only identifies 252 bytes :) */
|
||||
} __attribute__ ((aligned(256)));
|
||||
|
||||
|
||||
/*
|
||||
* 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!!
|
||||
* Layout is in section 7 (and appendix B) of the spec.
|
||||
*/
|
||||
struct ohci_regs {
|
||||
/* control and status registers (section 7.1) */
|
||||
__u32 revision;
|
||||
__u32 control;
|
||||
__u32 cmdstatus;
|
||||
__u32 intrstatus;
|
||||
__u32 intrenable;
|
||||
__u32 intrdisable;
|
||||
|
||||
/* memory pointers (section 7.2) */
|
||||
__u32 hcca;
|
||||
__u32 ed_periodcurrent;
|
||||
__u32 ed_controlhead;
|
||||
__u32 ed_controlcurrent;
|
||||
__u32 ed_bulkhead;
|
||||
__u32 ed_bulkcurrent;
|
||||
__u32 donehead;
|
||||
|
||||
/* frame counters (section 7.3) */
|
||||
__u32 fminterval;
|
||||
__u32 fmremaining;
|
||||
__u32 fmnumber;
|
||||
__u32 periodicstart;
|
||||
__u32 lsthresh;
|
||||
|
||||
/* Root hub ports (section 7.4) */
|
||||
struct ohci_roothub_regs {
|
||||
__u32 a;
|
||||
__u32 b;
|
||||
__u32 status;
|
||||
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */
|
||||
__u32 portstatus [MAX_ROOT_PORTS];
|
||||
} roothub;
|
||||
|
||||
/* and optional "legacy support" registers (appendix B) at 0x0100 */
|
||||
|
||||
} __attribute__ ((aligned(32)));
|
||||
|
||||
|
||||
/* OHCI CONTROL AND STATUS REGISTER MASKS */
|
||||
|
||||
/*
|
||||
* HcControl (control) register masks
|
||||
*/
|
||||
#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
|
||||
#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
|
||||
#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
|
||||
#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
|
||||
#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
|
||||
#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
|
||||
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
|
||||
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
|
||||
#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
|
||||
|
||||
/* pre-shifted values for HCFS */
|
||||
#define OHCI_USB_RESET (0 << 6)
|
||||
#define OHCI_USB_RESUME (1 << 6)
|
||||
#define OHCI_USB_OPER (2 << 6)
|
||||
#define OHCI_USB_SUSPEND (3 << 6)
|
||||
|
||||
// HCFS itself
|
||||
static char *hcfs2string (int state)
|
||||
{
|
||||
switch (state) {
|
||||
case OHCI_USB_RESET: return "reset";
|
||||
case OHCI_USB_RESUME: return "resume";
|
||||
case OHCI_USB_OPER: return "operational";
|
||||
case OHCI_USB_SUSPEND: return "suspend";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
/*
|
||||
* HcCommandStatus (cmdstatus) register masks
|
||||
*/
|
||||
#define OHCI_HCR (1 << 0) /* host controller reset */
|
||||
#define OHCI_CLF (1 << 1) /* control list filled */
|
||||
#define OHCI_BLF (1 << 2) /* bulk list filled */
|
||||
#define OHCI_OCR (1 << 3) /* ownership change request */
|
||||
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
|
||||
|
||||
/*
|
||||
* masks used with interrupt registers:
|
||||
* HcInterruptStatus (intrstatus)
|
||||
* HcInterruptEnable (intrenable)
|
||||
* HcInterruptDisable (intrdisable)
|
||||
*/
|
||||
#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
|
||||
#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
|
||||
#define OHCI_INTR_SF (1 << 2) /* start frame */
|
||||
#define OHCI_INTR_RD (1 << 3) /* resume detect */
|
||||
#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
|
||||
#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
|
||||
#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
|
||||
#define OHCI_INTR_OC (1 << 30) /* ownership change */
|
||||
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
|
||||
|
||||
|
||||
/* OHCI ROOT HUB REGISTER MASKS */
|
||||
|
||||
/* roothub.portstatus [i] bits */
|
||||
#define RH_PS_CCS 0x00000001 /* current connect status */
|
||||
#define RH_PS_PES 0x00000002 /* port enable status*/
|
||||
#define RH_PS_PSS 0x00000004 /* port suspend status */
|
||||
#define RH_PS_POCI 0x00000008 /* port over current indicator */
|
||||
#define RH_PS_PRS 0x00000010 /* port reset status */
|
||||
#define RH_PS_PPS 0x00000100 /* port power status */
|
||||
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
|
||||
#define RH_PS_CSC 0x00010000 /* connect status change */
|
||||
#define RH_PS_PESC 0x00020000 /* port enable status change */
|
||||
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
|
||||
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
|
||||
#define RH_PS_PRSC 0x00100000 /* port reset status change */
|
||||
|
||||
/* roothub.status bits */
|
||||
#define RH_HS_LPS 0x00000001 /* local power status */
|
||||
#define RH_HS_OCI 0x00000002 /* over current indicator */
|
||||
#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
|
||||
#define RH_HS_LPSC 0x00010000 /* local power status change */
|
||||
#define RH_HS_OCIC 0x00020000 /* over current indicator change */
|
||||
#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
|
||||
|
||||
/* roothub.b masks */
|
||||
#define RH_B_DR 0x0000ffff /* device removable flags */
|
||||
#define RH_B_PPCM 0xffff0000 /* port power control mask */
|
||||
|
||||
/* roothub.a masks */
|
||||
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* over current protection mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no over current protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
|
||||
|
||||
|
||||
/* hcd-private per-urb state */
|
||||
typedef struct urb_priv {
|
||||
struct ed *ed;
|
||||
__u16 length; // # tds in this request
|
||||
__u16 td_cnt; // tds already serviced
|
||||
int state;
|
||||
struct td *td [0]; // all TDs in this request
|
||||
|
||||
} urb_priv_t;
|
||||
|
||||
#define URB_DEL 1
|
||||
|
||||
#define TD_HASH_SIZE 64 /* power'o'two */
|
||||
// sizeof (struct td) ~= 64 == 2^6 ...
|
||||
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
|
||||
|
||||
|
||||
/*
|
||||
* This is the full ohci controller description
|
||||
*
|
||||
* Note how the "proper" USB information is just
|
||||
* a subset of what the full implementation needs. (Linus)
|
||||
*/
|
||||
|
||||
struct ohci_hcd {
|
||||
spinlock_t lock;
|
||||
|
||||
/*
|
||||
* I/O memory used to communicate with the HC (dma-consistent)
|
||||
*/
|
||||
struct ohci_regs *regs;
|
||||
|
||||
/*
|
||||
* main memory used to communicate with the HC (dma-consistent).
|
||||
* hcd adds to schedule for a live hc any time, but removals finish
|
||||
* only at the start of the next frame.
|
||||
*/
|
||||
struct ohci_hcca *hcca;
|
||||
dma_addr_t hcca_dma;
|
||||
|
||||
struct ed *ed_rm_list; /* to be removed */
|
||||
|
||||
struct ed *ed_bulktail; /* last in bulk list */
|
||||
struct ed *ed_controltail; /* last in ctrl list */
|
||||
struct ed *periodic [NUM_INTS]; /* shadow int_table */
|
||||
|
||||
/*
|
||||
* memory management for queue data structures
|
||||
*/
|
||||
struct pci_pool *td_cache;
|
||||
struct pci_pool *ed_cache;
|
||||
struct td *td_hash [TD_HASH_SIZE];
|
||||
|
||||
/*
|
||||
* driver state
|
||||
*/
|
||||
int disabled; /* e.g. got a UE, we're hung */
|
||||
int sleeping;
|
||||
int load [NUM_INTS];
|
||||
u32 hc_control; /* copy of hc control reg */
|
||||
|
||||
unsigned long flags; /* for HC bugs */
|
||||
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
|
||||
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
|
||||
// there are also chip quirks/bugs in init logic
|
||||
|
||||
/*
|
||||
* framework state
|
||||
*/
|
||||
struct usb_hcd hcd;
|
||||
};
|
||||
|
||||
#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef DEBUG
|
||||
#define STUB_DEBUG_FILES
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define ohci_dbg(ohci, fmt, args...) \
|
||||
dev_dbg ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_err(ohci, fmt, args...) \
|
||||
dev_err ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_info(ohci, fmt, args...) \
|
||||
dev_info ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_warn(ohci, fmt, args...) \
|
||||
dev_warn ((ohci)->hcd.controller , fmt , ## args )
|
||||
|
||||
#ifdef OHCI_VERBOSE_DEBUG
|
||||
# define ohci_vdbg ohci_dbg
|
||||
#else
|
||||
# define ohci_vdbg(ohci, fmt, args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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".
|
||||
*/
|
||||
struct ed {
|
||||
/* first fields are hardware-specified, le32 */
|
||||
__u32 hwINFO; /* endpoint config bitmap */
|
||||
/* info bits defined by hcd */
|
||||
#define ED_DEQUEUE __constant_cpu_to_le32(1 << 27)
|
||||
/* info bits defined by the hardware */
|
||||
#define ED_ISO __constant_cpu_to_le32(1 << 15)
|
||||
#define ED_SKIP __constant_cpu_to_le32(1 << 14)
|
||||
#define ED_LOWSPEED __constant_cpu_to_le32(1 << 13)
|
||||
#define ED_OUT __constant_cpu_to_le32(0x01 << 11)
|
||||
#define ED_IN __constant_cpu_to_le32(0x02 << 11)
|
||||
__u32 hwTailP; /* tail of TD list */
|
||||
__u32 hwHeadP; /* head of TD list (hc r/w) */
|
||||
#define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */
|
||||
#define ED_H __constant_cpu_to_le32(0x01) /* halted */
|
||||
__u32 hwNextED; /* next ED in list */
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
dma_addr_t dma; /* addr of ED */
|
||||
struct td *dummy; /* next TD to activate */
|
||||
|
||||
/* host's view of schedule */
|
||||
struct ed *ed_next; /* on schedule or rm_list */
|
||||
struct 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) --> ...
|
||||
* some special cases : OPER --> IDLE ...
|
||||
*/
|
||||
u8 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 */
|
||||
|
||||
u8 type; /* PIPE_{BULK,...} */
|
||||
|
||||
/* periodic scheduling params (for intr and iso) */
|
||||
u8 branch;
|
||||
u16 interval;
|
||||
u16 load;
|
||||
u16 last_iso; /* iso only */
|
||||
|
||||
/* HC may see EDs on rm_list until next frame (frame_no == tick) */
|
||||
u16 tick;
|
||||
} __attribute__ ((aligned(16)));
|
||||
|
||||
#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)
|
||||
*/
|
||||
struct td {
|
||||
/* first fields are hardware-specified, le32 */
|
||||
__u32 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) */
|
||||
|
||||
__u32 hwCBP; /* Current Buffer Pointer (or 0) */
|
||||
__u32 hwNextTD; /* Next TD Pointer */
|
||||
__u32 hwBE; /* Memory Buffer End Pointer */
|
||||
|
||||
/* PSW is only for ISO */
|
||||
#define MAXPSW 1 /* hardware allows 8 */
|
||||
__u16 hwPSW [MAXPSW];
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
__u8 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 */
|
||||
} __attribute__ ((aligned(32))); /* c/b/i need 16; only iso needs 32 */
|
||||
|
||||
#define TD_MASK ((u32)~0x1f) /* strip hw status in low addr bits */
|
||||
|
||||
/*
|
||||
* Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW
|
||||
*/
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
#define TD_UNEXPECTEDPID 0x07
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
/* 0x0A, 0x0B reserved for hardware */
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
/* 0x0E, 0x0F reserved for HCD */
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
|
||||
/* map OHCI TD status codes (CC) to errno values */
|
||||
static const int cc_to_error [16] = {
|
||||
/* No Error */ 0,
|
||||
/* CRC Error */ -EILSEQ,
|
||||
/* Bit Stuff */ -EPROTO,
|
||||
/* Data Togg */ -EILSEQ,
|
||||
/* Stall */ -EPIPE,
|
||||
/* DevNotResp */ -ETIMEDOUT,
|
||||
/* PIDCheck */ -EPROTO,
|
||||
/* UnExpPID */ -EPROTO,
|
||||
/* DataOver */ -EOVERFLOW,
|
||||
/* DataUnder */ -EREMOTEIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* BufferOver */ -ECOMM,
|
||||
/* BuffUnder */ -ENOSR,
|
||||
/* (for HCD) */ -EALREADY,
|
||||
/* (for HCD) */ -EALREADY
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
struct ohci_hcca {
|
||||
#define NUM_INTS 32
|
||||
__u32 int_table [NUM_INTS]; /* periodic schedule */
|
||||
__u16 frame_no; /* current frame number */
|
||||
__u16 pad1; /* set to 0 on each frame_no change */
|
||||
__u32 done_head; /* info returned for an interrupt */
|
||||
u8 reserved_for_hc [116];
|
||||
u8 what [4]; /* spec only identifies 252 bytes :) */
|
||||
} __attribute__ ((aligned(256)));
|
||||
|
||||
|
||||
/*
|
||||
* 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!!
|
||||
* Layout is in section 7 (and appendix B) of the spec.
|
||||
*/
|
||||
struct ohci_regs {
|
||||
/* control and status registers (section 7.1) */
|
||||
__u32 revision;
|
||||
__u32 control;
|
||||
__u32 cmdstatus;
|
||||
__u32 intrstatus;
|
||||
__u32 intrenable;
|
||||
__u32 intrdisable;
|
||||
|
||||
/* memory pointers (section 7.2) */
|
||||
__u32 hcca;
|
||||
__u32 ed_periodcurrent;
|
||||
__u32 ed_controlhead;
|
||||
__u32 ed_controlcurrent;
|
||||
__u32 ed_bulkhead;
|
||||
__u32 ed_bulkcurrent;
|
||||
__u32 donehead;
|
||||
|
||||
/* frame counters (section 7.3) */
|
||||
__u32 fminterval;
|
||||
__u32 fmremaining;
|
||||
__u32 fmnumber;
|
||||
__u32 periodicstart;
|
||||
__u32 lsthresh;
|
||||
|
||||
/* Root hub ports (section 7.4) */
|
||||
struct ohci_roothub_regs {
|
||||
__u32 a;
|
||||
__u32 b;
|
||||
__u32 status;
|
||||
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */
|
||||
__u32 portstatus [MAX_ROOT_PORTS];
|
||||
} roothub;
|
||||
|
||||
/* and optional "legacy support" registers (appendix B) at 0x0100 */
|
||||
|
||||
} __attribute__ ((aligned(32)));
|
||||
|
||||
|
||||
/* OHCI CONTROL AND STATUS REGISTER MASKS */
|
||||
|
||||
/*
|
||||
* HcControl (control) register masks
|
||||
*/
|
||||
#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */
|
||||
#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */
|
||||
#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */
|
||||
#define OHCI_CTRL_CLE (1 << 4) /* control list enable */
|
||||
#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */
|
||||
#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */
|
||||
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
|
||||
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
|
||||
#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */
|
||||
|
||||
/* pre-shifted values for HCFS */
|
||||
#define OHCI_USB_RESET (0 << 6)
|
||||
#define OHCI_USB_RESUME (1 << 6)
|
||||
#define OHCI_USB_OPER (2 << 6)
|
||||
#define OHCI_USB_SUSPEND (3 << 6)
|
||||
|
||||
// HCFS itself
|
||||
static char *hcfs2string (int state)
|
||||
{
|
||||
switch (state) {
|
||||
case OHCI_USB_RESET: return "reset";
|
||||
case OHCI_USB_RESUME: return "resume";
|
||||
case OHCI_USB_OPER: return "operational";
|
||||
case OHCI_USB_SUSPEND: return "suspend";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
/*
|
||||
* HcCommandStatus (cmdstatus) register masks
|
||||
*/
|
||||
#define OHCI_HCR (1 << 0) /* host controller reset */
|
||||
#define OHCI_CLF (1 << 1) /* control list filled */
|
||||
#define OHCI_BLF (1 << 2) /* bulk list filled */
|
||||
#define OHCI_OCR (1 << 3) /* ownership change request */
|
||||
#define OHCI_SOC (3 << 16) /* scheduling overrun count */
|
||||
|
||||
/*
|
||||
* masks used with interrupt registers:
|
||||
* HcInterruptStatus (intrstatus)
|
||||
* HcInterruptEnable (intrenable)
|
||||
* HcInterruptDisable (intrdisable)
|
||||
*/
|
||||
#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */
|
||||
#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */
|
||||
#define OHCI_INTR_SF (1 << 2) /* start frame */
|
||||
#define OHCI_INTR_RD (1 << 3) /* resume detect */
|
||||
#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */
|
||||
#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */
|
||||
#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */
|
||||
#define OHCI_INTR_OC (1 << 30) /* ownership change */
|
||||
#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */
|
||||
|
||||
|
||||
/* OHCI ROOT HUB REGISTER MASKS */
|
||||
|
||||
/* roothub.portstatus [i] bits */
|
||||
#define RH_PS_CCS 0x00000001 /* current connect status */
|
||||
#define RH_PS_PES 0x00000002 /* port enable status*/
|
||||
#define RH_PS_PSS 0x00000004 /* port suspend status */
|
||||
#define RH_PS_POCI 0x00000008 /* port over current indicator */
|
||||
#define RH_PS_PRS 0x00000010 /* port reset status */
|
||||
#define RH_PS_PPS 0x00000100 /* port power status */
|
||||
#define RH_PS_LSDA 0x00000200 /* low speed device attached */
|
||||
#define RH_PS_CSC 0x00010000 /* connect status change */
|
||||
#define RH_PS_PESC 0x00020000 /* port enable status change */
|
||||
#define RH_PS_PSSC 0x00040000 /* port suspend status change */
|
||||
#define RH_PS_OCIC 0x00080000 /* over current indicator change */
|
||||
#define RH_PS_PRSC 0x00100000 /* port reset status change */
|
||||
|
||||
/* roothub.status bits */
|
||||
#define RH_HS_LPS 0x00000001 /* local power status */
|
||||
#define RH_HS_OCI 0x00000002 /* over current indicator */
|
||||
#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
|
||||
#define RH_HS_LPSC 0x00010000 /* local power status change */
|
||||
#define RH_HS_OCIC 0x00020000 /* over current indicator change */
|
||||
#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
|
||||
|
||||
/* roothub.b masks */
|
||||
#define RH_B_DR 0x0000ffff /* device removable flags */
|
||||
#define RH_B_PPCM 0xffff0000 /* port power control mask */
|
||||
|
||||
/* roothub.a masks */
|
||||
#define RH_A_NDP (0xff << 0) /* number of downstream ports */
|
||||
#define RH_A_PSM (1 << 8) /* power switching mode */
|
||||
#define RH_A_NPS (1 << 9) /* no power switching */
|
||||
#define RH_A_DT (1 << 10) /* device type (mbz) */
|
||||
#define RH_A_OCPM (1 << 11) /* over current protection mode */
|
||||
#define RH_A_NOCP (1 << 12) /* no over current protection */
|
||||
#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
|
||||
|
||||
|
||||
/* hcd-private per-urb state */
|
||||
typedef struct urb_priv {
|
||||
struct ed *ed;
|
||||
__u16 length; // # tds in this request
|
||||
__u16 td_cnt; // tds already serviced
|
||||
int state;
|
||||
struct td *td [0]; // all TDs in this request
|
||||
|
||||
} urb_priv_t;
|
||||
|
||||
#define URB_DEL 1
|
||||
|
||||
#define TD_HASH_SIZE 64 /* power'o'two */
|
||||
// sizeof (struct td) ~= 64 == 2^6 ...
|
||||
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
|
||||
|
||||
|
||||
/*
|
||||
* This is the full ohci controller description
|
||||
*
|
||||
* Note how the "proper" USB information is just
|
||||
* a subset of what the full implementation needs. (Linus)
|
||||
*/
|
||||
|
||||
struct ohci_hcd {
|
||||
spinlock_t lock;
|
||||
|
||||
/*
|
||||
* I/O memory used to communicate with the HC (dma-consistent)
|
||||
*/
|
||||
struct ohci_regs *regs;
|
||||
|
||||
/*
|
||||
* main memory used to communicate with the HC (dma-consistent).
|
||||
* hcd adds to schedule for a live hc any time, but removals finish
|
||||
* only at the start of the next frame.
|
||||
*/
|
||||
struct ohci_hcca *hcca;
|
||||
dma_addr_t hcca_dma;
|
||||
|
||||
struct ed *ed_rm_list; /* to be removed */
|
||||
|
||||
struct ed *ed_bulktail; /* last in bulk list */
|
||||
struct ed *ed_controltail; /* last in ctrl list */
|
||||
struct ed *periodic [NUM_INTS]; /* shadow int_table */
|
||||
|
||||
/*
|
||||
* memory management for queue data structures
|
||||
*/
|
||||
struct pci_pool *td_cache;
|
||||
struct pci_pool *ed_cache;
|
||||
struct td *td_hash [TD_HASH_SIZE];
|
||||
|
||||
/*
|
||||
* driver state
|
||||
*/
|
||||
int disabled; /* e.g. got a UE, we're hung */
|
||||
int sleeping;
|
||||
int load [NUM_INTS];
|
||||
u32 hc_control; /* copy of hc control reg */
|
||||
|
||||
unsigned long flags; /* for HC bugs */
|
||||
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
|
||||
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
|
||||
// there are also chip quirks/bugs in init logic
|
||||
|
||||
/*
|
||||
* framework state
|
||||
*/
|
||||
struct usb_hcd hcd;
|
||||
};
|
||||
|
||||
#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef DEBUG
|
||||
#define STUB_DEBUG_FILES
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define ohci_dbg(ohci, fmt, args...) \
|
||||
dev_dbg ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_err(ohci, fmt, args...) \
|
||||
dev_err ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_info(ohci, fmt, args...) \
|
||||
dev_info ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_warn(ohci, fmt, args...) \
|
||||
dev_warn ((ohci)->hcd.controller , fmt , ## args )
|
||||
|
||||
#ifdef OHCI_VERBOSE_DEBUG
|
||||
# define ohci_vdbg ohci_dbg
|
||||
#else
|
||||
# define ohci_vdbg(ohci, fmt, args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB OHCI Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "ohci\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "ohci.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB OHCI Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "ohci\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "ohci.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Configs for OHCI
|
||||
*/
|
||||
|
||||
#define CONFIG_PCI
|
||||
/*
|
||||
* Configs for OHCI
|
||||
*/
|
||||
|
||||
#define CONFIG_PCI
|
||||
|
|
|
@ -1,309 +1,309 @@
|
|||
/*
|
||||
ReactOS specific functions for OHCI module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
#include "../linux/linux_wrapper.h"
|
||||
#include "ohci_main.h"
|
||||
|
||||
// declare basic init funcs
|
||||
void init_wrapper(struct pci_dev *probe_dev);
|
||||
int ohci_hcd_pci_init (void);
|
||||
void ohci_hcd_pci_cleanup (void);
|
||||
int STDCALL usb_init(void);
|
||||
void STDCALL usb_exit(void);
|
||||
extern struct pci_driver ohci_pci_driver;
|
||||
extern const struct pci_device_id pci_ids[];
|
||||
|
||||
|
||||
|
||||
// This should be removed, but for testing purposes it's here
|
||||
struct pci_dev *dev;
|
||||
//struct pci_device_id *dev_id;
|
||||
|
||||
|
||||
#define USB_OHCI_TAG TAG('u','s','b','o')
|
||||
|
||||
NTSTATUS STDCALL AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
|
||||
{
|
||||
PDEVICE_OBJECT fdo;
|
||||
NTSTATUS Status;
|
||||
WCHAR DeviceBuffer[20];
|
||||
UNICODE_STRING DeviceName;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
ULONG Size, DeviceNumber;
|
||||
|
||||
DPRINT1("ohci: AddDevice called\n");
|
||||
|
||||
// Allocate driver extension now
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
if (DriverExtension == NULL)
|
||||
{
|
||||
Status = IoAllocateDriverObjectExtension(
|
||||
DriverObject,
|
||||
DriverObject,
|
||||
sizeof(OHCI_DRIVER_EXTENSION),
|
||||
(PVOID *)&DriverExtension);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Allocating DriverObjectExtension failed.\n");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a unicode device name
|
||||
DeviceNumber = 0; //TODO: Allocate new device number every time
|
||||
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
|
||||
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
|
||||
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(OHCI_DEVICE_EXTENSION)/* + DriverExtension->InitializationData.HwDeviceExtensionSize*/,
|
||||
&DeviceName,
|
||||
FILE_DEVICE_CONTROLLER,
|
||||
0,
|
||||
FALSE,
|
||||
&fdo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// zerofill device extension
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)pdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
|
||||
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
|
||||
|
||||
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
// Initialize device extension
|
||||
DeviceExtension->DeviceNumber = DeviceNumber;
|
||||
DeviceExtension->PhysicalDeviceObject = pdo;
|
||||
DeviceExtension->FunctionalDeviceObject = fdo;
|
||||
DeviceExtension->DriverExtension = DriverExtension;
|
||||
|
||||
/* Get bus number from the upper level bus driver. */
|
||||
Size = sizeof(ULONG);
|
||||
Status = IoGetDeviceProperty(
|
||||
pdo,
|
||||
DevicePropertyBusNumber,
|
||||
Size,
|
||||
&DeviceExtension->SystemIoBusNumber,
|
||||
&Size);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Couldn't get an information from bus driver. Panic!!!\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Done AddDevice\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID STDCALL DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
DPRINT1("DriverUnload()\n");
|
||||
|
||||
// Exit usb device
|
||||
usb_exit();
|
||||
|
||||
// Remove device (ohci_pci_driver.remove)
|
||||
ohci_pci_driver.remove(dev);
|
||||
|
||||
ExFreePool(dev->slot_name);
|
||||
ExFreePool(dev);
|
||||
|
||||
// Perform some cleanup
|
||||
ohci_hcd_pci_cleanup();
|
||||
}
|
||||
|
||||
NTSTATUS InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// Fill generic linux structs
|
||||
dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_OHCI_TAG);
|
||||
|
||||
init_wrapper(dev);
|
||||
dev->irq = DeviceExtension->InterruptLevel;
|
||||
dev->dev_ext = (PVOID)DeviceExtension;
|
||||
dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_OHCI_TAG); // 128 max len for slot name
|
||||
|
||||
strcpy(dev->dev.name, "OpenHCI PCI-USB Controller");
|
||||
strcpy(dev->slot_name, "OHCD PCI Slot");
|
||||
|
||||
// Init the OHCI HCD. Probe will be called automatically, but will fail because id=NULL
|
||||
Status = ohci_hcd_pci_init();
|
||||
//FIXME: Check status returned value
|
||||
|
||||
// Init core usb
|
||||
usb_init();
|
||||
|
||||
// Probe device with real id now
|
||||
ohci_pci_driver.probe(dev, pci_ids);
|
||||
|
||||
DPRINT("InitLinuxWrapper() done\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
|
||||
/*
|
||||
* Get the initialization data we saved in VideoPortInitialize.
|
||||
*/
|
||||
DriverObject = DeviceObject->DriverObject;
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/*
|
||||
* Store some resources in the DeviceExtension.
|
||||
*/
|
||||
AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
|
||||
if (AllocatedResources != NULL)
|
||||
{
|
||||
CM_FULL_RESOURCE_DESCRIPTOR *FullList;
|
||||
CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
|
||||
ULONG ResourceCount;
|
||||
ULONG ResourceListSize;
|
||||
|
||||
/* Save the resource list */
|
||||
ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
|
||||
ResourceListSize =
|
||||
FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
|
||||
PartialDescriptors[ResourceCount]);
|
||||
DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
|
||||
if (DeviceExtension->AllocatedResources == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(DeviceExtension->AllocatedResources,
|
||||
AllocatedResources,
|
||||
ResourceListSize);
|
||||
|
||||
/* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
|
||||
for (FullList = AllocatedResources->List;
|
||||
FullList < AllocatedResources->List + AllocatedResources->Count;
|
||||
FullList++)
|
||||
{
|
||||
/* FIXME: Is this ASSERT ok for resources from the PNP manager? */
|
||||
/*ASSERT(FullList->InterfaceType == PCIBus &&
|
||||
FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
|
||||
1 == FullList->PartialResourceList.Version &&
|
||||
1 == FullList->PartialResourceList.Revision);*/
|
||||
for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
|
||||
Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
|
||||
Descriptor++)
|
||||
{
|
||||
if (Descriptor->Type == CmResourceTypeInterrupt)
|
||||
{
|
||||
DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
|
||||
DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
|
||||
}
|
||||
else if (Descriptor->Type == CmResourceTypeMemory)
|
||||
{
|
||||
DeviceExtension->BaseAddress = Descriptor->u.Memory.Start;
|
||||
DeviceExtension->BaseAddrLength = Descriptor->u.Memory.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINT1("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
|
||||
DeviceExtension->InterruptLevel,
|
||||
DeviceExtension->InterruptVector);
|
||||
|
||||
/*
|
||||
* Init wrapper with this object
|
||||
*/
|
||||
return InitLinuxWrapper(DeviceObject);
|
||||
}
|
||||
|
||||
// Dispatch PNP
|
||||
NTSTATUS STDCALL DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
NTSTATUS Status;
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (IrpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
|
||||
Status = OHCD_PnPStartDevice(DeviceObject, Irp);
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
IoDeleteDevice(DeviceObject); // just delete device for now
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||
{
|
||||
DbgPrint("IRP_MJ_POWER dispatch\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/*
|
||||
ReactOS specific functions for OHCI module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
#include "../linux/linux_wrapper.h"
|
||||
#include "ohci_main.h"
|
||||
|
||||
// declare basic init funcs
|
||||
void init_wrapper(struct pci_dev *probe_dev);
|
||||
int ohci_hcd_pci_init (void);
|
||||
void ohci_hcd_pci_cleanup (void);
|
||||
int STDCALL usb_init(void);
|
||||
void STDCALL usb_exit(void);
|
||||
extern struct pci_driver ohci_pci_driver;
|
||||
extern const struct pci_device_id pci_ids[];
|
||||
|
||||
|
||||
|
||||
// This should be removed, but for testing purposes it's here
|
||||
struct pci_dev *dev;
|
||||
//struct pci_device_id *dev_id;
|
||||
|
||||
|
||||
#define USB_OHCI_TAG TAG('u','s','b','o')
|
||||
|
||||
NTSTATUS STDCALL AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
|
||||
{
|
||||
PDEVICE_OBJECT fdo;
|
||||
NTSTATUS Status;
|
||||
WCHAR DeviceBuffer[20];
|
||||
UNICODE_STRING DeviceName;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
ULONG Size, DeviceNumber;
|
||||
|
||||
DPRINT1("ohci: AddDevice called\n");
|
||||
|
||||
// Allocate driver extension now
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
if (DriverExtension == NULL)
|
||||
{
|
||||
Status = IoAllocateDriverObjectExtension(
|
||||
DriverObject,
|
||||
DriverObject,
|
||||
sizeof(OHCI_DRIVER_EXTENSION),
|
||||
(PVOID *)&DriverExtension);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Allocating DriverObjectExtension failed.\n");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a unicode device name
|
||||
DeviceNumber = 0; //TODO: Allocate new device number every time
|
||||
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
|
||||
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
|
||||
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(OHCI_DEVICE_EXTENSION)/* + DriverExtension->InitializationData.HwDeviceExtensionSize*/,
|
||||
&DeviceName,
|
||||
FILE_DEVICE_CONTROLLER,
|
||||
0,
|
||||
FALSE,
|
||||
&fdo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// zerofill device extension
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)pdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
|
||||
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
|
||||
|
||||
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
// Initialize device extension
|
||||
DeviceExtension->DeviceNumber = DeviceNumber;
|
||||
DeviceExtension->PhysicalDeviceObject = pdo;
|
||||
DeviceExtension->FunctionalDeviceObject = fdo;
|
||||
DeviceExtension->DriverExtension = DriverExtension;
|
||||
|
||||
/* Get bus number from the upper level bus driver. */
|
||||
Size = sizeof(ULONG);
|
||||
Status = IoGetDeviceProperty(
|
||||
pdo,
|
||||
DevicePropertyBusNumber,
|
||||
Size,
|
||||
&DeviceExtension->SystemIoBusNumber,
|
||||
&Size);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Couldn't get an information from bus driver. Panic!!!\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Done AddDevice\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID STDCALL DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
DPRINT1("DriverUnload()\n");
|
||||
|
||||
// Exit usb device
|
||||
usb_exit();
|
||||
|
||||
// Remove device (ohci_pci_driver.remove)
|
||||
ohci_pci_driver.remove(dev);
|
||||
|
||||
ExFreePool(dev->slot_name);
|
||||
ExFreePool(dev);
|
||||
|
||||
// Perform some cleanup
|
||||
ohci_hcd_pci_cleanup();
|
||||
}
|
||||
|
||||
NTSTATUS InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// Fill generic linux structs
|
||||
dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_OHCI_TAG);
|
||||
|
||||
init_wrapper(dev);
|
||||
dev->irq = DeviceExtension->InterruptLevel;
|
||||
dev->dev_ext = (PVOID)DeviceExtension;
|
||||
dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_OHCI_TAG); // 128 max len for slot name
|
||||
|
||||
strcpy(dev->dev.name, "OpenHCI PCI-USB Controller");
|
||||
strcpy(dev->slot_name, "OHCD PCI Slot");
|
||||
|
||||
// Init the OHCI HCD. Probe will be called automatically, but will fail because id=NULL
|
||||
Status = ohci_hcd_pci_init();
|
||||
//FIXME: Check status returned value
|
||||
|
||||
// Init core usb
|
||||
usb_init();
|
||||
|
||||
// Probe device with real id now
|
||||
ohci_pci_driver.probe(dev, pci_ids);
|
||||
|
||||
DPRINT("InitLinuxWrapper() done\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
|
||||
/*
|
||||
* Get the initialization data we saved in VideoPortInitialize.
|
||||
*/
|
||||
DriverObject = DeviceObject->DriverObject;
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/*
|
||||
* Store some resources in the DeviceExtension.
|
||||
*/
|
||||
AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
|
||||
if (AllocatedResources != NULL)
|
||||
{
|
||||
CM_FULL_RESOURCE_DESCRIPTOR *FullList;
|
||||
CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
|
||||
ULONG ResourceCount;
|
||||
ULONG ResourceListSize;
|
||||
|
||||
/* Save the resource list */
|
||||
ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
|
||||
ResourceListSize =
|
||||
FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
|
||||
PartialDescriptors[ResourceCount]);
|
||||
DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
|
||||
if (DeviceExtension->AllocatedResources == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(DeviceExtension->AllocatedResources,
|
||||
AllocatedResources,
|
||||
ResourceListSize);
|
||||
|
||||
/* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
|
||||
for (FullList = AllocatedResources->List;
|
||||
FullList < AllocatedResources->List + AllocatedResources->Count;
|
||||
FullList++)
|
||||
{
|
||||
/* FIXME: Is this ASSERT ok for resources from the PNP manager? */
|
||||
/*ASSERT(FullList->InterfaceType == PCIBus &&
|
||||
FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
|
||||
1 == FullList->PartialResourceList.Version &&
|
||||
1 == FullList->PartialResourceList.Revision);*/
|
||||
for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
|
||||
Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
|
||||
Descriptor++)
|
||||
{
|
||||
if (Descriptor->Type == CmResourceTypeInterrupt)
|
||||
{
|
||||
DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
|
||||
DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
|
||||
}
|
||||
else if (Descriptor->Type == CmResourceTypeMemory)
|
||||
{
|
||||
DeviceExtension->BaseAddress = Descriptor->u.Memory.Start;
|
||||
DeviceExtension->BaseAddrLength = Descriptor->u.Memory.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINT1("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
|
||||
DeviceExtension->InterruptLevel,
|
||||
DeviceExtension->InterruptVector);
|
||||
|
||||
/*
|
||||
* Init wrapper with this object
|
||||
*/
|
||||
return InitLinuxWrapper(DeviceObject);
|
||||
}
|
||||
|
||||
// Dispatch PNP
|
||||
NTSTATUS STDCALL DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
NTSTATUS Status;
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (IrpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
|
||||
Status = OHCD_PnPStartDevice(DeviceObject, Irp);
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
IoDeleteDevice(DeviceObject); // just delete device for now
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||
{
|
||||
DbgPrint("IRP_MJ_POWER dispatch\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,46 +1,47 @@
|
|||
/*
|
||||
* OHCI WDM/PNP driver
|
||||
*
|
||||
* Copyright (C) 2005 ReactOS Team
|
||||
*
|
||||
* Author: Aleksey Bragin (aleksey@reactos.com)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OHCI_MAIN_H
|
||||
#define OHCI_MAIN_H
|
||||
|
||||
typedef struct _OHCI_DRIVER_EXTENSION
|
||||
{
|
||||
//OHCI_HW_INITIALIZATION_DATA InitializationData;
|
||||
PVOID HwContext;
|
||||
//UNICODE_STRING RegistryPath;
|
||||
} OHCI_DRIVER_EXTENSION, *POHCI_DRIVER_EXTENSION;
|
||||
|
||||
typedef struct _OHCI_DEVICE_EXTENSTION
|
||||
{
|
||||
ULONG DeviceNumber;
|
||||
PDEVICE_OBJECT PhysicalDeviceObject;
|
||||
PDEVICE_OBJECT FunctionalDeviceObject;
|
||||
PDEVICE_OBJECT NextDeviceObject;
|
||||
//UNICODE_STRING RegistryPath;
|
||||
PKINTERRUPT InterruptObject;
|
||||
KSPIN_LOCK InterruptSpinLock;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
ULONG InterruptVector;
|
||||
ULONG InterruptLevel;
|
||||
PHYSICAL_ADDRESS BaseAddress;
|
||||
ULONG BaseAddrLength;
|
||||
ULONG AdapterInterfaceType;
|
||||
ULONG SystemIoBusNumber;
|
||||
ULONG SystemIoSlotNumber;
|
||||
LIST_ENTRY AddressMappingListHead;
|
||||
//KDPC DpcObject;
|
||||
OHCI_DRIVER_EXTENSION *DriverExtension;
|
||||
ULONG DeviceOpened;
|
||||
//KMUTEX DeviceLock;
|
||||
//CHAR MiniPortDeviceExtension[1];
|
||||
} OHCI_DEVICE_EXTENSION, *POHCI_DEVICE_EXTENSION;
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
* OHCI WDM/PNP driver
|
||||
*
|
||||
* Copyright (C) 2005 ReactOS Team
|
||||
*
|
||||
* Author: Aleksey Bragin (aleksey@reactos.com)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OHCI_MAIN_H
|
||||
#define OHCI_MAIN_H
|
||||
|
||||
typedef struct _OHCI_DRIVER_EXTENSION
|
||||
{
|
||||
//OHCI_HW_INITIALIZATION_DATA InitializationData;
|
||||
PVOID HwContext;
|
||||
//UNICODE_STRING RegistryPath;
|
||||
} OHCI_DRIVER_EXTENSION, *POHCI_DRIVER_EXTENSION;
|
||||
|
||||
typedef struct _OHCI_DEVICE_EXTENSTION
|
||||
{
|
||||
ULONG DeviceNumber;
|
||||
PDEVICE_OBJECT PhysicalDeviceObject;
|
||||
PDEVICE_OBJECT FunctionalDeviceObject;
|
||||
PDEVICE_OBJECT NextDeviceObject;
|
||||
//UNICODE_STRING RegistryPath;
|
||||
PKINTERRUPT InterruptObject;
|
||||
KSPIN_LOCK InterruptSpinLock;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
ULONG InterruptVector;
|
||||
ULONG InterruptLevel;
|
||||
PHYSICAL_ADDRESS BaseAddress;
|
||||
ULONG BaseAddrLength;
|
||||
ULONG Flags;
|
||||
ULONG AdapterInterfaceType;
|
||||
ULONG SystemIoBusNumber;
|
||||
ULONG SystemIoSlotNumber;
|
||||
LIST_ENTRY AddressMappingListHead;
|
||||
//KDPC DpcObject;
|
||||
OHCI_DRIVER_EXTENSION *DriverExtension;
|
||||
ULONG DeviceOpened;
|
||||
//KMUTEX DeviceLock;
|
||||
//CHAR MiniPortDeviceExtension[1];
|
||||
} OHCI_DEVICE_EXTENSION, *POHCI_DEVICE_EXTENSION;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,384 +1,384 @@
|
|||
#ifndef _I386_BITOPS_H
|
||||
#define _I386_BITOPS_H
|
||||
|
||||
/*
|
||||
* Copyright 1992, Linus Torvalds.
|
||||
*/
|
||||
|
||||
//#include <linux/config.h>
|
||||
|
||||
/*
|
||||
* These have to be done with inline assembly: that way the bit-setting
|
||||
* is guaranteed to be atomic. All bit operations return 0 if the bit
|
||||
* was cleared before the operation and != 0 if it was not.
|
||||
*
|
||||
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define LOCK_PREFIX "lock ; "
|
||||
#else
|
||||
#define LOCK_PREFIX ""
|
||||
#endif
|
||||
|
||||
#define ADDR (*(volatile long *) addr)
|
||||
|
||||
/**
|
||||
* set_bit - Atomically set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is atomic and may not be reordered. See __set_bit()
|
||||
* if you do not require the atomic guarantees.
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* __set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* Unlike set_bit(), this function is non-atomic and may be reordered.
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__(
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* clear_bit() is atomic and may not be reordered. However, it does
|
||||
* not contain a memory barrier, so if it is used for locking purposes,
|
||||
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
|
||||
* in order to ensure changes are visible on other processors.
|
||||
*/
|
||||
static __inline__ void clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
#define smp_mb__before_clear_bit() barrier()
|
||||
#define smp_mb__after_clear_bit() barrier()
|
||||
|
||||
/**
|
||||
* __change_bit - Toggle a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* Unlike change_bit(), this function is non-atomic and may be reordered.
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* change_bit() is atomic and may not be reordered.
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
"btsl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
"btrl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/* WARNING: non atomic and it can be reordered! */
|
||||
static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"btcl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its new value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btcl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
#if 0 /* Fool kernel-doc since it doesn't do macros yet */
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static int test_bit(int nr, const volatile void * addr);
|
||||
#endif
|
||||
|
||||
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
|
||||
{
|
||||
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
|
||||
}
|
||||
|
||||
static __inline__ int variable_test_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"btl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit)
|
||||
:"m" (ADDR),"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
#define test_bit(nr,addr) \
|
||||
(__builtin_constant_p(nr) ? \
|
||||
constant_test_bit((nr),(addr)) : \
|
||||
variable_test_bit((nr),(addr)))
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit-number of the first zero bit, not the number of the byte
|
||||
* containing a bit.
|
||||
*/
|
||||
static __inline__ int find_first_zero_bit(void * addr, unsigned size)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
int res;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
/* This looks at memory. Mark it volatile to tell gcc not to move it around */
|
||||
__asm__ __volatile__(
|
||||
"movl $-1,%%eax\n\t"
|
||||
"xorl %%edx,%%edx\n\t"
|
||||
"repe; scasl\n\t"
|
||||
"je 1f\n\t"
|
||||
"xorl -4(%%edi),%%eax\n\t"
|
||||
"subl $4,%%edi\n\t"
|
||||
"bsfl %%eax,%%edx\n"
|
||||
"1:\tsubl %%ebx,%%edi\n\t"
|
||||
"shll $3,%%edi\n\t"
|
||||
"addl %%edi,%%edx"
|
||||
:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
|
||||
:"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The maximum size to search
|
||||
*/
|
||||
static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
|
||||
{
|
||||
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
|
||||
int set = 0, bit = offset & 31, res;
|
||||
|
||||
if (bit) {
|
||||
/*
|
||||
* Look for zero in first byte
|
||||
*/
|
||||
__asm__("bsfl %1,%0\n\t"
|
||||
"jne 1f\n\t"
|
||||
"movl $32, %0\n"
|
||||
"1:"
|
||||
: "=r" (set)
|
||||
: "r" (~(*p >> bit)));
|
||||
if (set < (32 - bit))
|
||||
return set + offset;
|
||||
set = 32 - bit;
|
||||
p++;
|
||||
}
|
||||
/*
|
||||
* No zero yet, search remaining full bytes for a zero
|
||||
*/
|
||||
res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
|
||||
return (offset + set + res);
|
||||
}
|
||||
|
||||
/**
|
||||
* ffz - find first zero in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||
*/
|
||||
static __inline__ unsigned long ffz(unsigned long word)
|
||||
{
|
||||
__asm__("bsfl %1,%0"
|
||||
:"=r" (word)
|
||||
:"r" (~word));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/**
|
||||
* ffs - find first bit set
|
||||
* @x: the word to search
|
||||
*
|
||||
* This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
static __inline__ int ffs(int x)
|
||||
{
|
||||
int r;
|
||||
|
||||
__asm__("bsfl %1,%0\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"movl $-1,%0\n"
|
||||
"1:" : "=r" (r) : "rm" (x));
|
||||
return r+1;
|
||||
}
|
||||
|
||||
/**
|
||||
* hweightN - returns the hamming weight of a N-bit word
|
||||
* @x: the word to weigh
|
||||
*
|
||||
* The Hamming Weight of a number is the total number of bits set in it.
|
||||
*/
|
||||
|
||||
#define hweight32(x) generic_hweight32(x)
|
||||
#define hweight16(x) generic_hweight16(x)
|
||||
#define hweight8(x) generic_hweight8(x)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define ext2_set_bit __test_and_set_bit
|
||||
#define ext2_clear_bit __test_and_clear_bit
|
||||
#define ext2_test_bit test_bit
|
||||
#define ext2_find_first_zero_bit find_first_zero_bit
|
||||
#define ext2_find_next_zero_bit find_next_zero_bit
|
||||
|
||||
/* Bitmap functions for the minix filesystem. */
|
||||
#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
|
||||
#define minix_set_bit(nr,addr) __set_bit(nr,addr)
|
||||
#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
|
||||
#define minix_test_bit(nr,addr) test_bit(nr,addr)
|
||||
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _I386_BITOPS_H */
|
||||
#ifndef _I386_BITOPS_H
|
||||
#define _I386_BITOPS_H
|
||||
|
||||
/*
|
||||
* Copyright 1992, Linus Torvalds.
|
||||
*/
|
||||
|
||||
//#include <linux/config.h>
|
||||
|
||||
/*
|
||||
* These have to be done with inline assembly: that way the bit-setting
|
||||
* is guaranteed to be atomic. All bit operations return 0 if the bit
|
||||
* was cleared before the operation and != 0 if it was not.
|
||||
*
|
||||
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define LOCK_PREFIX "lock ; "
|
||||
#else
|
||||
#define LOCK_PREFIX ""
|
||||
#endif
|
||||
|
||||
#define ADDR (*(volatile long *) addr)
|
||||
|
||||
/**
|
||||
* set_bit - Atomically set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is atomic and may not be reordered. See __set_bit()
|
||||
* if you do not require the atomic guarantees.
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* __set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* Unlike set_bit(), this function is non-atomic and may be reordered.
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__(
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* clear_bit() is atomic and may not be reordered. However, it does
|
||||
* not contain a memory barrier, so if it is used for locking purposes,
|
||||
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
|
||||
* in order to ensure changes are visible on other processors.
|
||||
*/
|
||||
static __inline__ void clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
#define smp_mb__before_clear_bit() barrier()
|
||||
#define smp_mb__after_clear_bit() barrier()
|
||||
|
||||
/**
|
||||
* __change_bit - Toggle a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* Unlike change_bit(), this function is non-atomic and may be reordered.
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* change_bit() is atomic and may not be reordered.
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
"btsl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
"btrl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/* WARNING: non atomic and it can be reordered! */
|
||||
static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"btcl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its new value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btcl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
#if 0 /* Fool kernel-doc since it doesn't do macros yet */
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static int test_bit(int nr, const volatile void * addr);
|
||||
#endif
|
||||
|
||||
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
|
||||
{
|
||||
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
|
||||
}
|
||||
|
||||
static __inline__ int variable_test_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"btl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit)
|
||||
:"m" (ADDR),"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
#define test_bit(nr,addr) \
|
||||
(__builtin_constant_p(nr) ? \
|
||||
constant_test_bit((nr),(addr)) : \
|
||||
variable_test_bit((nr),(addr)))
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit-number of the first zero bit, not the number of the byte
|
||||
* containing a bit.
|
||||
*/
|
||||
static __inline__ int find_first_zero_bit(void * addr, unsigned size)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
int res;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
/* This looks at memory. Mark it volatile to tell gcc not to move it around */
|
||||
__asm__ __volatile__(
|
||||
"movl $-1,%%eax\n\t"
|
||||
"xorl %%edx,%%edx\n\t"
|
||||
"repe; scasl\n\t"
|
||||
"je 1f\n\t"
|
||||
"xorl -4(%%edi),%%eax\n\t"
|
||||
"subl $4,%%edi\n\t"
|
||||
"bsfl %%eax,%%edx\n"
|
||||
"1:\tsubl %%ebx,%%edi\n\t"
|
||||
"shll $3,%%edi\n\t"
|
||||
"addl %%edi,%%edx"
|
||||
:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
|
||||
:"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The maximum size to search
|
||||
*/
|
||||
static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
|
||||
{
|
||||
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
|
||||
int set = 0, bit = offset & 31, res;
|
||||
|
||||
if (bit) {
|
||||
/*
|
||||
* Look for zero in first byte
|
||||
*/
|
||||
__asm__("bsfl %1,%0\n\t"
|
||||
"jne 1f\n\t"
|
||||
"movl $32, %0\n"
|
||||
"1:"
|
||||
: "=r" (set)
|
||||
: "r" (~(*p >> bit)));
|
||||
if (set < (32 - bit))
|
||||
return set + offset;
|
||||
set = 32 - bit;
|
||||
p++;
|
||||
}
|
||||
/*
|
||||
* No zero yet, search remaining full bytes for a zero
|
||||
*/
|
||||
res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
|
||||
return (offset + set + res);
|
||||
}
|
||||
|
||||
/**
|
||||
* ffz - find first zero in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||
*/
|
||||
static __inline__ unsigned long ffz(unsigned long word)
|
||||
{
|
||||
__asm__("bsfl %1,%0"
|
||||
:"=r" (word)
|
||||
:"r" (~word));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/**
|
||||
* ffs - find first bit set
|
||||
* @x: the word to search
|
||||
*
|
||||
* This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
static __inline__ int ffs(int x)
|
||||
{
|
||||
int r;
|
||||
|
||||
__asm__("bsfl %1,%0\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"movl $-1,%0\n"
|
||||
"1:" : "=r" (r) : "rm" (x));
|
||||
return r+1;
|
||||
}
|
||||
|
||||
/**
|
||||
* hweightN - returns the hamming weight of a N-bit word
|
||||
* @x: the word to weigh
|
||||
*
|
||||
* The Hamming Weight of a number is the total number of bits set in it.
|
||||
*/
|
||||
|
||||
#define hweight32(x) generic_hweight32(x)
|
||||
#define hweight16(x) generic_hweight16(x)
|
||||
#define hweight8(x) generic_hweight8(x)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define ext2_set_bit __test_and_set_bit
|
||||
#define ext2_clear_bit __test_and_clear_bit
|
||||
#define ext2_test_bit test_bit
|
||||
#define ext2_find_first_zero_bit find_first_zero_bit
|
||||
#define ext2_find_next_zero_bit find_next_zero_bit
|
||||
|
||||
/* Bitmap functions for the minix filesystem. */
|
||||
#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
|
||||
#define minix_set_bit(nr,addr) __set_bit(nr,addr)
|
||||
#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
|
||||
#define minix_test_bit(nr,addr) test_bit(nr,addr)
|
||||
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _I386_BITOPS_H */
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
#ifndef _LINUX_BITOPS_H
|
||||
#define _LINUX_BITOPS_H
|
||||
|
||||
|
||||
/*
|
||||
* ffs: find first bit set. This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
|
||||
static inline int generic_ffs(int x)
|
||||
{
|
||||
int r = 1;
|
||||
|
||||
if (!x)
|
||||
return 0;
|
||||
if (!(x & 0xffff)) {
|
||||
x >>= 16;
|
||||
r += 16;
|
||||
}
|
||||
if (!(x & 0xff)) {
|
||||
x >>= 8;
|
||||
r += 8;
|
||||
}
|
||||
if (!(x & 0xf)) {
|
||||
x >>= 4;
|
||||
r += 4;
|
||||
}
|
||||
if (!(x & 3)) {
|
||||
x >>= 2;
|
||||
r += 2;
|
||||
}
|
||||
if (!(x & 1)) {
|
||||
x >>= 1;
|
||||
r += 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* hweightN: returns the hamming weight (i.e. the number
|
||||
* of bits set) of a N-bit word
|
||||
*/
|
||||
|
||||
static inline unsigned int generic_hweight32(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
|
||||
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
|
||||
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
|
||||
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight16(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
|
||||
res = (res & 0x3333) + ((res >> 2) & 0x3333);
|
||||
res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
|
||||
return (res & 0x00FF) + ((res >> 8) & 0x00FF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight8(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
|
||||
res = (res & 0x33) + ((res >> 2) & 0x33);
|
||||
return (res & 0x0F) + ((res >> 4) & 0x0F);
|
||||
}
|
||||
|
||||
#include "asm/bitops.h"
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef _LINUX_BITOPS_H
|
||||
#define _LINUX_BITOPS_H
|
||||
|
||||
|
||||
/*
|
||||
* ffs: find first bit set. This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
|
||||
static inline int generic_ffs(int x)
|
||||
{
|
||||
int r = 1;
|
||||
|
||||
if (!x)
|
||||
return 0;
|
||||
if (!(x & 0xffff)) {
|
||||
x >>= 16;
|
||||
r += 16;
|
||||
}
|
||||
if (!(x & 0xff)) {
|
||||
x >>= 8;
|
||||
r += 8;
|
||||
}
|
||||
if (!(x & 0xf)) {
|
||||
x >>= 4;
|
||||
r += 4;
|
||||
}
|
||||
if (!(x & 3)) {
|
||||
x >>= 2;
|
||||
r += 2;
|
||||
}
|
||||
if (!(x & 1)) {
|
||||
x >>= 1;
|
||||
r += 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* hweightN: returns the hamming weight (i.e. the number
|
||||
* of bits set) of a N-bit word
|
||||
*/
|
||||
|
||||
static inline unsigned int generic_hweight32(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
|
||||
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
|
||||
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
|
||||
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight16(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
|
||||
res = (res & 0x3333) + ((res >> 2) & 0x3333);
|
||||
res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
|
||||
return (res & 0x00FF) + ((res >> 8) & 0x00FF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight8(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
|
||||
res = (res & 0x33) + ((res >> 2) & 0x33);
|
||||
return (res & 0x0F) + ((res >> 4) & 0x0F);
|
||||
}
|
||||
|
||||
#include "asm/bitops.h"
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,337 +1,337 @@
|
|||
#ifndef _Boot_H_
|
||||
#define _Boot_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/***************************************************************************
|
||||
Includes used by XBox boot code
|
||||
***************************************************************************/
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/////////////////////////////////
|
||||
// configuration
|
||||
|
||||
#include "consts.h"
|
||||
#include "stdint.h"
|
||||
#include "cromwell_types.h"
|
||||
|
||||
|
||||
unsigned int cromwell_config;
|
||||
unsigned int cromwell_retryload;
|
||||
unsigned int cromwell_loadbank;
|
||||
unsigned int cromwell_Biostype;
|
||||
|
||||
unsigned int xbox_ram;
|
||||
|
||||
#define XROMWELL 0
|
||||
#define CROMWELL 1
|
||||
|
||||
#define ICON_WIDTH 64
|
||||
#define ICON_HEIGHT 64
|
||||
/*
|
||||
static double min (double a, double b)
|
||||
{
|
||||
if (a < b) return a; else return b;
|
||||
}
|
||||
|
||||
static inline double max (double a, double b)
|
||||
{
|
||||
if (a > b) return a; else return b;
|
||||
}
|
||||
*/
|
||||
//#include "iso_fs.h"
|
||||
//#include "BootVideo.h"
|
||||
|
||||
//#define ASSERT(exp) { if(!(exp)) { bprintf("Assert failed file " __FILE__ " line %d\n", __LINE__); } }
|
||||
|
||||
#if 0
|
||||
extern volatile CURRENT_VIDEO_MODE_DETAILS vmode;
|
||||
unsigned int video_encoder;
|
||||
|
||||
volatile u32 VIDEO_CURSOR_POSX;
|
||||
volatile u32 VIDEO_CURSOR_POSY;
|
||||
volatile u32 VIDEO_ATTR;
|
||||
volatile u32 VIDEO_LUMASCALING;
|
||||
volatile u32 VIDEO_RSCALING;
|
||||
volatile u32 VIDEO_BSCALING;
|
||||
volatile u32 BIOS_TICK_COUNT;
|
||||
volatile u32 VIDEO_VSYNC_POSITION;
|
||||
volatile u32 VIDEO_VSYNC_DIR;
|
||||
volatile u32 DVD_TRAY_STATE;
|
||||
|
||||
u8 VIDEO_AV_MODE ;
|
||||
|
||||
#define DVD_CLOSED 0
|
||||
#define DVD_CLOSING 1
|
||||
#define DVD_OPEN 2
|
||||
#define DVD_OPENING 3
|
||||
|
||||
/////////////////////////////////
|
||||
// Superfunky i386 internal structures
|
||||
|
||||
typedef struct gdt_t {
|
||||
unsigned short m_wSize __attribute__ ((packed));
|
||||
unsigned long m_dwBase32 __attribute__ ((packed));
|
||||
unsigned short m_wDummy __attribute__ ((packed));
|
||||
} ts_descriptor_pointer;
|
||||
|
||||
typedef struct { // inside an 8-byte protected mode interrupt vector
|
||||
u16 m_wHandlerHighAddressLow16;
|
||||
u16 m_wSelector;
|
||||
u16 m_wType;
|
||||
u16 m_wHandlerLinearAddressHigh16;
|
||||
} ts_pm_interrupt;
|
||||
|
||||
typedef enum {
|
||||
EDT_UNKNOWN= 0,
|
||||
EDT_XBOXFS
|
||||
} enumDriveType;
|
||||
|
||||
typedef struct tsHarddiskInfo { // this is the retained knowledge about an IDE device after init
|
||||
unsigned short m_fwPortBase;
|
||||
unsigned short m_wCountHeads;
|
||||
unsigned short m_wCountCylinders;
|
||||
unsigned short m_wCountSectorsPerTrack;
|
||||
unsigned long m_dwCountSectorsTotal; /* total */
|
||||
unsigned char m_bLbaMode; /* am i lba (0x40) or chs (0x00) */
|
||||
unsigned char m_szIdentityModelNumber[40];
|
||||
unsigned char term_space_1[2];
|
||||
unsigned char m_szSerial[20];
|
||||
unsigned char term_space_2[2];
|
||||
char m_szFirmware[8];
|
||||
unsigned char term_space_3[2];
|
||||
unsigned char m_fDriveExists;
|
||||
unsigned char m_fAtapi; // true if a CDROM, etc
|
||||
enumDriveType m_enumDriveType;
|
||||
unsigned char m_bCableConductors; // valid for device 0 if present
|
||||
unsigned short m_wAtaRevisionSupported;
|
||||
unsigned char s_length;
|
||||
unsigned char m_length;
|
||||
unsigned char m_fHasMbr;
|
||||
unsigned short m_securitySettings; //This contains the contents of the ATA security regs
|
||||
} tsHarddiskInfo;
|
||||
|
||||
/////////////////////////////////
|
||||
// LED-flashing codes
|
||||
// or these together as argument to I2cSetFrontpanelLed
|
||||
|
||||
enum {
|
||||
I2C_LED_RED0 = 0x80,
|
||||
I2C_LED_RED1 = 0x40,
|
||||
I2C_LED_RED2 = 0x20,
|
||||
I2C_LED_RED3 = 0x10,
|
||||
I2C_LED_GREEN0 = 0x08,
|
||||
I2C_LED_GREEN1 = 0x04,
|
||||
I2C_LED_GREEN2 = 0x02,
|
||||
I2C_LED_GREEN3 = 0x01
|
||||
};
|
||||
|
||||
///////////////////////////////
|
||||
/* BIOS-wide error codes all have b31 set */
|
||||
|
||||
enum {
|
||||
ERR_SUCCESS = 0, // completed without error
|
||||
|
||||
ERR_I2C_ERROR_TIMEOUT = 0x80000001, // I2C action failed because it did not complete in a reasonable time
|
||||
ERR_I2C_ERROR_BUS = 0x80000002, // I2C action failed due to non retryable bus error
|
||||
|
||||
ERR_BOOT_PIC_ALG_BROKEN = 0x80000101 // PIC algorithm did not pass its self-test
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
// some Boot API prototypes
|
||||
|
||||
//////// BootPerformPicChallengeResponseAction.c
|
||||
|
||||
/* ---------------------------- IO primitives -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
static __inline void IoOutputByte(u16 wAds, u8 bValue) {
|
||||
// __asm__ (" out %%al,%%dx" : : "edx" (dwAds), "al" (bValue) );
|
||||
__asm__ __volatile__ ("outb %b0,%w1": :"a" (bValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
static __inline void IoOutputWord(u16 wAds, u16 wValue) {
|
||||
// __asm__ (" out %%ax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
|
||||
__asm__ __volatile__ ("outw %0,%w1": :"a" (wValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
static __inline void IoOutputDword(u16 wAds, u32 dwValue) {
|
||||
// __asm__ (" out %%eax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
|
||||
__asm__ __volatile__ ("outl %0,%w1": :"a" (dwValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
|
||||
static __inline u8 IoInputByte(u16 wAds) {
|
||||
unsigned char _v;
|
||||
|
||||
__asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
static __inline u16 IoInputWord(u16 wAds) {
|
||||
u16 _v;
|
||||
|
||||
__asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
static __inline u32 IoInputDword(u16 wAds) {
|
||||
u32 _v;
|
||||
|
||||
__asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
#define rdmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("rdmsr" \
|
||||
: "=a" (val1), "=d" (val2) \
|
||||
: "c" (msr))
|
||||
|
||||
#define wrmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("wrmsr" \
|
||||
: /* no outputs */ \
|
||||
: "c" (msr), "a" (val1), "d" (val2))
|
||||
|
||||
|
||||
void BootPciInterruptEnable(void);
|
||||
|
||||
// boot process
|
||||
int BootPerformPicChallengeResponseAction(void);
|
||||
// LED control (see associated enum above)
|
||||
int I2cSetFrontpanelLed(u8 b);
|
||||
|
||||
#define bprintf(...)
|
||||
|
||||
#if PRINT_TRACE
|
||||
#define TRACE bprintf(__FILE__ " :%d\n\r",__LINE__);
|
||||
#else
|
||||
#define TRACE
|
||||
#endif
|
||||
|
||||
typedef struct _LIST_ENTRY {
|
||||
struct _LIST_ENTRY *m_plistentryNext;
|
||||
struct _LIST_ENTRY *m_plistentryPrevious;
|
||||
} LIST_ENTRY;
|
||||
|
||||
void ListEntryInsertAfterCurrent(LIST_ENTRY *plistentryCurrent, LIST_ENTRY *plistentryNew);
|
||||
void ListEntryRemove(LIST_ENTRY *plistentryCurrent);
|
||||
|
||||
////////// BootPerformXCodeActions.c
|
||||
|
||||
int BootPerformXCodeActions(void);
|
||||
|
||||
#include "BootEEPROM.h"
|
||||
#include "BootParser.h"
|
||||
|
||||
////////// BootStartBios.c
|
||||
|
||||
void StartBios(CONFIGENTRY *config,int nActivePartition, int nFATXPresent,int bootfrom);
|
||||
int BootMenu(CONFIGENTRY *config,int nDrive,int nActivePartition, int nFATXPresent);
|
||||
|
||||
////////// BootResetActions.c
|
||||
void ClearIDT (void);
|
||||
void BootResetAction(void);
|
||||
void BootCpuCache(bool fEnable) ;
|
||||
int printk(const char *szFormat, ...);
|
||||
void BiosCmosWrite(u8 bAds, u8 bData);
|
||||
u8 BiosCmosRead(u8 bAds);
|
||||
|
||||
|
||||
///////// BootPciPeripheralInitialization.c
|
||||
void BootPciPeripheralInitialization(void);
|
||||
void BootAGPBUSInitialization(void);
|
||||
void BootDetectMemorySize(void);
|
||||
extern void ReadPCIByte(unsigned int bus, unsigned int dev, unsigned intfunc, unsigned int reg_off, unsigned char *pbyteval);
|
||||
extern void WritePCIByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char byteval);
|
||||
extern void ReadPCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int *pdwordval);
|
||||
extern void WritePCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dwordval);
|
||||
extern void ReadPCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
|
||||
extern void WritePCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
|
||||
|
||||
void PciWriteByte (unsigned int bus, unsigned int dev, unsigned int func,
|
||||
unsigned int reg_off, unsigned char byteval);
|
||||
u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
|
||||
u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u32 dw);
|
||||
u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
|
||||
|
||||
///////// BootPerformPicChallengeResponseAction.c
|
||||
|
||||
int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite);
|
||||
int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite);
|
||||
bool I2CGetTemperature(int *, int *);
|
||||
void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask);
|
||||
|
||||
///////// BootIde.c
|
||||
|
||||
extern tsHarddiskInfo tsaHarddiskInfo[]; // static struct stores data about attached drives
|
||||
int BootIdeInit(void);
|
||||
int BootIdeReadSector(int nDriveIndex, void * pbBuffer, unsigned int block, int byte_offset, int n_bytes);
|
||||
int BootIdeBootSectorHddOrElTorito(int nDriveIndex, u8 * pbaResult);
|
||||
int BootIdeAtapiAdditionalSenseCode(int nDrive, u8 * pba, int nLengthMaxReturn);
|
||||
int BootIdeSetTransferMode(int nIndexDrive, int nMode);
|
||||
int BootIdeWaitNotBusy(unsigned uIoBase);
|
||||
bool BootIdeAtapiReportFriendlyError(int nDriveIndex, char * szErrorReturn, int nMaxLengthError);
|
||||
void BootIdeAtapiPrintkFriendlyError(int nDriveIndex);
|
||||
|
||||
///////// BootUSB.c
|
||||
|
||||
void BootStopUSB(void);
|
||||
void BootStartUSB(void);
|
||||
void USBGetEvents(void);
|
||||
|
||||
#include "xpad.h"
|
||||
|
||||
extern struct xpad_data XPAD_current[4];
|
||||
extern struct xpad_data XPAD_last[4];
|
||||
|
||||
extern void wait_ms(u32 ticks);
|
||||
extern void wait_us(u32 ticks);
|
||||
extern void wait_smalldelay(void);
|
||||
|
||||
|
||||
void * memcpy(void *dest, const void *src, size_t size);
|
||||
void * memset(void *dest, int data, size_t size);
|
||||
int memcmp(const void *buffer1, const void *buffer2, size_t num);
|
||||
int _strncmp(const char *sz1, const char *sz2, int nMax);
|
||||
char * strcpy(char *sz, const char *szc);
|
||||
char * _strncpy (char * dest, const char * src, size_t n);
|
||||
void chrreplace(char *string, char search, char ch);
|
||||
|
||||
#define printf printk
|
||||
#define sleep wait_ms
|
||||
int tolower(int ch);
|
||||
int isspace (int c);
|
||||
|
||||
void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength);
|
||||
void * malloc(size_t size);
|
||||
void free(void *);
|
||||
|
||||
extern volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde;
|
||||
extern volatile bool fSeenPowerdown;
|
||||
typedef enum {
|
||||
ETS_OPEN_OR_OPENING=0,
|
||||
ETS_CLOSING,
|
||||
ETS_CLOSED
|
||||
} TRAY_STATE;
|
||||
extern volatile TRAY_STATE traystate;
|
||||
|
||||
|
||||
extern void BootInterruptsWriteIdt(void);
|
||||
#endif
|
||||
int copy_swap_trim(unsigned char *dst, unsigned char *src, int len);
|
||||
void HMAC_SHA1( unsigned char *result,
|
||||
unsigned char *key, int key_length,
|
||||
unsigned char *text1, int text1_length,
|
||||
unsigned char *text2, int text2_length );
|
||||
|
||||
char *strrchr0(char *string, char ch);
|
||||
|
||||
#endif // _Boot_H_
|
||||
#ifndef _Boot_H_
|
||||
#define _Boot_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/***************************************************************************
|
||||
Includes used by XBox boot code
|
||||
***************************************************************************/
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/////////////////////////////////
|
||||
// configuration
|
||||
|
||||
#include "consts.h"
|
||||
#include "stdint.h"
|
||||
#include "cromwell_types.h"
|
||||
|
||||
|
||||
unsigned int cromwell_config;
|
||||
unsigned int cromwell_retryload;
|
||||
unsigned int cromwell_loadbank;
|
||||
unsigned int cromwell_Biostype;
|
||||
|
||||
unsigned int xbox_ram;
|
||||
|
||||
#define XROMWELL 0
|
||||
#define CROMWELL 1
|
||||
|
||||
#define ICON_WIDTH 64
|
||||
#define ICON_HEIGHT 64
|
||||
/*
|
||||
static double min (double a, double b)
|
||||
{
|
||||
if (a < b) return a; else return b;
|
||||
}
|
||||
|
||||
static inline double max (double a, double b)
|
||||
{
|
||||
if (a > b) return a; else return b;
|
||||
}
|
||||
*/
|
||||
//#include "iso_fs.h"
|
||||
//#include "BootVideo.h"
|
||||
|
||||
//#define ASSERT(exp) { if(!(exp)) { bprintf("Assert failed file " __FILE__ " line %d\n", __LINE__); } }
|
||||
|
||||
#if 0
|
||||
extern volatile CURRENT_VIDEO_MODE_DETAILS vmode;
|
||||
unsigned int video_encoder;
|
||||
|
||||
volatile u32 VIDEO_CURSOR_POSX;
|
||||
volatile u32 VIDEO_CURSOR_POSY;
|
||||
volatile u32 VIDEO_ATTR;
|
||||
volatile u32 VIDEO_LUMASCALING;
|
||||
volatile u32 VIDEO_RSCALING;
|
||||
volatile u32 VIDEO_BSCALING;
|
||||
volatile u32 BIOS_TICK_COUNT;
|
||||
volatile u32 VIDEO_VSYNC_POSITION;
|
||||
volatile u32 VIDEO_VSYNC_DIR;
|
||||
volatile u32 DVD_TRAY_STATE;
|
||||
|
||||
u8 VIDEO_AV_MODE ;
|
||||
|
||||
#define DVD_CLOSED 0
|
||||
#define DVD_CLOSING 1
|
||||
#define DVD_OPEN 2
|
||||
#define DVD_OPENING 3
|
||||
|
||||
/////////////////////////////////
|
||||
// Superfunky i386 internal structures
|
||||
|
||||
typedef struct gdt_t {
|
||||
unsigned short m_wSize __attribute__ ((packed));
|
||||
unsigned long m_dwBase32 __attribute__ ((packed));
|
||||
unsigned short m_wDummy __attribute__ ((packed));
|
||||
} ts_descriptor_pointer;
|
||||
|
||||
typedef struct { // inside an 8-byte protected mode interrupt vector
|
||||
u16 m_wHandlerHighAddressLow16;
|
||||
u16 m_wSelector;
|
||||
u16 m_wType;
|
||||
u16 m_wHandlerLinearAddressHigh16;
|
||||
} ts_pm_interrupt;
|
||||
|
||||
typedef enum {
|
||||
EDT_UNKNOWN= 0,
|
||||
EDT_XBOXFS
|
||||
} enumDriveType;
|
||||
|
||||
typedef struct tsHarddiskInfo { // this is the retained knowledge about an IDE device after init
|
||||
unsigned short m_fwPortBase;
|
||||
unsigned short m_wCountHeads;
|
||||
unsigned short m_wCountCylinders;
|
||||
unsigned short m_wCountSectorsPerTrack;
|
||||
unsigned long m_dwCountSectorsTotal; /* total */
|
||||
unsigned char m_bLbaMode; /* am i lba (0x40) or chs (0x00) */
|
||||
unsigned char m_szIdentityModelNumber[40];
|
||||
unsigned char term_space_1[2];
|
||||
unsigned char m_szSerial[20];
|
||||
unsigned char term_space_2[2];
|
||||
char m_szFirmware[8];
|
||||
unsigned char term_space_3[2];
|
||||
unsigned char m_fDriveExists;
|
||||
unsigned char m_fAtapi; // true if a CDROM, etc
|
||||
enumDriveType m_enumDriveType;
|
||||
unsigned char m_bCableConductors; // valid for device 0 if present
|
||||
unsigned short m_wAtaRevisionSupported;
|
||||
unsigned char s_length;
|
||||
unsigned char m_length;
|
||||
unsigned char m_fHasMbr;
|
||||
unsigned short m_securitySettings; //This contains the contents of the ATA security regs
|
||||
} tsHarddiskInfo;
|
||||
|
||||
/////////////////////////////////
|
||||
// LED-flashing codes
|
||||
// or these together as argument to I2cSetFrontpanelLed
|
||||
|
||||
enum {
|
||||
I2C_LED_RED0 = 0x80,
|
||||
I2C_LED_RED1 = 0x40,
|
||||
I2C_LED_RED2 = 0x20,
|
||||
I2C_LED_RED3 = 0x10,
|
||||
I2C_LED_GREEN0 = 0x08,
|
||||
I2C_LED_GREEN1 = 0x04,
|
||||
I2C_LED_GREEN2 = 0x02,
|
||||
I2C_LED_GREEN3 = 0x01
|
||||
};
|
||||
|
||||
///////////////////////////////
|
||||
/* BIOS-wide error codes all have b31 set */
|
||||
|
||||
enum {
|
||||
ERR_SUCCESS = 0, // completed without error
|
||||
|
||||
ERR_I2C_ERROR_TIMEOUT = 0x80000001, // I2C action failed because it did not complete in a reasonable time
|
||||
ERR_I2C_ERROR_BUS = 0x80000002, // I2C action failed due to non retryable bus error
|
||||
|
||||
ERR_BOOT_PIC_ALG_BROKEN = 0x80000101 // PIC algorithm did not pass its self-test
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
// some Boot API prototypes
|
||||
|
||||
//////// BootPerformPicChallengeResponseAction.c
|
||||
|
||||
/* ---------------------------- IO primitives -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
static __inline void IoOutputByte(u16 wAds, u8 bValue) {
|
||||
// __asm__ (" out %%al,%%dx" : : "edx" (dwAds), "al" (bValue) );
|
||||
__asm__ __volatile__ ("outb %b0,%w1": :"a" (bValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
static __inline void IoOutputWord(u16 wAds, u16 wValue) {
|
||||
// __asm__ (" out %%ax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
|
||||
__asm__ __volatile__ ("outw %0,%w1": :"a" (wValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
static __inline void IoOutputDword(u16 wAds, u32 dwValue) {
|
||||
// __asm__ (" out %%eax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
|
||||
__asm__ __volatile__ ("outl %0,%w1": :"a" (dwValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
|
||||
static __inline u8 IoInputByte(u16 wAds) {
|
||||
unsigned char _v;
|
||||
|
||||
__asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
static __inline u16 IoInputWord(u16 wAds) {
|
||||
u16 _v;
|
||||
|
||||
__asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
static __inline u32 IoInputDword(u16 wAds) {
|
||||
u32 _v;
|
||||
|
||||
__asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
#define rdmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("rdmsr" \
|
||||
: "=a" (val1), "=d" (val2) \
|
||||
: "c" (msr))
|
||||
|
||||
#define wrmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("wrmsr" \
|
||||
: /* no outputs */ \
|
||||
: "c" (msr), "a" (val1), "d" (val2))
|
||||
|
||||
|
||||
void BootPciInterruptEnable(void);
|
||||
|
||||
// boot process
|
||||
int BootPerformPicChallengeResponseAction(void);
|
||||
// LED control (see associated enum above)
|
||||
int I2cSetFrontpanelLed(u8 b);
|
||||
|
||||
#define bprintf(...)
|
||||
|
||||
#if PRINT_TRACE
|
||||
#define TRACE bprintf(__FILE__ " :%d\n\r",__LINE__);
|
||||
#else
|
||||
#define TRACE
|
||||
#endif
|
||||
|
||||
typedef struct _LIST_ENTRY {
|
||||
struct _LIST_ENTRY *m_plistentryNext;
|
||||
struct _LIST_ENTRY *m_plistentryPrevious;
|
||||
} LIST_ENTRY;
|
||||
|
||||
void ListEntryInsertAfterCurrent(LIST_ENTRY *plistentryCurrent, LIST_ENTRY *plistentryNew);
|
||||
void ListEntryRemove(LIST_ENTRY *plistentryCurrent);
|
||||
|
||||
////////// BootPerformXCodeActions.c
|
||||
|
||||
int BootPerformXCodeActions(void);
|
||||
|
||||
#include "BootEEPROM.h"
|
||||
#include "BootParser.h"
|
||||
|
||||
////////// BootStartBios.c
|
||||
|
||||
void StartBios(CONFIGENTRY *config,int nActivePartition, int nFATXPresent,int bootfrom);
|
||||
int BootMenu(CONFIGENTRY *config,int nDrive,int nActivePartition, int nFATXPresent);
|
||||
|
||||
////////// BootResetActions.c
|
||||
void ClearIDT (void);
|
||||
void BootResetAction(void);
|
||||
void BootCpuCache(bool fEnable) ;
|
||||
int printk(const char *szFormat, ...);
|
||||
void BiosCmosWrite(u8 bAds, u8 bData);
|
||||
u8 BiosCmosRead(u8 bAds);
|
||||
|
||||
|
||||
///////// BootPciPeripheralInitialization.c
|
||||
void BootPciPeripheralInitialization(void);
|
||||
void BootAGPBUSInitialization(void);
|
||||
void BootDetectMemorySize(void);
|
||||
extern void ReadPCIByte(unsigned int bus, unsigned int dev, unsigned intfunc, unsigned int reg_off, unsigned char *pbyteval);
|
||||
extern void WritePCIByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char byteval);
|
||||
extern void ReadPCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int *pdwordval);
|
||||
extern void WritePCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dwordval);
|
||||
extern void ReadPCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
|
||||
extern void WritePCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
|
||||
|
||||
void PciWriteByte (unsigned int bus, unsigned int dev, unsigned int func,
|
||||
unsigned int reg_off, unsigned char byteval);
|
||||
u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
|
||||
u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u32 dw);
|
||||
u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
|
||||
|
||||
///////// BootPerformPicChallengeResponseAction.c
|
||||
|
||||
int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite);
|
||||
int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite);
|
||||
bool I2CGetTemperature(int *, int *);
|
||||
void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask);
|
||||
|
||||
///////// BootIde.c
|
||||
|
||||
extern tsHarddiskInfo tsaHarddiskInfo[]; // static struct stores data about attached drives
|
||||
int BootIdeInit(void);
|
||||
int BootIdeReadSector(int nDriveIndex, void * pbBuffer, unsigned int block, int byte_offset, int n_bytes);
|
||||
int BootIdeBootSectorHddOrElTorito(int nDriveIndex, u8 * pbaResult);
|
||||
int BootIdeAtapiAdditionalSenseCode(int nDrive, u8 * pba, int nLengthMaxReturn);
|
||||
int BootIdeSetTransferMode(int nIndexDrive, int nMode);
|
||||
int BootIdeWaitNotBusy(unsigned uIoBase);
|
||||
bool BootIdeAtapiReportFriendlyError(int nDriveIndex, char * szErrorReturn, int nMaxLengthError);
|
||||
void BootIdeAtapiPrintkFriendlyError(int nDriveIndex);
|
||||
|
||||
///////// BootUSB.c
|
||||
|
||||
void BootStopUSB(void);
|
||||
void BootStartUSB(void);
|
||||
void USBGetEvents(void);
|
||||
|
||||
#include "xpad.h"
|
||||
|
||||
extern struct xpad_data XPAD_current[4];
|
||||
extern struct xpad_data XPAD_last[4];
|
||||
|
||||
extern void wait_ms(u32 ticks);
|
||||
extern void wait_us(u32 ticks);
|
||||
extern void wait_smalldelay(void);
|
||||
|
||||
|
||||
void * memcpy(void *dest, const void *src, size_t size);
|
||||
void * memset(void *dest, int data, size_t size);
|
||||
int memcmp(const void *buffer1, const void *buffer2, size_t num);
|
||||
int _strncmp(const char *sz1, const char *sz2, int nMax);
|
||||
char * strcpy(char *sz, const char *szc);
|
||||
char * _strncpy (char * dest, const char * src, size_t n);
|
||||
void chrreplace(char *string, char search, char ch);
|
||||
|
||||
#define printf printk
|
||||
#define sleep wait_ms
|
||||
int tolower(int ch);
|
||||
int isspace (int c);
|
||||
|
||||
void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength);
|
||||
void * malloc(size_t size);
|
||||
void free(void *);
|
||||
|
||||
extern volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde;
|
||||
extern volatile bool fSeenPowerdown;
|
||||
typedef enum {
|
||||
ETS_OPEN_OR_OPENING=0,
|
||||
ETS_CLOSING,
|
||||
ETS_CLOSED
|
||||
} TRAY_STATE;
|
||||
extern volatile TRAY_STATE traystate;
|
||||
|
||||
|
||||
extern void BootInterruptsWriteIdt(void);
|
||||
#endif
|
||||
int copy_swap_trim(unsigned char *dst, unsigned char *src, int len);
|
||||
void HMAC_SHA1( unsigned char *result,
|
||||
unsigned char *key, int key_length,
|
||||
unsigned char *text1, int text1_length,
|
||||
unsigned char *text2, int text2_length );
|
||||
|
||||
char *strrchr0(char *string, char ch);
|
||||
|
||||
#endif // _Boot_H_
|
||||
|
|
|
@ -1,70 +1,70 @@
|
|||
#ifndef _Consts_H_
|
||||
#define _Consts_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* includes for startup code in a form usable by the .S files
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#define PCI_CFG_ADDR 0x0CF8
|
||||
#define PCI_CFG_DATA 0x0CFC
|
||||
|
||||
|
||||
#define I2C_IO_BASE 0xc000
|
||||
|
||||
#define BUS_0 0
|
||||
#define BUS_1 1
|
||||
|
||||
#define DEV_0 0
|
||||
#define DEV_1 1
|
||||
#define DEV_2 2
|
||||
#define DEV_3 3
|
||||
#define DEV_4 4
|
||||
#define DEV_5 5
|
||||
#define DEV_6 6
|
||||
#define DEV_7 7
|
||||
#define DEV_8 8
|
||||
#define DEV_9 9
|
||||
#define DEV_a 0xa
|
||||
#define DEV_b 0xb
|
||||
#define DEV_c 0xc
|
||||
#define DEV_d 0xd
|
||||
#define DEV_e 0xe
|
||||
#define DEV_f 0xf
|
||||
#define DEV_10 0x10
|
||||
#define DEV_11 0x11
|
||||
#define DEV_12 0x12
|
||||
#define DEV_13 0x13
|
||||
#define DEV_14 0x14
|
||||
#define DEV_15 0x15
|
||||
#define DEV_16 0x16
|
||||
#define DEV_17 0x17
|
||||
#define DEV_18 0x18
|
||||
#define DEV_19 0x19
|
||||
#define DEV_1a 0x1a
|
||||
#define DEV_1b 0x1b
|
||||
#define DEV_1c 0x1c
|
||||
#define DEV_1d 0x1d
|
||||
#define DEV_1e 0x1e
|
||||
#define DEV_1f 0x1f
|
||||
|
||||
#define FUNC_0 0
|
||||
/*
|
||||
#define boot_post_macro(value) \
|
||||
movb $(value), %al ;\
|
||||
outb %al, $0x80
|
||||
*/
|
||||
|
||||
#endif // _Consts_H_
|
||||
|
||||
|
||||
#ifndef _Consts_H_
|
||||
#define _Consts_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* includes for startup code in a form usable by the .S files
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#define PCI_CFG_ADDR 0x0CF8
|
||||
#define PCI_CFG_DATA 0x0CFC
|
||||
|
||||
|
||||
#define I2C_IO_BASE 0xc000
|
||||
|
||||
#define BUS_0 0
|
||||
#define BUS_1 1
|
||||
|
||||
#define DEV_0 0
|
||||
#define DEV_1 1
|
||||
#define DEV_2 2
|
||||
#define DEV_3 3
|
||||
#define DEV_4 4
|
||||
#define DEV_5 5
|
||||
#define DEV_6 6
|
||||
#define DEV_7 7
|
||||
#define DEV_8 8
|
||||
#define DEV_9 9
|
||||
#define DEV_a 0xa
|
||||
#define DEV_b 0xb
|
||||
#define DEV_c 0xc
|
||||
#define DEV_d 0xd
|
||||
#define DEV_e 0xe
|
||||
#define DEV_f 0xf
|
||||
#define DEV_10 0x10
|
||||
#define DEV_11 0x11
|
||||
#define DEV_12 0x12
|
||||
#define DEV_13 0x13
|
||||
#define DEV_14 0x14
|
||||
#define DEV_15 0x15
|
||||
#define DEV_16 0x16
|
||||
#define DEV_17 0x17
|
||||
#define DEV_18 0x18
|
||||
#define DEV_19 0x19
|
||||
#define DEV_1a 0x1a
|
||||
#define DEV_1b 0x1b
|
||||
#define DEV_1c 0x1c
|
||||
#define DEV_1d 0x1d
|
||||
#define DEV_1e 0x1e
|
||||
#define DEV_1f 0x1f
|
||||
|
||||
#define FUNC_0 0
|
||||
/*
|
||||
#define boot_post_macro(value) \
|
||||
movb $(value), %al ;\
|
||||
outb %al, $0x80
|
||||
*/
|
||||
|
||||
#endif // _Consts_H_
|
||||
|
||||
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
#ifndef cromwell_types_h
|
||||
#define cromwell_types_h
|
||||
|
||||
/////////////////////////////////
|
||||
// some typedefs to make for easy sizing
|
||||
|
||||
//typedef unsigned long ULONG;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
#ifndef bool_already_defined_
|
||||
typedef int bool;
|
||||
#endif
|
||||
typedef unsigned long RGBA; // LSB=R -> MSB = A
|
||||
//typedef long long __int64;
|
||||
|
||||
#define guint int
|
||||
#define guint8 unsigned char
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef cromwell_types_h */
|
||||
#ifndef cromwell_types_h
|
||||
#define cromwell_types_h
|
||||
|
||||
/////////////////////////////////
|
||||
// some typedefs to make for easy sizing
|
||||
|
||||
//typedef unsigned long ULONG;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
#ifndef bool_already_defined_
|
||||
typedef int bool;
|
||||
#endif
|
||||
typedef unsigned long RGBA; // LSB=R -> MSB = A
|
||||
//typedef long long __int64;
|
||||
|
||||
#define guint int
|
||||
#define guint8 unsigned char
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef cromwell_types_h */
|
||||
|
|
|
@ -1,132 +1,132 @@
|
|||
#ifndef _I386_ERRNO_H
|
||||
#define _I386_ERRNO_H
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
#endif
|
||||
#ifndef _I386_ERRNO_H
|
||||
#define _I386_ERRNO_H
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,224 +1,224 @@
|
|||
#ifndef _BOOT_LIST_H
|
||||
#define _BOOT_LIST_H
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = (void *) 0;
|
||||
entry->prev = (void *) 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); \
|
||||
pos = pos->next)
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); \
|
||||
pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member) \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
#endif
|
||||
#ifndef _BOOT_LIST_H
|
||||
#define _BOOT_LIST_H
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = (void *) 0;
|
||||
entry->prev = (void *) 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); \
|
||||
pos = pos->next)
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); \
|
||||
pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member) \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,158 +1,162 @@
|
|||
// PCI -> HAL interface
|
||||
// this file is part of linux_wrapper.h
|
||||
|
||||
//FIXME: Move this file, make its definitions more general
|
||||
#include "../host/ohci_main.h"
|
||||
|
||||
/*
|
||||
Initialize device before it's used by a driver. Ask low-level code to enable I/O and memory.
|
||||
Wake up the device if it was suspended. Beware, this function can fail.
|
||||
*/
|
||||
static int __inline__ pci_enable_device(struct pci_dev *dev)
|
||||
{
|
||||
DPRINT1("pci_enable_device() called...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get physical address where resource x resides
|
||||
static PHYSICAL_ADDRESS __inline__ pci_resource_start (struct pci_dev *dev, int x)
|
||||
{
|
||||
POHCI_DEVICE_EXTENSION dev_ext = (POHCI_DEVICE_EXTENSION)dev->dev_ext;
|
||||
DPRINT1("pci_resource_start() called, x=0x%x\n", x);
|
||||
|
||||
//FIXME: Take x into account
|
||||
return dev_ext->BaseAddress;
|
||||
//return dev->base[x];
|
||||
}
|
||||
|
||||
// ???
|
||||
static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x)
|
||||
{
|
||||
POHCI_DEVICE_EXTENSION ext = (POHCI_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
DPRINT1("pci_resource_len() called, x=0x%x\n", x);
|
||||
|
||||
//FIXME: Take x into account
|
||||
return ext->BaseAddrLength;
|
||||
}
|
||||
|
||||
// ???
|
||||
static int __inline__ pci_resource_flags(struct pci_dev *dev, int x)
|
||||
{
|
||||
DPRINT1("pci_resource_flags() called, x=0x%x\n");
|
||||
return dev->flags[x];
|
||||
}
|
||||
|
||||
/*
|
||||
Enables bus-mastering for device dev
|
||||
*/
|
||||
static int __inline__ pci_set_master(struct pci_dev *dev) {return 0;}
|
||||
|
||||
// Store pointer to data for this device
|
||||
static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d)
|
||||
{
|
||||
DPRINT1("pci_set_drvdata() called...\n");
|
||||
dev->data=(void*)d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get pointer to previously saved data
|
||||
static void __inline__ *pci_get_drvdata(struct pci_dev *dev)
|
||||
{
|
||||
DPRINT1("pci_get_drvdata() called...\n");
|
||||
return dev->data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
I/O mem related stuff below
|
||||
*/
|
||||
|
||||
/*
|
||||
Allocate I/O memory region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
name name of requester
|
||||
*/
|
||||
static int __inline__ request_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
{
|
||||
DPRINT1("request_region(): addr=0x%x, len=0x%x\n", addr, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Unmap I/O memory from kernel address space.
|
||||
|
||||
Parameters:
|
||||
addr virtual start address
|
||||
|
||||
*/
|
||||
static int __inline__ iounmap(void* p)
|
||||
{
|
||||
DPRINT1("iounmap(): p=0x%x. FIXME - how to obtain len of mapped region?\n", p);
|
||||
|
||||
//MmUnnapIoSpace(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Release I/O port region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
*/
|
||||
static int __inline__ release_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
DPRINT1("release_region(): addr=0x%x, len=0x%x\n", addr, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate I/O memory region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
name name of requester
|
||||
*/
|
||||
static int __inline__ request_mem_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
{
|
||||
DPRINT1("request_mem_region(): addr=0x%x, len=0x%x\n", addr, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Remap I/O memory into kernel address space (no cache).
|
||||
|
||||
Parameters:
|
||||
phys_addr begin of physical address range
|
||||
size size of physical address range
|
||||
|
||||
Returns:
|
||||
virtual start address of mapped range
|
||||
*/
|
||||
static void __inline__ *ioremap_nocache(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
// MmMapIoSpace with NoCache param
|
||||
DPRINT1("ioremap_nocache(): addr=0x%x, len=0x%x\n", addr, len);
|
||||
|
||||
return MmMapIoSpace(addr, len, MmNonCached);
|
||||
}
|
||||
|
||||
/*
|
||||
Release I/O memory region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
*/
|
||||
static int __inline__ release_mem_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
DPRINT1("release_mem_region(): addr=0x%x, len=0x%x\n", addr, len);
|
||||
return 0;
|
||||
}
|
||||
// PCI -> HAL interface
|
||||
// this file is part of linux_wrapper.h
|
||||
|
||||
//FIXME: Move this file, make its definitions more general
|
||||
#include "../host/ohci_main.h"
|
||||
|
||||
/*
|
||||
Initialize device before it's used by a driver. Ask low-level code to enable I/O and memory.
|
||||
Wake up the device if it was suspended. Beware, this function can fail.
|
||||
*/
|
||||
static int __inline__ pci_enable_device(struct pci_dev *dev)
|
||||
{
|
||||
DPRINT1("pci_enable_device() called...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get physical address where resource x resides
|
||||
static PHYSICAL_ADDRESS __inline__ pci_resource_start (struct pci_dev *dev, int x)
|
||||
{
|
||||
POHCI_DEVICE_EXTENSION dev_ext = (POHCI_DEVICE_EXTENSION)dev->dev_ext;
|
||||
DPRINT1("pci_resource_start() called, x=0x%x\n", x);
|
||||
|
||||
//FIXME: Take x into account
|
||||
return dev_ext->BaseAddress;
|
||||
//return dev->base[x];
|
||||
}
|
||||
|
||||
// ???
|
||||
static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x)
|
||||
{
|
||||
POHCI_DEVICE_EXTENSION ext = (POHCI_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
DPRINT1("pci_resource_len() called, x=0x%x\n", x);
|
||||
|
||||
//FIXME: Take x into account
|
||||
return ext->BaseAddrLength;
|
||||
}
|
||||
|
||||
// ???
|
||||
static int __inline__ pci_resource_flags(struct pci_dev *dev, int x)
|
||||
{
|
||||
POHCI_DEVICE_EXTENSION ext = (POHCI_DEVICE_EXTENSION)dev->dev_ext;
|
||||
|
||||
DPRINT1("pci_resource_flags() called, x=0x%x\n", x);
|
||||
|
||||
//FIXME: Take x into account
|
||||
return ext->Flags;
|
||||
}
|
||||
|
||||
/*
|
||||
Enables bus-mastering for device dev
|
||||
*/
|
||||
static int __inline__ pci_set_master(struct pci_dev *dev) {return 0;}
|
||||
|
||||
// Store pointer to data for this device
|
||||
static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d)
|
||||
{
|
||||
DPRINT1("pci_set_drvdata() called...\n");
|
||||
dev->data=(void*)d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get pointer to previously saved data
|
||||
static void __inline__ *pci_get_drvdata(struct pci_dev *dev)
|
||||
{
|
||||
DPRINT1("pci_get_drvdata() called...\n");
|
||||
return dev->data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========================================================================
|
||||
I/O mem related stuff below
|
||||
*/
|
||||
|
||||
/*
|
||||
Allocate I/O memory region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
name name of requester
|
||||
*/
|
||||
static int __inline__ request_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
{
|
||||
DPRINT1("request_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return ~0;
|
||||
}
|
||||
|
||||
/*
|
||||
Unmap I/O memory from kernel address space.
|
||||
|
||||
Parameters:
|
||||
addr virtual start address
|
||||
|
||||
*/
|
||||
static int __inline__ iounmap(void* p)
|
||||
{
|
||||
DPRINT1("iounmap(): p=0x%x. FIXME - how to obtain len of mapped region?\n", p);
|
||||
|
||||
//MmUnnapIoSpace(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Release I/O port region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
*/
|
||||
static int __inline__ release_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
DPRINT1("release_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate I/O memory region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
name name of requester
|
||||
*/
|
||||
static int __inline__ request_mem_region(PHYSICAL_ADDRESS addr, unsigned long len, const char * d)
|
||||
{
|
||||
DPRINT1("request_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Remap I/O memory into kernel address space (no cache).
|
||||
|
||||
Parameters:
|
||||
phys_addr begin of physical address range
|
||||
size size of physical address range
|
||||
|
||||
Returns:
|
||||
virtual start address of mapped range
|
||||
*/
|
||||
static void __inline__ *ioremap_nocache(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
// MmMapIoSpace with NoCache param
|
||||
DPRINT1("ioremap_nocache(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
|
||||
return MmMapIoSpace(addr, len, MmNonCached);
|
||||
}
|
||||
|
||||
/*
|
||||
Release I/O memory region.
|
||||
|
||||
Parameters:
|
||||
start begin of region
|
||||
n length of region
|
||||
*/
|
||||
static int __inline__ release_mem_region(PHYSICAL_ADDRESS addr, unsigned long len)
|
||||
{
|
||||
DPRINT1("release_mem_region(): addr=0x%lx, len=0x%lx\n", addr.u.LowPart, len);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#ifndef PCI_IDS__H
|
||||
#define PCI_IDS__H
|
||||
|
||||
#define PCI_VENDOR_ID_NS 0x100b
|
||||
#define PCI_VENDOR_ID_AMD 0x1022
|
||||
#define PCI_VENDOR_ID_OPTI 0x1045
|
||||
#define PCI_VENDOR_ID_VIA 0x1106
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
|
||||
#define PCI_DEVICE_ID_NS_87560_LIO 0x000e
|
||||
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
|
||||
|
||||
#define PCI_CLASS_SERIAL_USB (PCI_CLASS_SERIAL_BUS_CTLR << 8 + PCI_SUBCLASS_SB_USB)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef PCI_IDS__H
|
||||
#define PCI_IDS__H
|
||||
|
||||
#define PCI_VENDOR_ID_NS 0x100b
|
||||
#define PCI_VENDOR_ID_AMD 0x1022
|
||||
#define PCI_VENDOR_ID_OPTI 0x1045
|
||||
#define PCI_VENDOR_ID_VIA 0x1106
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
|
||||
#define PCI_DEVICE_ID_NS_87560_LIO 0x000e
|
||||
#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
|
||||
|
||||
#define PCI_CLASS_SERIAL_USB ((PCI_CLASS_SERIAL_BUS_CTLR << 8) + PCI_SUBCLASS_SB_USB)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,315 +1,315 @@
|
|||
/*
|
||||
* This file holds USB constants and structures that are needed for USB
|
||||
* device APIs. These are used by the USB device model, which is defined
|
||||
* in chapter 9 of the USB 2.0 specification. Linux has several APIs in C
|
||||
* that need these:
|
||||
*
|
||||
* - the master/host side Linux-USB kernel driver API;
|
||||
* - the "usbfs" user space API; and
|
||||
* - (eventually) a Linux "gadget" slave/device side driver API.
|
||||
*
|
||||
* USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
|
||||
* act either as a USB master/host or as a USB slave/device. That means
|
||||
* the master and slave side APIs will benefit from working well together.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_CH9_H
|
||||
#define __LINUX_USB_CH9_H
|
||||
#if 0
|
||||
#include <asm/types.h> /* __u8 etc */
|
||||
#endif
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* CONTROL REQUEST SUPPORT */
|
||||
|
||||
/*
|
||||
* USB directions
|
||||
*
|
||||
* This bit flag is used in endpoint descriptors' bEndpointAddress field.
|
||||
* It's also one of three fields in control requests bRequestType.
|
||||
*/
|
||||
#define USB_DIR_OUT 0 /* to device */
|
||||
#define USB_DIR_IN 0x80 /* to host */
|
||||
|
||||
/*
|
||||
* USB types, the second of three bRequestType fields
|
||||
*/
|
||||
#define USB_TYPE_MASK (0x03 << 5)
|
||||
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||
#define USB_TYPE_CLASS (0x01 << 5)
|
||||
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||
|
||||
/*
|
||||
* USB recipients, the third of three bRequestType fields
|
||||
*/
|
||||
#define USB_RECIP_MASK 0x1f
|
||||
#define USB_RECIP_DEVICE 0x00
|
||||
#define USB_RECIP_INTERFACE 0x01
|
||||
#define USB_RECIP_ENDPOINT 0x02
|
||||
#define USB_RECIP_OTHER 0x03
|
||||
|
||||
/*
|
||||
* Standard requests, for the bRequest field of a SETUP packet.
|
||||
*
|
||||
* These are qualified by the bRequestType field, so that for example
|
||||
* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
|
||||
* by a GET_STATUS request.
|
||||
*/
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
|
||||
/**
|
||||
* struct usb_ctrlrequest - SETUP data for a USB device control request
|
||||
* @bRequestType: matches the USB bmRequestType field
|
||||
* @bRequest: matches the USB bRequest field
|
||||
* @wValue: matches the USB wValue field (le16 byte order)
|
||||
* @wIndex: matches the USB wIndex field (le16 byte order)
|
||||
* @wLength: matches the USB wLength field (le16 byte order)
|
||||
*
|
||||
* This structure is used to send control requests to a USB device. It matches
|
||||
* the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
|
||||
* USB spec for a fuller description of the different fields, and what they are
|
||||
* used for.
|
||||
*
|
||||
* Note that the driver for any interface can issue control requests.
|
||||
* For most devices, interfaces don't coordinate with each other, so
|
||||
* such requests may be made at any time.
|
||||
*/
|
||||
struct usb_ctrlrequest {
|
||||
__u8 bRequestType;
|
||||
__u8 bRequest;
|
||||
__u16 wValue;
|
||||
__u16 wIndex;
|
||||
__u16 wLength;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
|
||||
* (rarely) accepted by SET_DESCRIPTOR.
|
||||
*
|
||||
* Note that all multi-byte values here are encoded in little endian
|
||||
* byte order "on the wire". But when exposed through Linux-USB APIs,
|
||||
* they've been converted to cpu byte order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Descriptor types ... USB 2.0 spec table 9.5
|
||||
*/
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
#define USB_DT_STRING 0x03
|
||||
#define USB_DT_INTERFACE 0x04
|
||||
#define USB_DT_ENDPOINT 0x05
|
||||
#define USB_DT_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DT_OTHER_SPEED_CONFIG 0x07
|
||||
#define USB_DT_INTERFACE_POWER 0x08
|
||||
|
||||
/* All standard descriptors have these 2 fields at the beginning */
|
||||
struct usb_descriptor_header {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE: Device descriptor */
|
||||
struct usb_device_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
__u16 bcdDevice;
|
||||
__u8 iManufacturer;
|
||||
__u8 iProduct;
|
||||
__u8 iSerialNumber;
|
||||
__u8 bNumConfigurations;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
|
||||
|
||||
/*
|
||||
* Device and/or Interface Class codes
|
||||
* as found in bDeviceClass or bInterfaceClass
|
||||
* and defined by www.usb.org documents
|
||||
*/
|
||||
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
|
||||
#define USB_CLASS_AUDIO 1
|
||||
#define USB_CLASS_COMM 2
|
||||
#define USB_CLASS_HID 3
|
||||
#define USB_CLASS_PHYSICAL 5
|
||||
#define USB_CLASS_STILL_IMAGE 6
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MASS_STORAGE 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_CDC_DATA 0x0a
|
||||
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
|
||||
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
|
||||
#define USB_CLASS_APP_SPEC 0xfe
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_CONFIG: Configuration descriptor information.
|
||||
*
|
||||
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
|
||||
* descriptor type is different. Highspeed-capable devices can look
|
||||
* different depending on what speed they're currently running. Only
|
||||
* devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
|
||||
* descriptors.
|
||||
*/
|
||||
struct usb_config_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wTotalLength;
|
||||
__u8 bNumInterfaces;
|
||||
__u8 bConfigurationValue;
|
||||
__u8 iConfiguration;
|
||||
__u8 bmAttributes;
|
||||
__u8 bMaxPower;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
|
||||
/* from config descriptor bmAttributes */
|
||||
#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
|
||||
#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
|
||||
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_STRING: String descriptor */
|
||||
struct usb_string_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wData[1]; /* UTF-16LE encoded */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* note that "string" zero is special, it holds language codes that
|
||||
* the device supports, not Unicode characters.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_INTERFACE: Interface descriptor */
|
||||
struct usb_interface_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bInterfaceNumber;
|
||||
__u8 bAlternateSetting;
|
||||
__u8 bNumEndpoints;
|
||||
__u8 bInterfaceClass;
|
||||
__u8 bInterfaceSubClass;
|
||||
__u8 bInterfaceProtocol;
|
||||
__u8 iInterface;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_ENDPOINT: Endpoint descriptor */
|
||||
struct usb_endpoint_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bEndpointAddress;
|
||||
__u8 bmAttributes;
|
||||
__u16 wMaxPacketSize;
|
||||
__u8 bInterval;
|
||||
|
||||
// NOTE: these two are _only_ in audio endpoints.
|
||||
// use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
|
||||
__u8 bRefresh;
|
||||
__u8 bSynchAddress;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
|
||||
|
||||
/*
|
||||
* Endpoints
|
||||
*/
|
||||
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
|
||||
#define USB_ENDPOINT_DIR_MASK 0x80
|
||||
|
||||
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
#define USB_ENDPOINT_XFER_INT 3
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
|
||||
struct usb_qualifier_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u8 bNumConfigurations;
|
||||
__u8 bRESERVED;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB 2.0 defines three speeds, here's how Linux identifies them */
|
||||
|
||||
enum usb_device_speed {
|
||||
USB_SPEED_UNKNOWN = 0, /* enumerating */
|
||||
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
|
||||
USB_SPEED_HIGH /* usb 2.0 */
|
||||
};
|
||||
|
||||
enum usb_device_state {
|
||||
/* NOTATTACHED isn't in the USB spec, and this state acts
|
||||
* the same as ATTACHED ... but it's clearer this way.
|
||||
*/
|
||||
USB_STATE_NOTATTACHED = 0,
|
||||
|
||||
/* the chapter 9 device states */
|
||||
USB_STATE_ATTACHED,
|
||||
USB_STATE_POWERED,
|
||||
USB_STATE_DEFAULT, /* limited function */
|
||||
USB_STATE_ADDRESS,
|
||||
USB_STATE_CONFIGURED, /* most functions */
|
||||
|
||||
USB_STATE_SUSPENDED
|
||||
|
||||
/* NOTE: there are actually four different SUSPENDED
|
||||
* states, returning to POWERED, DEFAULT, ADDRESS, or
|
||||
* CONFIGURED respectively when SOF tokens flow again.
|
||||
*/
|
||||
};
|
||||
|
||||
#endif /* __LINUX_USB_CH9_H */
|
||||
/*
|
||||
* This file holds USB constants and structures that are needed for USB
|
||||
* device APIs. These are used by the USB device model, which is defined
|
||||
* in chapter 9 of the USB 2.0 specification. Linux has several APIs in C
|
||||
* that need these:
|
||||
*
|
||||
* - the master/host side Linux-USB kernel driver API;
|
||||
* - the "usbfs" user space API; and
|
||||
* - (eventually) a Linux "gadget" slave/device side driver API.
|
||||
*
|
||||
* USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
|
||||
* act either as a USB master/host or as a USB slave/device. That means
|
||||
* the master and slave side APIs will benefit from working well together.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_CH9_H
|
||||
#define __LINUX_USB_CH9_H
|
||||
#if 0
|
||||
#include <asm/types.h> /* __u8 etc */
|
||||
#endif
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* CONTROL REQUEST SUPPORT */
|
||||
|
||||
/*
|
||||
* USB directions
|
||||
*
|
||||
* This bit flag is used in endpoint descriptors' bEndpointAddress field.
|
||||
* It's also one of three fields in control requests bRequestType.
|
||||
*/
|
||||
#define USB_DIR_OUT 0 /* to device */
|
||||
#define USB_DIR_IN 0x80 /* to host */
|
||||
|
||||
/*
|
||||
* USB types, the second of three bRequestType fields
|
||||
*/
|
||||
#define USB_TYPE_MASK (0x03 << 5)
|
||||
#define USB_TYPE_STANDARD (0x00 << 5)
|
||||
#define USB_TYPE_CLASS (0x01 << 5)
|
||||
#define USB_TYPE_VENDOR (0x02 << 5)
|
||||
#define USB_TYPE_RESERVED (0x03 << 5)
|
||||
|
||||
/*
|
||||
* USB recipients, the third of three bRequestType fields
|
||||
*/
|
||||
#define USB_RECIP_MASK 0x1f
|
||||
#define USB_RECIP_DEVICE 0x00
|
||||
#define USB_RECIP_INTERFACE 0x01
|
||||
#define USB_RECIP_ENDPOINT 0x02
|
||||
#define USB_RECIP_OTHER 0x03
|
||||
|
||||
/*
|
||||
* Standard requests, for the bRequest field of a SETUP packet.
|
||||
*
|
||||
* These are qualified by the bRequestType field, so that for example
|
||||
* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
|
||||
* by a GET_STATUS request.
|
||||
*/
|
||||
#define USB_REQ_GET_STATUS 0x00
|
||||
#define USB_REQ_CLEAR_FEATURE 0x01
|
||||
#define USB_REQ_SET_FEATURE 0x03
|
||||
#define USB_REQ_SET_ADDRESS 0x05
|
||||
#define USB_REQ_GET_DESCRIPTOR 0x06
|
||||
#define USB_REQ_SET_DESCRIPTOR 0x07
|
||||
#define USB_REQ_GET_CONFIGURATION 0x08
|
||||
#define USB_REQ_SET_CONFIGURATION 0x09
|
||||
#define USB_REQ_GET_INTERFACE 0x0A
|
||||
#define USB_REQ_SET_INTERFACE 0x0B
|
||||
#define USB_REQ_SYNCH_FRAME 0x0C
|
||||
|
||||
|
||||
/**
|
||||
* struct usb_ctrlrequest - SETUP data for a USB device control request
|
||||
* @bRequestType: matches the USB bmRequestType field
|
||||
* @bRequest: matches the USB bRequest field
|
||||
* @wValue: matches the USB wValue field (le16 byte order)
|
||||
* @wIndex: matches the USB wIndex field (le16 byte order)
|
||||
* @wLength: matches the USB wLength field (le16 byte order)
|
||||
*
|
||||
* This structure is used to send control requests to a USB device. It matches
|
||||
* the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
|
||||
* USB spec for a fuller description of the different fields, and what they are
|
||||
* used for.
|
||||
*
|
||||
* Note that the driver for any interface can issue control requests.
|
||||
* For most devices, interfaces don't coordinate with each other, so
|
||||
* such requests may be made at any time.
|
||||
*/
|
||||
struct usb_ctrlrequest {
|
||||
__u8 bRequestType;
|
||||
__u8 bRequest;
|
||||
__u16 wValue;
|
||||
__u16 wIndex;
|
||||
__u16 wLength;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
|
||||
* (rarely) accepted by SET_DESCRIPTOR.
|
||||
*
|
||||
* Note that all multi-byte values here are encoded in little endian
|
||||
* byte order "on the wire". But when exposed through Linux-USB APIs,
|
||||
* they've been converted to cpu byte order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Descriptor types ... USB 2.0 spec table 9.5
|
||||
*/
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
#define USB_DT_STRING 0x03
|
||||
#define USB_DT_INTERFACE 0x04
|
||||
#define USB_DT_ENDPOINT 0x05
|
||||
#define USB_DT_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DT_OTHER_SPEED_CONFIG 0x07
|
||||
#define USB_DT_INTERFACE_POWER 0x08
|
||||
|
||||
/* All standard descriptors have these 2 fields at the beginning */
|
||||
struct usb_descriptor_header {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE: Device descriptor */
|
||||
struct usb_device_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
__u16 bcdDevice;
|
||||
__u8 iManufacturer;
|
||||
__u8 iProduct;
|
||||
__u8 iSerialNumber;
|
||||
__u8 bNumConfigurations;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
|
||||
|
||||
/*
|
||||
* Device and/or Interface Class codes
|
||||
* as found in bDeviceClass or bInterfaceClass
|
||||
* and defined by www.usb.org documents
|
||||
*/
|
||||
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
|
||||
#define USB_CLASS_AUDIO 1
|
||||
#define USB_CLASS_COMM 2
|
||||
#define USB_CLASS_HID 3
|
||||
#define USB_CLASS_PHYSICAL 5
|
||||
#define USB_CLASS_STILL_IMAGE 6
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MASS_STORAGE 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_CDC_DATA 0x0a
|
||||
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
|
||||
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
|
||||
#define USB_CLASS_APP_SPEC 0xfe
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_CONFIG: Configuration descriptor information.
|
||||
*
|
||||
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
|
||||
* descriptor type is different. Highspeed-capable devices can look
|
||||
* different depending on what speed they're currently running. Only
|
||||
* devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
|
||||
* descriptors.
|
||||
*/
|
||||
struct usb_config_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wTotalLength;
|
||||
__u8 bNumInterfaces;
|
||||
__u8 bConfigurationValue;
|
||||
__u8 iConfiguration;
|
||||
__u8 bmAttributes;
|
||||
__u8 bMaxPower;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
|
||||
/* from config descriptor bmAttributes */
|
||||
#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
|
||||
#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
|
||||
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_STRING: String descriptor */
|
||||
struct usb_string_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wData[1]; /* UTF-16LE encoded */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* note that "string" zero is special, it holds language codes that
|
||||
* the device supports, not Unicode characters.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_INTERFACE: Interface descriptor */
|
||||
struct usb_interface_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bInterfaceNumber;
|
||||
__u8 bAlternateSetting;
|
||||
__u8 bNumEndpoints;
|
||||
__u8 bInterfaceClass;
|
||||
__u8 bInterfaceSubClass;
|
||||
__u8 bInterfaceProtocol;
|
||||
__u8 iInterface;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_ENDPOINT: Endpoint descriptor */
|
||||
struct usb_endpoint_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bEndpointAddress;
|
||||
__u8 bmAttributes;
|
||||
__u16 wMaxPacketSize;
|
||||
__u8 bInterval;
|
||||
|
||||
// NOTE: these two are _only_ in audio endpoints.
|
||||
// use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
|
||||
__u8 bRefresh;
|
||||
__u8 bSynchAddress;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
|
||||
|
||||
/*
|
||||
* Endpoints
|
||||
*/
|
||||
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
|
||||
#define USB_ENDPOINT_DIR_MASK 0x80
|
||||
|
||||
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
|
||||
#define USB_ENDPOINT_XFER_CONTROL 0
|
||||
#define USB_ENDPOINT_XFER_ISOC 1
|
||||
#define USB_ENDPOINT_XFER_BULK 2
|
||||
#define USB_ENDPOINT_XFER_INT 3
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
|
||||
struct usb_qualifier_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u8 bNumConfigurations;
|
||||
__u8 bRESERVED;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB 2.0 defines three speeds, here's how Linux identifies them */
|
||||
|
||||
enum usb_device_speed {
|
||||
USB_SPEED_UNKNOWN = 0, /* enumerating */
|
||||
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
|
||||
USB_SPEED_HIGH /* usb 2.0 */
|
||||
};
|
||||
|
||||
enum usb_device_state {
|
||||
/* NOTATTACHED isn't in the USB spec, and this state acts
|
||||
* the same as ATTACHED ... but it's clearer this way.
|
||||
*/
|
||||
USB_STATE_NOTATTACHED = 0,
|
||||
|
||||
/* the chapter 9 device states */
|
||||
USB_STATE_ATTACHED,
|
||||
USB_STATE_POWERED,
|
||||
USB_STATE_DEFAULT, /* limited function */
|
||||
USB_STATE_ADDRESS,
|
||||
USB_STATE_CONFIGURED, /* most functions */
|
||||
|
||||
USB_STATE_SUSPENDED
|
||||
|
||||
/* NOTE: there are actually four different SUSPENDED
|
||||
* states, returning to POWERED, DEFAULT, ADDRESS, or
|
||||
* CONFIGURED respectively when SOF tokens flow again.
|
||||
*/
|
||||
};
|
||||
|
||||
#endif /* __LINUX_USB_CH9_H */
|
||||
|
|
|
@ -1,90 +1,90 @@
|
|||
/*
|
||||
* USB support for XBOX, based on Linux kernel source
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
void subsys_usb_init(void);
|
||||
void module_exit_usb_exit(void);
|
||||
|
||||
extern struct pci_device_id *module_table_pci_ids;
|
||||
|
||||
// straigth call...
|
||||
int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id);
|
||||
void usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
void XPADInit(void);
|
||||
void XPADRemove(void);
|
||||
void XRemoteInit(void);
|
||||
void XRemoteRemove(void);
|
||||
|
||||
extern int (*thread_handler)(void*);
|
||||
int (*hub_thread_handler)(void*);
|
||||
|
||||
extern int nousb;
|
||||
extern int xpad_num;
|
||||
|
||||
struct pci_dev xx_ohci_dev={
|
||||
.vendor = 0,
|
||||
.device = 0,
|
||||
.bus = NULL,
|
||||
.irq = 1, // currently not used...
|
||||
.slot_name = "OHCI",
|
||||
.dev = {.name = "PCI",.dma_mask=1},
|
||||
.base = {0xfed00000},
|
||||
.flags = {}
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void BootStartUSB(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
nousb=0;
|
||||
|
||||
init_wrapper();
|
||||
subsys_usb_init();
|
||||
hub_thread_handler=thread_handler;
|
||||
usb_hcd_pci_probe(&xx_ohci_dev, module_table_pci_ids);
|
||||
XPADInit();
|
||||
|
||||
XRemoteInit();
|
||||
|
||||
UsbKeyBoardInit();
|
||||
|
||||
for(n=0;n<30;n++) {
|
||||
USBGetEvents();
|
||||
wait_ms(1);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void USBGetEvents(void)
|
||||
{
|
||||
inc_jiffies(1);
|
||||
do_all_timers();
|
||||
hub_thread_handler(NULL);
|
||||
handle_irqs(-1);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void BootStopUSB(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
XPADRemove();
|
||||
XRemoteRemove();
|
||||
UsbKeyBoardRemove();
|
||||
|
||||
for(n=0;n<100;n++)
|
||||
{
|
||||
USBGetEvents();
|
||||
wait_ms(1);
|
||||
}
|
||||
|
||||
module_exit_usb_exit();
|
||||
usb_hcd_pci_remove(&xx_ohci_dev);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
* USB support for XBOX, based on Linux kernel source
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
void subsys_usb_init(void);
|
||||
void module_exit_usb_exit(void);
|
||||
|
||||
extern struct pci_device_id *module_table_pci_ids;
|
||||
|
||||
// straigth call...
|
||||
int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id);
|
||||
void usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
void XPADInit(void);
|
||||
void XPADRemove(void);
|
||||
void XRemoteInit(void);
|
||||
void XRemoteRemove(void);
|
||||
|
||||
extern int (*thread_handler)(void*);
|
||||
int (*hub_thread_handler)(void*);
|
||||
|
||||
extern int nousb;
|
||||
extern int xpad_num;
|
||||
|
||||
struct pci_dev xx_ohci_dev={
|
||||
.vendor = 0,
|
||||
.device = 0,
|
||||
.bus = NULL,
|
||||
.irq = 1, // currently not used...
|
||||
.slot_name = "OHCI",
|
||||
.dev = {.name = "PCI",.dma_mask=1},
|
||||
.base = {0xfed00000},
|
||||
.flags = {}
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void BootStartUSB(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
nousb=0;
|
||||
|
||||
init_wrapper();
|
||||
subsys_usb_init();
|
||||
hub_thread_handler=thread_handler;
|
||||
usb_hcd_pci_probe(&xx_ohci_dev, module_table_pci_ids);
|
||||
XPADInit();
|
||||
|
||||
XRemoteInit();
|
||||
|
||||
UsbKeyBoardInit();
|
||||
|
||||
for(n=0;n<30;n++) {
|
||||
USBGetEvents();
|
||||
wait_ms(1);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void USBGetEvents(void)
|
||||
{
|
||||
inc_jiffies(1);
|
||||
do_all_timers();
|
||||
hub_thread_handler(NULL);
|
||||
handle_irqs(-1);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void BootStopUSB(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
XPADRemove();
|
||||
XRemoteRemove();
|
||||
UsbKeyBoardRemove();
|
||||
|
||||
for(n=0;n<100;n++)
|
||||
{
|
||||
USBGetEvents();
|
||||
wait_ms(1);
|
||||
}
|
||||
|
||||
module_exit_usb_exit();
|
||||
usb_hcd_pci_remove(&xx_ohci_dev);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
O_TARGET := usbwrapper.o BootUSB.o linuxwrapper.o xpad.o xremote.o usbkey.o risefall.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
||||
O_TARGET := usbwrapper.o BootUSB.o linuxwrapper.o xpad.o xremote.o usbkey.o risefall.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
|
||||
|
|
|
@ -1,375 +1,382 @@
|
|||
/*
|
||||
* USB support based on Linux kernel source
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
* Concept:
|
||||
*
|
||||
* 1) Forget all device interrupts, scheduling, semaphores, threads etc.
|
||||
* 1a) Forget all DMA and PCI helper functions
|
||||
* 2) Forget usbdevfs, procfs and ioctls
|
||||
* 3) Emulate OHCI interrupts and root hub timer by polling
|
||||
* 4) Emulate hub kernel thread by polling
|
||||
* 5) Emulate synchronous USB-messages (usb_*_msg) with busy waiting
|
||||
*
|
||||
* To be done:
|
||||
* 6) Remove code bloat
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
/* internal state */
|
||||
|
||||
static struct pci_dev *pci_probe_dev;
|
||||
extern int (*thread_handler)(void*);
|
||||
extern void* thread_parm;
|
||||
|
||||
struct my_irqs reg_irqs[MAX_IRQS];
|
||||
int num_irqs;
|
||||
int need_wakeup;
|
||||
|
||||
int my_jiffies;
|
||||
|
||||
struct timer_list *main_timer_list[MAX_TIMERS];
|
||||
struct dummy_process act_cur={0};
|
||||
struct dummy_process *my_current;
|
||||
|
||||
int (*thread_handler)(void*);
|
||||
void* thread_parm;
|
||||
|
||||
#define MAX_DRVS 8
|
||||
static struct device_driver *m_drivers[MAX_DRVS];
|
||||
static int drvs_num;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Helper functions for top-level system
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
void init_wrapper(struct pci_dev *probe_dev)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
{
|
||||
main_timer_list[n]=NULL;
|
||||
}
|
||||
|
||||
my_jiffies=0;
|
||||
num_irqs=0;
|
||||
my_current=&act_cur;
|
||||
pci_probe_dev=probe_dev;
|
||||
|
||||
for(n=0;n<MAX_IRQS;n++)
|
||||
{
|
||||
reg_irqs[n].handler=NULL;
|
||||
reg_irqs[n].irq=-1;
|
||||
}
|
||||
drvs_num=0;
|
||||
need_wakeup=0;
|
||||
for(n=0;n<MAX_DRVS;n++)
|
||||
m_drivers[n]=NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void handle_irqs(int irq)
|
||||
{
|
||||
int n;
|
||||
// printk("handle irqs\n");
|
||||
for(n=0;n<MAX_IRQS;n++)
|
||||
{
|
||||
if (reg_irqs[n].handler && (irq==reg_irqs[n].irq || irq==-1))
|
||||
reg_irqs[n].handler(reg_irqs[n].irq,reg_irqs[n].data,NULL);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void inc_jiffies(int n)
|
||||
{
|
||||
my_jiffies+=n;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void do_all_timers(void)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
{
|
||||
if (main_timer_list[n] &&
|
||||
main_timer_list[n]->function && main_timer_list[n]->expires)
|
||||
{
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
main_timer_list[n]->expires=0;
|
||||
|
||||
main_timer_list[n]=NULL; // remove timer
|
||||
// printk("do timer %i fn %p\n",n,function);
|
||||
|
||||
function(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Purpose: Remember thread procedure and data in global var
|
||||
// ReactOS Purpose: Create real kernel thread
|
||||
int my_kernel_thread(int STDCALL (*handler)(void*), void* parm, int flags)
|
||||
{
|
||||
HANDLE hThread;
|
||||
//thread_handler=handler;
|
||||
//thread_parm=parm;
|
||||
//return 42; // PID :-)
|
||||
|
||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
PsCreateSystemThread(&hThread,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(PKSTART_ROUTINE)handler,
|
||||
parm);
|
||||
|
||||
return (int)hThread; // FIXME: Correct?
|
||||
}
|
||||
|
||||
// Kill the process
|
||||
int my_kill_proc(int pid, int signal, int unk)
|
||||
{
|
||||
HANDLE hThread;
|
||||
|
||||
// TODO: Implement actual process killing
|
||||
|
||||
hThread = (HANDLE)pid;
|
||||
ZwClose(hThread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Device management
|
||||
* As simple as possible, but as complete as necessary ...
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* calls probe function for hotplug (which does device matching), this is the
|
||||
only link between usbcore and the registered device drivers! */
|
||||
int my_device_add(struct device *dev)
|
||||
{
|
||||
int n,found=0;
|
||||
// printk("drv_num %i %p %p\n",drvs_num,m_drivers[0]->probe,m_drivers[1]->probe);
|
||||
if (dev->driver)
|
||||
{
|
||||
if (dev->driver->probe)
|
||||
return dev->driver->probe(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(n=0;n<drvs_num;n++)
|
||||
{
|
||||
if (m_drivers[n]->probe)
|
||||
{
|
||||
dev->driver=m_drivers[n];
|
||||
// printk("probe%i %p ",n,m_drivers[n]->probe);
|
||||
if (m_drivers[n]->probe(dev) == 0)
|
||||
{
|
||||
// return 0;
|
||||
found=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) return 0;
|
||||
}
|
||||
dev->driver=NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_driver_register(struct device_driver *driver)
|
||||
{
|
||||
|
||||
if (drvs_num<MAX_DRVS)
|
||||
{
|
||||
// printk("driver_register %i: %p %p",drvs_num,driver,driver->probe);
|
||||
m_drivers[drvs_num++]=driver;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_device_unregister(struct device *dev)
|
||||
{
|
||||
if (dev->driver && dev->driver->remove)
|
||||
dev->driver->remove(dev);
|
||||
return 0;
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct device *my_get_device(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_device_initialize(struct device *dev)
|
||||
{
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wake_up(PKEVENT evnt)
|
||||
{
|
||||
need_wakeup=1;
|
||||
|
||||
KeSetEvent(evnt, 0, FALSE); // Signal event
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_init_waitqueue_head(PKEVENT evnt)
|
||||
{
|
||||
// this is used only in core/message.c, and it isn't needed there
|
||||
//KeInitializeEvent(evnt, NotificationEvent, TRUE); // signalled state
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* wait until woken up (only one wait allowed!) */
|
||||
int my_schedule_timeout(int x)
|
||||
{
|
||||
int wait=1;
|
||||
x+=10; // safety
|
||||
// printk("schedule_timeout %i\n",x);
|
||||
while(x>0)
|
||||
{
|
||||
do_all_timers();
|
||||
#ifndef HAVE_IRQS
|
||||
handle_irqs(-1);
|
||||
|
||||
#endif
|
||||
if (need_wakeup)
|
||||
break;
|
||||
wait_ms(wait);
|
||||
inc_jiffies(wait);
|
||||
x-=wait;
|
||||
}
|
||||
need_wakeup=0;
|
||||
// printk("schedule DONE!!!!!!\n");
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wait_for_completion(struct completion *x)
|
||||
{
|
||||
int n=100;
|
||||
// printk("wait for completion\n");
|
||||
while(!x->done && (n>0))
|
||||
{
|
||||
do_all_timers();
|
||||
#ifndef HAVE_IRQS
|
||||
handle_irqs(-1);
|
||||
|
||||
#endif
|
||||
wait_ms(10);
|
||||
n--;
|
||||
}
|
||||
// printk("wait for completion done %i\n",x->done);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_interruptible_sleep_on(PKEVENT evnt)
|
||||
{
|
||||
KeWaitForSingleObject(evnt, Executive, KernelMode, FALSE, NULL);
|
||||
KeClearEvent(evnt); // reset to not-signalled
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Helper for pci_module_init
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_module_init(struct pci_driver *x)
|
||||
{
|
||||
struct pci_dev *dev=pci_probe_dev;
|
||||
const struct pci_device_id *id=NULL;
|
||||
if (!pci_probe_dev)
|
||||
{
|
||||
printk(KERN_ERR "PCI device not set!\n");
|
||||
return 0;
|
||||
}
|
||||
x->probe(dev, id);
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct pci_dev *my_pci_find_slot(int a,int b)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
|
||||
{
|
||||
//dev->bus, dev->devfn, where, val
|
||||
OHCI_DEVICE_EXTENSION *dev_ext = (OHCI_DEVICE_EXTENSION *)dev->dev_ext;
|
||||
|
||||
//FIXME: Is returning this value correct?
|
||||
//FIXME: Mixing pci_dev and win structs isn't a good thing at all
|
||||
return HalSetBusDataByOffset(PCIConfiguration, dev->bus->number, dev_ext->SystemIoSlotNumber, &val, where, sizeof(val));
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_request_irq(unsigned int irq,
|
||||
int (*handler)(int,void *, struct pt_regs *),
|
||||
unsigned long mode, const char *desc, void *data)
|
||||
{
|
||||
if (num_irqs<MAX_IRQS)
|
||||
{
|
||||
reg_irqs[num_irqs].handler=handler;
|
||||
reg_irqs[num_irqs].irq=irq;
|
||||
reg_irqs[num_irqs].data=data;
|
||||
num_irqs++;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_free_irq(int irq, void* p)
|
||||
{
|
||||
/* No free... */
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Lookaside funcs
|
||||
/*------------------------------------------------------------------------*/
|
||||
kmem_cache_t *my_kmem_cache_create(const char *tag, size_t alloc_size,
|
||||
size_t offset, unsigned long flags,
|
||||
void *ctor,
|
||||
void *dtor)
|
||||
{
|
||||
//TODO: Take in account ctor and dtor - callbacks for alloc/free, flags and offset
|
||||
//FIXME: We assume this cache is always NPaged
|
||||
PNPAGED_LOOKASIDE_LIST Lookaside;
|
||||
ULONG Tag=0x11223344; //FIXME: Make this from tag
|
||||
|
||||
Lookaside = ExAllocatePool(NonPagedPool, sizeof(NPAGED_LOOKASIDE_LIST));
|
||||
|
||||
ExInitializeNPagedLookasideList(
|
||||
Lookaside,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
alloc_size,
|
||||
Tag,
|
||||
0);
|
||||
|
||||
return (kmem_cache_t *)Lookaside;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
BOOLEAN my_kmem_cache_destroy(kmem_cache_t *co)
|
||||
{
|
||||
ExDeleteNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co);
|
||||
|
||||
ExFreePool(co);
|
||||
return FALSE;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void *my_kmem_cache_alloc(kmem_cache_t *co, int flags)
|
||||
{
|
||||
return ExAllocateFromNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_kmem_cache_free(kmem_cache_t *co, void *ptr)
|
||||
{
|
||||
ExFreeToNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co, ptr);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// DMA, not used now
|
||||
/*------------------------------------------------------------------------*/
|
||||
void *my_dma_pool_alloc(struct dma_pool *pool, int gfp_flags, dma_addr_t *dma_handle)
|
||||
{
|
||||
// HalAllocCommonBuffer
|
||||
// But ideally IoGetDmaAdapter
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* USB support based on Linux kernel source
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
* Concept:
|
||||
*
|
||||
* 1) Forget all device interrupts, scheduling, semaphores, threads etc.
|
||||
* 1a) Forget all DMA and PCI helper functions
|
||||
* 2) Forget usbdevfs, procfs and ioctls
|
||||
* 3) Emulate OHCI interrupts and root hub timer by polling
|
||||
* 4) Emulate hub kernel thread by polling
|
||||
* 5) Emulate synchronous USB-messages (usb_*_msg) with busy waiting
|
||||
*
|
||||
* To be done:
|
||||
* 6) Remove code bloat
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
/* internal state */
|
||||
|
||||
static struct pci_dev *pci_probe_dev;
|
||||
extern int (*thread_handler)(void*);
|
||||
extern void* thread_parm;
|
||||
|
||||
struct my_irqs reg_irqs[MAX_IRQS];
|
||||
int num_irqs;
|
||||
int need_wakeup;
|
||||
|
||||
int my_jiffies;
|
||||
|
||||
struct timer_list *main_timer_list[MAX_TIMERS];
|
||||
struct dummy_process act_cur={0};
|
||||
struct dummy_process *my_current;
|
||||
|
||||
int (*thread_handler)(void*);
|
||||
void* thread_parm;
|
||||
|
||||
#define MAX_DRVS 8
|
||||
static struct device_driver *m_drivers[MAX_DRVS];
|
||||
static int drvs_num;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Helper functions for top-level system
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
void init_wrapper(struct pci_dev *probe_dev)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
{
|
||||
main_timer_list[n]=NULL;
|
||||
}
|
||||
|
||||
my_jiffies=0;
|
||||
num_irqs=0;
|
||||
my_current=&act_cur;
|
||||
pci_probe_dev=probe_dev;
|
||||
|
||||
for(n=0;n<MAX_IRQS;n++)
|
||||
{
|
||||
reg_irqs[n].handler=NULL;
|
||||
reg_irqs[n].irq=-1;
|
||||
}
|
||||
drvs_num=0;
|
||||
need_wakeup=0;
|
||||
for(n=0;n<MAX_DRVS;n++)
|
||||
m_drivers[n]=NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void handle_irqs(int irq)
|
||||
{
|
||||
int n;
|
||||
printk("handle irqs\n");
|
||||
for(n=0;n<MAX_IRQS;n++)
|
||||
{
|
||||
if (reg_irqs[n].handler && (irq==reg_irqs[n].irq || irq==-1))
|
||||
reg_irqs[n].handler(reg_irqs[n].irq,reg_irqs[n].data,NULL);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void inc_jiffies(int n)
|
||||
{
|
||||
my_jiffies+=n;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void do_all_timers(void)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
{
|
||||
if (main_timer_list[n] &&
|
||||
main_timer_list[n]->function && main_timer_list[n]->expires)
|
||||
{
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
main_timer_list[n]->expires=0;
|
||||
|
||||
main_timer_list[n]=NULL; // remove timer
|
||||
printk("do timer %i fn %p\n",n,function);
|
||||
|
||||
function(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Purpose: Remember thread procedure and data in global var
|
||||
// ReactOS Purpose: Create real kernel thread
|
||||
int my_kernel_thread(int STDCALL (*handler)(void*), void* parm, int flags)
|
||||
{
|
||||
HANDLE hThread;
|
||||
//thread_handler=handler;
|
||||
//thread_parm=parm;
|
||||
//return 42; // PID :-)
|
||||
|
||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
PsCreateSystemThread(&hThread,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(PKSTART_ROUTINE)handler,
|
||||
parm);
|
||||
|
||||
return (int)hThread; // FIXME: Correct?
|
||||
}
|
||||
|
||||
// Kill the process
|
||||
int my_kill_proc(int pid, int signal, int unk)
|
||||
{
|
||||
HANDLE hThread;
|
||||
|
||||
// TODO: Implement actual process killing
|
||||
|
||||
hThread = (HANDLE)pid;
|
||||
ZwClose(hThread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Device management
|
||||
* As simple as possible, but as complete as necessary ...
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* calls probe function for hotplug (which does device matching), this is the
|
||||
only link between usbcore and the registered device drivers! */
|
||||
int my_device_add(struct device *dev)
|
||||
{
|
||||
int n,found=0;
|
||||
printk("drv_num %i %p %p\n",drvs_num,m_drivers[0]->probe,m_drivers[1]->probe);
|
||||
|
||||
if (dev->driver)
|
||||
{
|
||||
if (dev->driver->probe)
|
||||
return dev->driver->probe(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(n=0;n<drvs_num;n++)
|
||||
{
|
||||
if (m_drivers[n]->probe)
|
||||
{
|
||||
dev->driver=m_drivers[n];
|
||||
printk("probe%i %p ",n,m_drivers[n]->probe);
|
||||
|
||||
if (m_drivers[n]->probe(dev) == 0)
|
||||
{
|
||||
// return 0;
|
||||
found=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) return 0;
|
||||
}
|
||||
dev->driver=NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_driver_register(struct device_driver *driver)
|
||||
{
|
||||
|
||||
if (drvs_num<MAX_DRVS)
|
||||
{
|
||||
printk("driver_register %i: %p %p",drvs_num,driver,driver->probe);
|
||||
|
||||
m_drivers[drvs_num++]=driver;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_device_unregister(struct device *dev)
|
||||
{
|
||||
if (dev->driver && dev->driver->remove)
|
||||
dev->driver->remove(dev);
|
||||
return 0;
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct device *my_get_device(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_device_initialize(struct device *dev)
|
||||
{
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wake_up(PKEVENT evnt)
|
||||
{
|
||||
need_wakeup=1;
|
||||
|
||||
KeSetEvent(evnt, 0, FALSE); // Signal event
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_init_waitqueue_head(PKEVENT evnt)
|
||||
{
|
||||
// this is used only in core/message.c, and it isn't needed there
|
||||
//KeInitializeEvent(evnt, NotificationEvent, TRUE); // signalled state
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* wait until woken up (only one wait allowed!) */
|
||||
int my_schedule_timeout(int x)
|
||||
{
|
||||
int wait=1;
|
||||
x+=10; // safety
|
||||
printk("schedule_timeout %i\n",x);
|
||||
|
||||
while(x>0)
|
||||
{
|
||||
do_all_timers();
|
||||
#ifndef HAVE_IRQS
|
||||
handle_irqs(-1);
|
||||
|
||||
#endif
|
||||
if (need_wakeup)
|
||||
break;
|
||||
wait_ms(wait);
|
||||
inc_jiffies(wait);
|
||||
x-=wait;
|
||||
}
|
||||
need_wakeup=0;
|
||||
printk("schedule DONE!!!!!!\n");
|
||||
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wait_for_completion(struct completion *x)
|
||||
{
|
||||
int n=100;
|
||||
printk("wait for completion\n");
|
||||
|
||||
while(!x->done && (n>0))
|
||||
{
|
||||
do_all_timers();
|
||||
#ifndef HAVE_IRQS
|
||||
handle_irqs(-1);
|
||||
|
||||
#endif
|
||||
wait_ms(10);
|
||||
n--;
|
||||
}
|
||||
printk("wait for completion done %i\n",x->done);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_interruptible_sleep_on(PKEVENT evnt)
|
||||
{
|
||||
KeWaitForSingleObject(evnt, Executive, KernelMode, FALSE, NULL);
|
||||
KeClearEvent(evnt); // reset to not-signalled
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Helper for pci_module_init
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_module_init(struct pci_driver *x)
|
||||
{
|
||||
struct pci_dev *dev=pci_probe_dev;
|
||||
const struct pci_device_id *id=NULL;
|
||||
if (!pci_probe_dev)
|
||||
{
|
||||
DPRINT1("PCI device not set!\n");
|
||||
return 0;
|
||||
}
|
||||
x->probe(dev, id);
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct pci_dev *my_pci_find_slot(int a,int b)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
|
||||
{
|
||||
//dev->bus, dev->devfn, where, val
|
||||
OHCI_DEVICE_EXTENSION *dev_ext = (OHCI_DEVICE_EXTENSION *)dev->dev_ext;
|
||||
|
||||
//FIXME: Is returning this value correct?
|
||||
//FIXME: Mixing pci_dev and win structs isn't a good thing at all
|
||||
return HalSetBusDataByOffset(PCIConfiguration, dev->bus->number, dev_ext->SystemIoSlotNumber, &val, where, sizeof(val));
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_request_irq(unsigned int irq,
|
||||
int (*handler)(int,void *, struct pt_regs *),
|
||||
unsigned long mode, const char *desc, void *data)
|
||||
{
|
||||
if (num_irqs<MAX_IRQS)
|
||||
{
|
||||
reg_irqs[num_irqs].handler=handler;
|
||||
reg_irqs[num_irqs].irq=irq;
|
||||
reg_irqs[num_irqs].data=data;
|
||||
num_irqs++;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_free_irq(int irq, void* p)
|
||||
{
|
||||
/* No free... */
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Lookaside funcs
|
||||
/*------------------------------------------------------------------------*/
|
||||
kmem_cache_t *my_kmem_cache_create(const char *tag, size_t alloc_size,
|
||||
size_t offset, unsigned long flags,
|
||||
void *ctor,
|
||||
void *dtor)
|
||||
{
|
||||
//TODO: Take in account ctor and dtor - callbacks for alloc/free, flags and offset
|
||||
//FIXME: We assume this cache is always NPaged
|
||||
PNPAGED_LOOKASIDE_LIST Lookaside;
|
||||
ULONG Tag=0x11223344; //FIXME: Make this from tag
|
||||
|
||||
Lookaside = ExAllocatePool(NonPagedPool, sizeof(NPAGED_LOOKASIDE_LIST));
|
||||
|
||||
ExInitializeNPagedLookasideList(
|
||||
Lookaside,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
alloc_size,
|
||||
Tag,
|
||||
0);
|
||||
|
||||
return (kmem_cache_t *)Lookaside;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
BOOLEAN my_kmem_cache_destroy(kmem_cache_t *co)
|
||||
{
|
||||
ExDeleteNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co);
|
||||
|
||||
ExFreePool(co);
|
||||
return FALSE;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void *my_kmem_cache_alloc(kmem_cache_t *co, int flags)
|
||||
{
|
||||
return ExAllocateFromNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_kmem_cache_free(kmem_cache_t *co, void *ptr)
|
||||
{
|
||||
ExFreeToNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)co, ptr);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// DMA, not used now
|
||||
/*------------------------------------------------------------------------*/
|
||||
void *my_dma_pool_alloc(struct dma_pool *pool, int gfp_flags, dma_addr_t *dma_handle)
|
||||
{
|
||||
// HalAllocCommonBuffer
|
||||
// But ideally IoGetDmaAdapter
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,138 +1,138 @@
|
|||
#include "../usb_wrapper.h"
|
||||
#include "config.h"
|
||||
#include "xremote.h"
|
||||
|
||||
// This is for the Xpad
|
||||
extern unsigned char xpad_button_history[7];
|
||||
|
||||
// This is for the Keyboard
|
||||
extern unsigned int current_keyboard_key;
|
||||
|
||||
int risefall_xpad_BUTTON(unsigned char selected_Button) {
|
||||
|
||||
int xpad_id;
|
||||
int match;
|
||||
extern int xpad_num;
|
||||
|
||||
// USB keyboard section
|
||||
|
||||
match=0;
|
||||
if (current_keyboard_key!=0) {
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_KEY_A :
|
||||
if (current_keyboard_key == 0x28) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_KEY_B :
|
||||
if (current_keyboard_key == 0x29) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_UP :
|
||||
if (current_keyboard_key == 0x52) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN :
|
||||
if (current_keyboard_key == 0x51) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT :
|
||||
if (current_keyboard_key == 0x50) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT :
|
||||
if (current_keyboard_key == 0x4f) match=1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
//A match occurred, so the event has now been processed
|
||||
//Clear it, and return success
|
||||
current_keyboard_key=0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Xbox IR remote section
|
||||
|
||||
match=0;
|
||||
if (!remotekeyIsRepeat) {
|
||||
/* We only grab the key event when the button is first pressed.
|
||||
* If it's being held down, we ignore the multiple events this
|
||||
* generates */
|
||||
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_KEY_A:
|
||||
if (current_remote_key == RC_KEY_SELECT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_UP:
|
||||
if (current_remote_key == RC_KEY_UP) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN:
|
||||
if (current_remote_key == RC_KEY_DOWN) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT:
|
||||
if (current_remote_key == RC_KEY_LEFT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT:
|
||||
if (current_remote_key == RC_KEY_RIGHT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_KEY_BACK:
|
||||
if (current_remote_key == RC_KEY_BACK) match=1;
|
||||
break;
|
||||
}
|
||||
if (match) {
|
||||
//A match occurred, so the event has now been processed
|
||||
//Clear it, and return success
|
||||
current_remote_key=0;
|
||||
remotekeyIsRepeat=0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Xbox controller section
|
||||
if (selected_Button < 6) {
|
||||
|
||||
unsigned char Button;
|
||||
|
||||
Button = XPAD_current[0].keys[selected_Button];
|
||||
|
||||
if ((Button>0x30)&&(xpad_button_history[selected_Button]==0)) {
|
||||
// Button Rising Edge
|
||||
xpad_button_history[selected_Button] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((Button==0x00)&&(xpad_button_history[selected_Button]==1)) {
|
||||
// Button Falling Edge
|
||||
xpad_button_history[selected_Button] = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((selected_Button > 5) & (selected_Button < 10) ) {
|
||||
|
||||
unsigned char Buttonmask;
|
||||
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_PAD_UP :
|
||||
Buttonmask = XPAD_PAD_UP;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN :
|
||||
Buttonmask = XPAD_PAD_DOWN;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT :
|
||||
Buttonmask = XPAD_PAD_LEFT;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT :
|
||||
Buttonmask = XPAD_PAD_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Rising Edge
|
||||
if (((XPAD_current[0].pad&Buttonmask) != 0) & ((xpad_button_history[6]&Buttonmask) == 0)) {
|
||||
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
|
||||
return 1;
|
||||
}
|
||||
// Falling Edge
|
||||
if (((XPAD_current[0].pad&Buttonmask) == 0) & ((xpad_button_history[6]&Buttonmask) != 0)) {
|
||||
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#include "../usb_wrapper.h"
|
||||
#include "config.h"
|
||||
#include "xremote.h"
|
||||
|
||||
// This is for the Xpad
|
||||
extern unsigned char xpad_button_history[7];
|
||||
|
||||
// This is for the Keyboard
|
||||
extern unsigned int current_keyboard_key;
|
||||
|
||||
int risefall_xpad_BUTTON(unsigned char selected_Button) {
|
||||
|
||||
int xpad_id;
|
||||
int match;
|
||||
extern int xpad_num;
|
||||
|
||||
// USB keyboard section
|
||||
|
||||
match=0;
|
||||
if (current_keyboard_key!=0) {
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_KEY_A :
|
||||
if (current_keyboard_key == 0x28) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_KEY_B :
|
||||
if (current_keyboard_key == 0x29) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_UP :
|
||||
if (current_keyboard_key == 0x52) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN :
|
||||
if (current_keyboard_key == 0x51) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT :
|
||||
if (current_keyboard_key == 0x50) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT :
|
||||
if (current_keyboard_key == 0x4f) match=1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
//A match occurred, so the event has now been processed
|
||||
//Clear it, and return success
|
||||
current_keyboard_key=0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Xbox IR remote section
|
||||
|
||||
match=0;
|
||||
if (!remotekeyIsRepeat) {
|
||||
/* We only grab the key event when the button is first pressed.
|
||||
* If it's being held down, we ignore the multiple events this
|
||||
* generates */
|
||||
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_KEY_A:
|
||||
if (current_remote_key == RC_KEY_SELECT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_UP:
|
||||
if (current_remote_key == RC_KEY_UP) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN:
|
||||
if (current_remote_key == RC_KEY_DOWN) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT:
|
||||
if (current_remote_key == RC_KEY_LEFT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT:
|
||||
if (current_remote_key == RC_KEY_RIGHT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_KEY_BACK:
|
||||
if (current_remote_key == RC_KEY_BACK) match=1;
|
||||
break;
|
||||
}
|
||||
if (match) {
|
||||
//A match occurred, so the event has now been processed
|
||||
//Clear it, and return success
|
||||
current_remote_key=0;
|
||||
remotekeyIsRepeat=0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Xbox controller section
|
||||
if (selected_Button < 6) {
|
||||
|
||||
unsigned char Button;
|
||||
|
||||
Button = XPAD_current[0].keys[selected_Button];
|
||||
|
||||
if ((Button>0x30)&&(xpad_button_history[selected_Button]==0)) {
|
||||
// Button Rising Edge
|
||||
xpad_button_history[selected_Button] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((Button==0x00)&&(xpad_button_history[selected_Button]==1)) {
|
||||
// Button Falling Edge
|
||||
xpad_button_history[selected_Button] = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((selected_Button > 5) & (selected_Button < 10) ) {
|
||||
|
||||
unsigned char Buttonmask;
|
||||
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_PAD_UP :
|
||||
Buttonmask = XPAD_PAD_UP;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN :
|
||||
Buttonmask = XPAD_PAD_DOWN;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT :
|
||||
Buttonmask = XPAD_PAD_LEFT;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT :
|
||||
Buttonmask = XPAD_PAD_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Rising Edge
|
||||
if (((XPAD_current[0].pad&Buttonmask) != 0) & ((xpad_button_history[6]&Buttonmask) == 0)) {
|
||||
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
|
||||
return 1;
|
||||
}
|
||||
// Falling Edge
|
||||
if (((XPAD_current[0].pad&Buttonmask) == 0) & ((xpad_button_history[6]&Buttonmask) != 0)) {
|
||||
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "../usb_wrapper.h"
|
||||
|
||||
|
||||
void wait_ms(int mils)
|
||||
{
|
||||
LARGE_INTEGER Interval;
|
||||
|
||||
Interval.QuadPart = -mils*10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
|
||||
}
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
|
||||
void wait_ms(int mils)
|
||||
{
|
||||
LARGE_INTEGER Interval;
|
||||
|
||||
Interval.QuadPart = -mils*10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
|
||||
}
|
||||
|
|
|
@ -1,123 +1,123 @@
|
|||
#include "../usb_wrapper.h"
|
||||
|
||||
#define keyboarddebug 0
|
||||
|
||||
#if keyboarddebug
|
||||
extern int printe(const char *szFormat, ...);
|
||||
int ycoffset = 0;
|
||||
#endif
|
||||
|
||||
unsigned int current_keyboard_key;
|
||||
|
||||
struct usb_kbd_info {
|
||||
struct urb *urb;
|
||||
unsigned char kbd_pkt[8];
|
||||
unsigned char old[8];
|
||||
|
||||
/*
|
||||
struct input_dev dev;
|
||||
struct usb_device *usbdev;
|
||||
struct urb irq, led;
|
||||
struct usb_ctrlrequest dr;
|
||||
unsigned char leds, newleds;
|
||||
char name[128];
|
||||
int open;
|
||||
*/
|
||||
};
|
||||
|
||||
static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct usb_kbd_info *kbd = urb->context;
|
||||
int i;
|
||||
|
||||
if (urb->status) return;
|
||||
|
||||
memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8);
|
||||
|
||||
current_keyboard_key = kbd->kbd_pkt[2];
|
||||
|
||||
|
||||
#if keyboarddebug
|
||||
ycoffset += 15;
|
||||
ycoffset = ycoffset % 600;
|
||||
VIDEO_CURSOR_POSX=20;
|
||||
VIDEO_CURSOR_POSY=ycoffset;
|
||||
printe(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]);
|
||||
#endif
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
}
|
||||
|
||||
static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct usb_kbd_info *usbk;
|
||||
|
||||
int i, pipe, maxp;
|
||||
char *buf;
|
||||
|
||||
usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0);
|
||||
if (!usbk) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
usbk->urb=urb;
|
||||
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
usbk->kbd_pkt, 8, usb_kbd_irq,
|
||||
usbk, 8);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
usb_set_intfdata(intf,usbk);
|
||||
#if keyboarddebug
|
||||
printe("USB Keyboard Connected\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void usb_kbd_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_kbd_info *usbk = usb_get_intfdata (intf);
|
||||
usbprintk("Keyboard disconnected\n ");
|
||||
usb_unlink_urb(usbk->urb);
|
||||
usb_free_urb(usbk->urb);
|
||||
kfree(usbk);
|
||||
}
|
||||
|
||||
static struct usb_device_id usb_kbd_id_table [] = {
|
||||
{ USB_INTERFACE_INFO(3, 1, 1) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
static struct usb_driver usb_kbd_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "keyboard",
|
||||
.probe = usb_kbd_probe,
|
||||
.disconnect = usb_kbd_disconnect,
|
||||
.id_table = usb_kbd_id_table,
|
||||
};
|
||||
|
||||
void UsbKeyBoardInit(void)
|
||||
{
|
||||
|
||||
//current_remote_key=0;
|
||||
//sbprintk("Keyboard probe %p ",xremote_probe);
|
||||
if (usb_register(&usb_kbd_driver) < 0) {
|
||||
#if keyboarddebug
|
||||
printe("Unable to register Keyboard driver");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UsbKeyBoardRemove(void) {
|
||||
usb_deregister(&usb_kbd_driver);
|
||||
}
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
#define keyboarddebug 0
|
||||
|
||||
#if keyboarddebug
|
||||
extern int printe(const char *szFormat, ...);
|
||||
int ycoffset = 0;
|
||||
#endif
|
||||
|
||||
unsigned int current_keyboard_key;
|
||||
|
||||
struct usb_kbd_info {
|
||||
struct urb *urb;
|
||||
unsigned char kbd_pkt[8];
|
||||
unsigned char old[8];
|
||||
|
||||
/*
|
||||
struct input_dev dev;
|
||||
struct usb_device *usbdev;
|
||||
struct urb irq, led;
|
||||
struct usb_ctrlrequest dr;
|
||||
unsigned char leds, newleds;
|
||||
char name[128];
|
||||
int open;
|
||||
*/
|
||||
};
|
||||
|
||||
static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct usb_kbd_info *kbd = urb->context;
|
||||
int i;
|
||||
|
||||
if (urb->status) return;
|
||||
|
||||
memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8);
|
||||
|
||||
current_keyboard_key = kbd->kbd_pkt[2];
|
||||
|
||||
|
||||
#if keyboarddebug
|
||||
ycoffset += 15;
|
||||
ycoffset = ycoffset % 600;
|
||||
VIDEO_CURSOR_POSX=20;
|
||||
VIDEO_CURSOR_POSY=ycoffset;
|
||||
printe(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]);
|
||||
#endif
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
}
|
||||
|
||||
static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct usb_kbd_info *usbk;
|
||||
|
||||
int i, pipe, maxp;
|
||||
char *buf;
|
||||
|
||||
usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0);
|
||||
if (!usbk) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
usbk->urb=urb;
|
||||
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
usbk->kbd_pkt, 8, usb_kbd_irq,
|
||||
usbk, 8);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
usb_set_intfdata(intf,usbk);
|
||||
#if keyboarddebug
|
||||
printe("USB Keyboard Connected\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void usb_kbd_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_kbd_info *usbk = usb_get_intfdata (intf);
|
||||
usbprintk("Keyboard disconnected\n ");
|
||||
usb_unlink_urb(usbk->urb);
|
||||
usb_free_urb(usbk->urb);
|
||||
kfree(usbk);
|
||||
}
|
||||
|
||||
static struct usb_device_id usb_kbd_id_table [] = {
|
||||
{ USB_INTERFACE_INFO(3, 1, 1) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
static struct usb_driver usb_kbd_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "keyboard",
|
||||
.probe = usb_kbd_probe,
|
||||
.disconnect = usb_kbd_disconnect,
|
||||
.id_table = usb_kbd_id_table,
|
||||
};
|
||||
|
||||
void UsbKeyBoardInit(void)
|
||||
{
|
||||
|
||||
//current_remote_key=0;
|
||||
//sbprintk("Keyboard probe %p ",xremote_probe);
|
||||
if (usb_register(&usb_kbd_driver) < 0) {
|
||||
#if keyboarddebug
|
||||
printe("Unable to register Keyboard driver");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UsbKeyBoardRemove(void) {
|
||||
usb_deregister(&usb_kbd_driver);
|
||||
}
|
||||
|
|
|
@ -1,65 +1,65 @@
|
|||
/*
|
||||
* Interface calls to BIOS
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "boot.h"
|
||||
#include <stdarg.h>
|
||||
#include "video.h"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Output window for USB messages
|
||||
int usb_curs_x=0;
|
||||
int usb_curs_y=0;
|
||||
|
||||
void zxprintf(char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[1024];
|
||||
int tmp_x, tmp_y;
|
||||
tmp_x=VIDEO_CURSOR_POSX;
|
||||
tmp_y=VIDEO_CURSOR_POSY;
|
||||
|
||||
VIDEO_CURSOR_POSX=usb_curs_x;
|
||||
VIDEO_CURSOR_POSY=usb_curs_y;
|
||||
|
||||
if ((VIDEO_CURSOR_POSY==0) || (VIDEO_CURSOR_POSY > (vmode.height -16)))
|
||||
{
|
||||
BootVideoClearScreen(&jpegBackdrop, 3*vmode.height/4,
|
||||
vmode.height);
|
||||
VIDEO_CURSOR_POSY=3*vmode.height/4;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buffer,fmt,ap);
|
||||
//printk(buffer);
|
||||
va_end(ap);
|
||||
|
||||
usb_curs_x=VIDEO_CURSOR_POSX;
|
||||
usb_curs_y=VIDEO_CURSOR_POSY;
|
||||
VIDEO_CURSOR_POSX=tmp_x;
|
||||
VIDEO_CURSOR_POSY=tmp_y;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int zxsnprintf(char *buffer, size_t s, char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int x;
|
||||
va_start(ap, fmt);
|
||||
x=vsprintf(buffer,fmt,ap);
|
||||
va_end(ap);
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int zxsprintf(char *buffer, char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int x;
|
||||
va_start(ap, fmt);
|
||||
x=vsprintf(buffer,fmt,ap);
|
||||
va_end(ap);
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Interface calls to BIOS
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "boot.h"
|
||||
#include <stdarg.h>
|
||||
#include "video.h"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Output window for USB messages
|
||||
int usb_curs_x=0;
|
||||
int usb_curs_y=0;
|
||||
|
||||
void zxprintf(char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[1024];
|
||||
int tmp_x, tmp_y;
|
||||
tmp_x=VIDEO_CURSOR_POSX;
|
||||
tmp_y=VIDEO_CURSOR_POSY;
|
||||
|
||||
VIDEO_CURSOR_POSX=usb_curs_x;
|
||||
VIDEO_CURSOR_POSY=usb_curs_y;
|
||||
|
||||
if ((VIDEO_CURSOR_POSY==0) || (VIDEO_CURSOR_POSY > (vmode.height -16)))
|
||||
{
|
||||
BootVideoClearScreen(&jpegBackdrop, 3*vmode.height/4,
|
||||
vmode.height);
|
||||
VIDEO_CURSOR_POSY=3*vmode.height/4;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buffer,fmt,ap);
|
||||
//printk(buffer);
|
||||
va_end(ap);
|
||||
|
||||
usb_curs_x=VIDEO_CURSOR_POSX;
|
||||
usb_curs_y=VIDEO_CURSOR_POSY;
|
||||
VIDEO_CURSOR_POSX=tmp_x;
|
||||
VIDEO_CURSOR_POSY=tmp_y;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int zxsnprintf(char *buffer, size_t s, char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int x;
|
||||
va_start(ap, fmt);
|
||||
x=vsprintf(buffer,fmt,ap);
|
||||
va_end(ap);
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int zxsprintf(char *buffer, char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int x;
|
||||
va_start(ap, fmt);
|
||||
x=vsprintf(buffer,fmt,ap);
|
||||
va_end(ap);
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1,183 +1,183 @@
|
|||
/*
|
||||
* Simple XPAD driver for XBOX
|
||||
*
|
||||
* (c) 2003-07-04, Georg Acher (georg@acher.org)
|
||||
*
|
||||
* Inspired by linux/drivers/usb/input/xpad.c
|
||||
* by Marko Friedemann <mfr@bmx-chemnitz.de>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
#include "config.h"
|
||||
|
||||
// history for the Rising - falling events
|
||||
unsigned char xpad_button_history[7];
|
||||
|
||||
/* Stores time and XPAD state */
|
||||
struct xpad_data XPAD_current[4];
|
||||
struct xpad_data XPAD_last[4];
|
||||
|
||||
struct xpad_info
|
||||
{
|
||||
struct urb *urb;
|
||||
int num;
|
||||
unsigned char data[32];
|
||||
};
|
||||
|
||||
int xpad_num=0;
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void xpad_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct xpad_info *xpi = urb->context;
|
||||
unsigned char* data= urb->transfer_buffer;
|
||||
|
||||
// struct xpad_data *xp=&XPAD_current[xpi->num];
|
||||
// struct xpad_data *xpo=&XPAD_last[xpi->num];
|
||||
|
||||
/* This hack means the xpad event always gets posted to the
|
||||
* first xpad - avoids problems iterating over multiple xpads
|
||||
* as the xpi->num entries are not reused when xpads are
|
||||
* connected, then removed */
|
||||
|
||||
struct xpad_data *xp=&XPAD_current[0];
|
||||
struct xpad_data *xpo=&XPAD_last[0];
|
||||
|
||||
if (xpi->num<0 || xpi->num>3)
|
||||
return;
|
||||
|
||||
memcpy(xpo,xp,sizeof(struct xpad_data));
|
||||
|
||||
xp->stick_left_x=(short) (((short)data[13] << 8) | data[12]);
|
||||
xp->stick_left_y=(short) (((short)data[15] << 8) | data[14]);
|
||||
xp->stick_right_x=(short) (((short)data[17] << 8) | data[16]);
|
||||
xp->stick_right_y=(short) (((short)data[19] << 8) | data[18]);
|
||||
xp->trig_left= data[10];
|
||||
xp->trig_right= data[11];
|
||||
xp->pad = data[2]&0xf;
|
||||
xp->state = (data[2]>>4)&0xf;
|
||||
xp->keys[0] = data[4]; // a
|
||||
xp->keys[1] = data[5]; // b
|
||||
xp->keys[2] = data[6]; // x
|
||||
xp->keys[3] = data[7]; // y
|
||||
xp->keys[4] = data[8]; // black
|
||||
xp->keys[5] = data[9]; // white
|
||||
xp->timestamp=jiffies; // FIXME: A more uniform flowing time would be better...
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct xpad_info *xpi;
|
||||
|
||||
xpi=kmalloc(sizeof(struct xpad_info),GFP_KERNEL);
|
||||
if (!xpi) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
xpi->urb=urb;
|
||||
xpi->num=xpad_num;
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
xpi->data, 32, xpad_irq,
|
||||
xpi, 32);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
usb_set_intfdata(intf,xpi);
|
||||
usbprintk("XPAD #%i connected\n",xpad_num);
|
||||
#ifdef XPAD_VIBRA_STARTUP
|
||||
{
|
||||
// Brum Brum
|
||||
char data1[6]={0,6,0,120,0,120};
|
||||
char data2[6]={0,6,0,0,0,0};
|
||||
int dummy;
|
||||
|
||||
usb_bulk_msg(udev, usb_sndbulkpipe(udev,2),
|
||||
data1, 6, &dummy, 500);
|
||||
wait_ms(500);
|
||||
usb_bulk_msg(udev, usb_sndbulkpipe(udev,2),
|
||||
data2, 6, &dummy, 500);
|
||||
}
|
||||
#endif
|
||||
xpad_num++;
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void xpad_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct xpad_info *xpi=usb_get_intfdata (intf);
|
||||
usb_unlink_urb(xpi->urb);
|
||||
usb_free_urb(xpi->urb);
|
||||
kfree(xpi);
|
||||
xpad_num--;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static struct usb_device_id xpad_ids [] = {
|
||||
{ USB_DEVICE(0x044f, 0x0f07) },//Thrustmaster, Inc. Controller
|
||||
{ USB_DEVICE(0x045e, 0x0202) },//Microsoft Xbox Controller
|
||||
{ USB_DEVICE(0x045e, 0x0285) },//Microsoft Xbox Controller S
|
||||
{ USB_DEVICE(0x045e, 0x0289) },//Microsoft Xbox Controller S
|
||||
{ USB_DEVICE(0x046d, 0xca88) },//Logitech Compact Controller for Xbox
|
||||
{ USB_DEVICE(0x05fd, 0x1007) },//???Mad Catz Controller???
|
||||
{ USB_DEVICE(0x05fd, 0x107a) },//InterAct PowerPad Pro
|
||||
{ USB_DEVICE(0x0738, 0x4516) },//Mad Catz Control Pad
|
||||
{ USB_DEVICE(0x0738, 0x4522) },//Mad Catz LumiCON
|
||||
{ USB_DEVICE(0x0738, 0x4526) },//Mad Catz Control Pad Pro
|
||||
{ USB_DEVICE(0x0738, 0x4536) },//Mad Catz MicroCON
|
||||
{ USB_DEVICE(0x0738, 0x4556) },//Mad Catz Lynx Wireless Controller
|
||||
{ USB_DEVICE(0x0c12, 0x9902) },//HAMA VibraX - *FAULTY HARDWARE*
|
||||
{ USB_DEVICE(0x0e4c, 0x1097) },//Radica Gamester Controller
|
||||
{ USB_DEVICE(0x0e4c, 0x2390) },//Radica Games Jtech Controller
|
||||
{ USB_DEVICE(0x0e6f, 0x0003) },//Logic3 Freebird wireless Controller
|
||||
{ USB_DEVICE(0x0e6f, 0x0005) },//Eclipse wireless Controlle
|
||||
{ USB_DEVICE(0x0f30, 0x0202) },//Joytech Advanced Controller
|
||||
{ USB_DEVICE(0xffff, 0xffff) },//Chinese-made Xbox Controller
|
||||
{ USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
static struct usb_driver xpad_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "XPAD",
|
||||
.probe = xpad_probe,
|
||||
.disconnect = xpad_disconnect,
|
||||
.id_table = xpad_ids,
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void XPADInit(void)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<4;n++)
|
||||
{
|
||||
memset(&XPAD_current[n], 0, sizeof(struct xpad_data));
|
||||
memset(&XPAD_last[n], 0, sizeof(struct xpad_data));
|
||||
}
|
||||
memset(&xpad_button_history, 0, sizeof(xpad_button_history));
|
||||
|
||||
usbprintk("XPAD probe %p ",xpad_probe);
|
||||
if (usb_register(&xpad_driver) < 0) {
|
||||
err("Unable to register XPAD driver");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void XPADRemove(void) {
|
||||
usb_deregister(&xpad_driver);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Simple XPAD driver for XBOX
|
||||
*
|
||||
* (c) 2003-07-04, Georg Acher (georg@acher.org)
|
||||
*
|
||||
* Inspired by linux/drivers/usb/input/xpad.c
|
||||
* by Marko Friedemann <mfr@bmx-chemnitz.de>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
#include "config.h"
|
||||
|
||||
// history for the Rising - falling events
|
||||
unsigned char xpad_button_history[7];
|
||||
|
||||
/* Stores time and XPAD state */
|
||||
struct xpad_data XPAD_current[4];
|
||||
struct xpad_data XPAD_last[4];
|
||||
|
||||
struct xpad_info
|
||||
{
|
||||
struct urb *urb;
|
||||
int num;
|
||||
unsigned char data[32];
|
||||
};
|
||||
|
||||
int xpad_num=0;
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void xpad_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct xpad_info *xpi = urb->context;
|
||||
unsigned char* data= urb->transfer_buffer;
|
||||
|
||||
// struct xpad_data *xp=&XPAD_current[xpi->num];
|
||||
// struct xpad_data *xpo=&XPAD_last[xpi->num];
|
||||
|
||||
/* This hack means the xpad event always gets posted to the
|
||||
* first xpad - avoids problems iterating over multiple xpads
|
||||
* as the xpi->num entries are not reused when xpads are
|
||||
* connected, then removed */
|
||||
|
||||
struct xpad_data *xp=&XPAD_current[0];
|
||||
struct xpad_data *xpo=&XPAD_last[0];
|
||||
|
||||
if (xpi->num<0 || xpi->num>3)
|
||||
return;
|
||||
|
||||
memcpy(xpo,xp,sizeof(struct xpad_data));
|
||||
|
||||
xp->stick_left_x=(short) (((short)data[13] << 8) | data[12]);
|
||||
xp->stick_left_y=(short) (((short)data[15] << 8) | data[14]);
|
||||
xp->stick_right_x=(short) (((short)data[17] << 8) | data[16]);
|
||||
xp->stick_right_y=(short) (((short)data[19] << 8) | data[18]);
|
||||
xp->trig_left= data[10];
|
||||
xp->trig_right= data[11];
|
||||
xp->pad = data[2]&0xf;
|
||||
xp->state = (data[2]>>4)&0xf;
|
||||
xp->keys[0] = data[4]; // a
|
||||
xp->keys[1] = data[5]; // b
|
||||
xp->keys[2] = data[6]; // x
|
||||
xp->keys[3] = data[7]; // y
|
||||
xp->keys[4] = data[8]; // black
|
||||
xp->keys[5] = data[9]; // white
|
||||
xp->timestamp=jiffies; // FIXME: A more uniform flowing time would be better...
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct xpad_info *xpi;
|
||||
|
||||
xpi=kmalloc(sizeof(struct xpad_info),GFP_KERNEL);
|
||||
if (!xpi) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
xpi->urb=urb;
|
||||
xpi->num=xpad_num;
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
xpi->data, 32, xpad_irq,
|
||||
xpi, 32);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
usb_set_intfdata(intf,xpi);
|
||||
usbprintk("XPAD #%i connected\n",xpad_num);
|
||||
#ifdef XPAD_VIBRA_STARTUP
|
||||
{
|
||||
// Brum Brum
|
||||
char data1[6]={0,6,0,120,0,120};
|
||||
char data2[6]={0,6,0,0,0,0};
|
||||
int dummy;
|
||||
|
||||
usb_bulk_msg(udev, usb_sndbulkpipe(udev,2),
|
||||
data1, 6, &dummy, 500);
|
||||
wait_ms(500);
|
||||
usb_bulk_msg(udev, usb_sndbulkpipe(udev,2),
|
||||
data2, 6, &dummy, 500);
|
||||
}
|
||||
#endif
|
||||
xpad_num++;
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void xpad_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct xpad_info *xpi=usb_get_intfdata (intf);
|
||||
usb_unlink_urb(xpi->urb);
|
||||
usb_free_urb(xpi->urb);
|
||||
kfree(xpi);
|
||||
xpad_num--;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static struct usb_device_id xpad_ids [] = {
|
||||
{ USB_DEVICE(0x044f, 0x0f07) },//Thrustmaster, Inc. Controller
|
||||
{ USB_DEVICE(0x045e, 0x0202) },//Microsoft Xbox Controller
|
||||
{ USB_DEVICE(0x045e, 0x0285) },//Microsoft Xbox Controller S
|
||||
{ USB_DEVICE(0x045e, 0x0289) },//Microsoft Xbox Controller S
|
||||
{ USB_DEVICE(0x046d, 0xca88) },//Logitech Compact Controller for Xbox
|
||||
{ USB_DEVICE(0x05fd, 0x1007) },//???Mad Catz Controller???
|
||||
{ USB_DEVICE(0x05fd, 0x107a) },//InterAct PowerPad Pro
|
||||
{ USB_DEVICE(0x0738, 0x4516) },//Mad Catz Control Pad
|
||||
{ USB_DEVICE(0x0738, 0x4522) },//Mad Catz LumiCON
|
||||
{ USB_DEVICE(0x0738, 0x4526) },//Mad Catz Control Pad Pro
|
||||
{ USB_DEVICE(0x0738, 0x4536) },//Mad Catz MicroCON
|
||||
{ USB_DEVICE(0x0738, 0x4556) },//Mad Catz Lynx Wireless Controller
|
||||
{ USB_DEVICE(0x0c12, 0x9902) },//HAMA VibraX - *FAULTY HARDWARE*
|
||||
{ USB_DEVICE(0x0e4c, 0x1097) },//Radica Gamester Controller
|
||||
{ USB_DEVICE(0x0e4c, 0x2390) },//Radica Games Jtech Controller
|
||||
{ USB_DEVICE(0x0e6f, 0x0003) },//Logic3 Freebird wireless Controller
|
||||
{ USB_DEVICE(0x0e6f, 0x0005) },//Eclipse wireless Controlle
|
||||
{ USB_DEVICE(0x0f30, 0x0202) },//Joytech Advanced Controller
|
||||
{ USB_DEVICE(0xffff, 0xffff) },//Chinese-made Xbox Controller
|
||||
{ USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
static struct usb_driver xpad_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "XPAD",
|
||||
.probe = xpad_probe,
|
||||
.disconnect = xpad_disconnect,
|
||||
.id_table = xpad_ids,
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void XPADInit(void)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<4;n++)
|
||||
{
|
||||
memset(&XPAD_current[n], 0, sizeof(struct xpad_data));
|
||||
memset(&XPAD_last[n], 0, sizeof(struct xpad_data));
|
||||
}
|
||||
memset(&xpad_button_history, 0, sizeof(xpad_button_history));
|
||||
|
||||
usbprintk("XPAD probe %p ",xpad_probe);
|
||||
if (usb_register(&xpad_driver) < 0) {
|
||||
err("Unable to register XPAD driver");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void XPADRemove(void) {
|
||||
usb_deregister(&xpad_driver);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,142 +1,142 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: xremote.c,v 1.5 2004/11/22 19:10:57 davidmpye Exp $
|
||||
*
|
||||
* Copyright (c) 2002 Steven Toth <steve@toth.demon.co.uk>
|
||||
*
|
||||
* XBOX DVD dongle infrared device driver for the input driver suite.
|
||||
*
|
||||
* This work was derived from the usbkbd.c kernel module.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* 2002_08_31 - 0.1 - Initial release
|
||||
* 2002_09_02 - 0.2 - Added IOCTL support enabling user space administration
|
||||
* of the translation matrix.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
|
||||
u16 current_remote_key;
|
||||
u8 remotekeyIsRepeat;
|
||||
|
||||
struct xremote_info
|
||||
{
|
||||
struct urb *urb;
|
||||
unsigned char irpkt[8];
|
||||
};
|
||||
|
||||
/* USB callback completion handler
|
||||
* Code in transfer_buffer is received as six unsigned chars
|
||||
* Example PLAY=00 06 ea 0a 40 00
|
||||
* The command is located in byte[2], the rest are ignored.
|
||||
* Key position is byte[4] bit0 (7-0 format) 0=down, 1=up
|
||||
* All other bits are unknown / now required.
|
||||
*/
|
||||
|
||||
static void xremote_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct xremote_info *xri = urb->context;
|
||||
|
||||
if (urb->status) return;
|
||||
if (urb->actual_length < 6) return;
|
||||
|
||||
/* Messy/unnecessary, fix this */
|
||||
memcpy(xri->irpkt, urb->transfer_buffer, 6);
|
||||
|
||||
/* Set the key action based in the sent action */
|
||||
current_remote_key = ((xri->irpkt[2] & 0xff)<<8) | (xri->irpkt[3] & 0xff);
|
||||
|
||||
if (((xri->irpkt[4] & 0xff) + ((xri->irpkt[5] & 0xff ) << 8))>0x41) {
|
||||
remotekeyIsRepeat=0;
|
||||
}
|
||||
else remotekeyIsRepeat=1;
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static int xremote_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct xremote_info *xri;
|
||||
|
||||
xri=(struct xremote_info *)kmalloc(sizeof(struct xremote_info),0);
|
||||
if (!xri) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
xri->urb=urb;
|
||||
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
xri->irpkt, 8, xremote_irq,
|
||||
xri, 8);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
usb_set_intfdata(intf,xri);
|
||||
|
||||
usbprintk("DVD Remote connected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xremote_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct xremote_info *xri = usb_get_intfdata (intf);
|
||||
usbprintk("DVD Remote disconnected\n ");
|
||||
usb_unlink_urb(xri->urb);
|
||||
usb_free_urb(xri->urb);
|
||||
kfree(xri);
|
||||
}
|
||||
|
||||
static struct usb_device_id xremote_id_table [] = {
|
||||
{ USB_DEVICE(0x040b, 0x6521) }, /* Gamester Xbox DVD Movie Playback Kit IR */
|
||||
{ USB_DEVICE(0x045e, 0x0284) }, /* Microsoft Xbox DVD Movie Playback Kit IR */
|
||||
{ USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
static struct usb_driver xremote_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "XRemote",
|
||||
.probe = xremote_probe,
|
||||
.disconnect = xremote_disconnect,
|
||||
.id_table = xremote_id_table,
|
||||
};
|
||||
|
||||
void XRemoteInit(void)
|
||||
{
|
||||
|
||||
current_remote_key=0;
|
||||
usbprintk("XRemote probe %p ",xremote_probe);
|
||||
if (usb_register(&xremote_driver) < 0) {
|
||||
err("Unable to register XRemote driver");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XRemoteRemove(void) {
|
||||
usb_deregister(&xremote_driver);
|
||||
}
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2002 Steven Toth <steve@toth.demon.co.uk>
|
||||
*
|
||||
* XBOX DVD dongle infrared device driver for the input driver suite.
|
||||
*
|
||||
* This work was derived from the usbkbd.c kernel module.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* 2002_08_31 - 0.1 - Initial release
|
||||
* 2002_09_02 - 0.2 - Added IOCTL support enabling user space administration
|
||||
* of the translation matrix.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
|
||||
u16 current_remote_key;
|
||||
u8 remotekeyIsRepeat;
|
||||
|
||||
struct xremote_info
|
||||
{
|
||||
struct urb *urb;
|
||||
unsigned char irpkt[8];
|
||||
};
|
||||
|
||||
/* USB callback completion handler
|
||||
* Code in transfer_buffer is received as six unsigned chars
|
||||
* Example PLAY=00 06 ea 0a 40 00
|
||||
* The command is located in byte[2], the rest are ignored.
|
||||
* Key position is byte[4] bit0 (7-0 format) 0=down, 1=up
|
||||
* All other bits are unknown / now required.
|
||||
*/
|
||||
|
||||
static void xremote_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct xremote_info *xri = urb->context;
|
||||
|
||||
if (urb->status) return;
|
||||
if (urb->actual_length < 6) return;
|
||||
|
||||
/* Messy/unnecessary, fix this */
|
||||
memcpy(xri->irpkt, urb->transfer_buffer, 6);
|
||||
|
||||
/* Set the key action based in the sent action */
|
||||
current_remote_key = ((xri->irpkt[2] & 0xff)<<8) | (xri->irpkt[3] & 0xff);
|
||||
|
||||
if (((xri->irpkt[4] & 0xff) + ((xri->irpkt[5] & 0xff ) << 8))>0x41) {
|
||||
remotekeyIsRepeat=0;
|
||||
}
|
||||
else remotekeyIsRepeat=1;
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static int xremote_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct xremote_info *xri;
|
||||
|
||||
xri=(struct xremote_info *)kmalloc(sizeof(struct xremote_info),0);
|
||||
if (!xri) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
xri->urb=urb;
|
||||
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
xri->irpkt, 8, xremote_irq,
|
||||
xri, 8);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
usb_set_intfdata(intf,xri);
|
||||
|
||||
usbprintk("DVD Remote connected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xremote_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct xremote_info *xri = usb_get_intfdata (intf);
|
||||
usbprintk("DVD Remote disconnected\n ");
|
||||
usb_unlink_urb(xri->urb);
|
||||
usb_free_urb(xri->urb);
|
||||
kfree(xri);
|
||||
}
|
||||
|
||||
static struct usb_device_id xremote_id_table [] = {
|
||||
{ USB_DEVICE(0x040b, 0x6521) }, /* Gamester Xbox DVD Movie Playback Kit IR */
|
||||
{ USB_DEVICE(0x045e, 0x0284) }, /* Microsoft Xbox DVD Movie Playback Kit IR */
|
||||
{ USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
static struct usb_driver xremote_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "XRemote",
|
||||
.probe = xremote_probe,
|
||||
.disconnect = xremote_disconnect,
|
||||
.id_table = xremote_id_table,
|
||||
};
|
||||
|
||||
void XRemoteInit(void)
|
||||
{
|
||||
|
||||
current_remote_key=0;
|
||||
usbprintk("XRemote probe %p ",xremote_probe);
|
||||
if (usb_register(&xremote_driver) < 0) {
|
||||
err("Unable to register XRemote driver");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XRemoteRemove(void) {
|
||||
usb_deregister(&xremote_driver);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = uhci
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a usbcore.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -DDEBUG_MODE
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
uhci-hcd.o uhci_main.o ../sys/ros_wrapper.o ../sys/linuxwrapper.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = uhci
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a usbcore.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -DDEBUG_MODE
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
uhci-hcd.o uhci_main.o ../sys/ros_wrapper.o ../sys/linuxwrapper.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
|
|
|
@ -42,11 +42,15 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_DEBUG
|
||||
#define DEBUG
|
||||
#else
|
||||
#undef DEBUG
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -79,9 +83,9 @@
|
|||
* debug = 3, show all TD's in URB's when dumping
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
static int debug = 1;
|
||||
static int debug = 3;
|
||||
#else
|
||||
static int debug = 0;
|
||||
static int debug = 2;
|
||||
#endif
|
||||
MODULE_PARM(debug, "i");
|
||||
MODULE_PARM_DESC(debug, "Debug level");
|
||||
|
@ -1873,7 +1877,7 @@ static void uhci_remove_pending_qhs(struct uhci_hcd *uhci)
|
|||
spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags);
|
||||
}
|
||||
|
||||
static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
|
||||
static int uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
|
||||
{
|
||||
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
|
||||
unsigned int io_addr = uhci->io_addr;
|
||||
|
@ -1886,7 +1890,7 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
|
|||
*/
|
||||
status = inw(io_addr + USBSTS);
|
||||
if (!status) /* shared interrupt, not mine */
|
||||
return;
|
||||
return 0;
|
||||
outw(status, io_addr + USBSTS); /* Clear it */
|
||||
|
||||
if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
|
||||
|
@ -1925,6 +1929,8 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
|
|||
spin_unlock(&uhci->urb_list_lock);
|
||||
|
||||
uhci_finish_completion(hcd, regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reset_hc(struct uhci_hcd *uhci)
|
||||
|
@ -2271,6 +2277,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
|
|||
err("unable to allocate root hub");
|
||||
goto err_alloc_root_hub;
|
||||
}
|
||||
hcd->pdev->bus = (struct pci_bus *)udev; /* Fix bus pointer for initial device */
|
||||
|
||||
uhci->term_td = uhci_alloc_td(uhci, udev);
|
||||
if (!uhci->term_td) {
|
||||
|
@ -2484,7 +2491,7 @@ static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
|
|||
|
||||
static const char hcd_name[] = "uhci-hcd";
|
||||
|
||||
static const struct hc_driver uhci_driver = {
|
||||
static struct hc_driver uhci_driver = {
|
||||
.description = hcd_name,
|
||||
|
||||
/* Generic hardware linkage */
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
LIBRARY uhci.sys
|
||||
EXPORTS
|
||||
LIBRARY uhci.sys
|
||||
EXPORTS
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB UHCI Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "uhci\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "uhci.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB UHCI Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "uhci\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "uhci.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Configs for UHCI
|
||||
*/
|
||||
|
||||
#define CONFIG_PCI
|
||||
/*
|
||||
* Configs for UHCI
|
||||
*/
|
||||
|
||||
#define CONFIG_PCI
|
||||
|
|
|
@ -1,309 +1,337 @@
|
|||
/*
|
||||
ReactOS specific functions for UHCI module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
#include "../linux/linux_wrapper.h"
|
||||
#include "../host/ohci_main.h"
|
||||
|
||||
// declare basic init funcs
|
||||
void init_wrapper(struct pci_dev *probe_dev);
|
||||
int uhci_hcd_init(void);
|
||||
void uhci_hcd_cleanup(void);
|
||||
int STDCALL usb_init(void);
|
||||
void STDCALL usb_exit(void);
|
||||
extern struct pci_driver uhci_pci_driver;
|
||||
extern const struct pci_device_id uhci_pci_ids[];
|
||||
|
||||
|
||||
|
||||
// This should be removed, but for testing purposes it's here
|
||||
struct pci_dev *dev;
|
||||
//struct pci_device_id *dev_id;
|
||||
|
||||
|
||||
#define USB_UHCI_TAG TAG('u','s','b','u')
|
||||
|
||||
NTSTATUS STDCALL AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
|
||||
{
|
||||
PDEVICE_OBJECT fdo;
|
||||
NTSTATUS Status;
|
||||
WCHAR DeviceBuffer[20];
|
||||
UNICODE_STRING DeviceName;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
ULONG Size, DeviceNumber;
|
||||
|
||||
DPRINT1("uhci: AddDevice called\n");
|
||||
|
||||
// Allocate driver extension now
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
if (DriverExtension == NULL)
|
||||
{
|
||||
Status = IoAllocateDriverObjectExtension(
|
||||
DriverObject,
|
||||
DriverObject,
|
||||
sizeof(OHCI_DRIVER_EXTENSION),
|
||||
(PVOID *)&DriverExtension);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Allocating DriverObjectExtension failed.\n");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a unicode device name
|
||||
DeviceNumber = 0; //TODO: Allocate new device number every time
|
||||
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
|
||||
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
|
||||
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(OHCI_DEVICE_EXTENSION)/* + DriverExtension->InitializationData.HwDeviceExtensionSize*/,
|
||||
&DeviceName,
|
||||
FILE_DEVICE_CONTROLLER,
|
||||
0,
|
||||
FALSE,
|
||||
&fdo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// zerofill device extension
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)pdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
|
||||
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
|
||||
|
||||
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
// Initialize device extension
|
||||
DeviceExtension->DeviceNumber = DeviceNumber;
|
||||
DeviceExtension->PhysicalDeviceObject = pdo;
|
||||
DeviceExtension->FunctionalDeviceObject = fdo;
|
||||
DeviceExtension->DriverExtension = DriverExtension;
|
||||
|
||||
/* Get bus number from the upper level bus driver. */
|
||||
Size = sizeof(ULONG);
|
||||
Status = IoGetDeviceProperty(
|
||||
pdo,
|
||||
DevicePropertyBusNumber,
|
||||
Size,
|
||||
&DeviceExtension->SystemIoBusNumber,
|
||||
&Size);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Couldn't get an information from bus driver. Panic!!!\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Done AddDevice\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID STDCALL DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
DPRINT1("DriverUnload()\n");
|
||||
|
||||
// Exit usb device
|
||||
usb_exit();
|
||||
|
||||
// Remove device (ohci_pci_driver.remove)
|
||||
uhci_pci_driver.remove(dev);
|
||||
|
||||
ExFreePool(dev->slot_name);
|
||||
ExFreePool(dev);
|
||||
|
||||
// Perform some cleanup
|
||||
uhci_hcd_cleanup();
|
||||
}
|
||||
|
||||
NTSTATUS InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// Fill generic linux structs
|
||||
dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_UHCI_TAG);
|
||||
|
||||
init_wrapper(dev);
|
||||
dev->irq = DeviceExtension->InterruptLevel;
|
||||
dev->dev_ext = (PVOID)DeviceExtension;
|
||||
dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_UHCI_TAG); // 128 max len for slot name
|
||||
|
||||
strcpy(dev->dev.name, "UnivHCI PCI-USB Controller");
|
||||
strcpy(dev->slot_name, "UHCD PCI Slot");
|
||||
|
||||
// Init the OHCI HCD. Probe will be called automatically, but will fail because id=NULL
|
||||
Status = uhci_hcd_init();
|
||||
//FIXME: Check status returned value
|
||||
|
||||
// Init core usb
|
||||
usb_init();
|
||||
|
||||
// Probe device with real id now
|
||||
uhci_pci_driver.probe(dev, uhci_pci_ids);
|
||||
|
||||
DPRINT("InitLinuxWrapper() done\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
|
||||
/*
|
||||
* Get the initialization data we saved in VideoPortInitialize.
|
||||
*/
|
||||
DriverObject = DeviceObject->DriverObject;
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/*
|
||||
* Store some resources in the DeviceExtension.
|
||||
*/
|
||||
AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
|
||||
if (AllocatedResources != NULL)
|
||||
{
|
||||
CM_FULL_RESOURCE_DESCRIPTOR *FullList;
|
||||
CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
|
||||
ULONG ResourceCount;
|
||||
ULONG ResourceListSize;
|
||||
|
||||
/* Save the resource list */
|
||||
ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
|
||||
ResourceListSize =
|
||||
FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
|
||||
PartialDescriptors[ResourceCount]);
|
||||
DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
|
||||
if (DeviceExtension->AllocatedResources == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(DeviceExtension->AllocatedResources,
|
||||
AllocatedResources,
|
||||
ResourceListSize);
|
||||
|
||||
/* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
|
||||
for (FullList = AllocatedResources->List;
|
||||
FullList < AllocatedResources->List + AllocatedResources->Count;
|
||||
FullList++)
|
||||
{
|
||||
/* FIXME: Is this ASSERT ok for resources from the PNP manager? */
|
||||
/*ASSERT(FullList->InterfaceType == PCIBus &&
|
||||
FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
|
||||
1 == FullList->PartialResourceList.Version &&
|
||||
1 == FullList->PartialResourceList.Revision);*/
|
||||
for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
|
||||
Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
|
||||
Descriptor++)
|
||||
{
|
||||
if (Descriptor->Type == CmResourceTypeInterrupt)
|
||||
{
|
||||
DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
|
||||
DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
|
||||
}
|
||||
else if (Descriptor->Type == CmResourceTypeMemory)
|
||||
{
|
||||
DeviceExtension->BaseAddress = Descriptor->u.Memory.Start;
|
||||
DeviceExtension->BaseAddrLength = Descriptor->u.Memory.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINT1("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
|
||||
DeviceExtension->InterruptLevel,
|
||||
DeviceExtension->InterruptVector);
|
||||
|
||||
/*
|
||||
* Init wrapper with this object
|
||||
*/
|
||||
return InitLinuxWrapper(DeviceObject);
|
||||
}
|
||||
|
||||
// Dispatch PNP
|
||||
NTSTATUS STDCALL DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
NTSTATUS Status;
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (IrpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
|
||||
Status = OHCD_PnPStartDevice(DeviceObject, Irp);
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
IoDeleteDevice(DeviceObject); // just delete device for now
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||
{
|
||||
DbgPrint("IRP_MJ_POWER dispatch\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
/*
|
||||
ReactOS specific functions for UHCI module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
|
||||
// config and include core/hcd.h, for hc_device struct
|
||||
#include "../usb_wrapper.h"
|
||||
#include "../core/hcd.h"
|
||||
|
||||
#include "../host/ohci_main.h"
|
||||
|
||||
|
||||
// declare basic init funcs
|
||||
void init_wrapper(struct pci_dev *probe_dev);
|
||||
int uhci_hcd_init(void);
|
||||
void uhci_hcd_cleanup(void);
|
||||
int STDCALL usb_init(void);
|
||||
void STDCALL usb_exit(void);
|
||||
extern struct pci_driver uhci_pci_driver;
|
||||
extern struct pci_device_id uhci_pci_ids[];
|
||||
|
||||
|
||||
// This should be removed, but for testing purposes it's here
|
||||
struct pci_dev *dev;
|
||||
//struct pci_device_id *dev_id;
|
||||
|
||||
#define USB_UHCI_TAG TAG('u','s','b','u')
|
||||
|
||||
NTSTATUS STDCALL AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
|
||||
{
|
||||
PDEVICE_OBJECT fdo;
|
||||
NTSTATUS Status;
|
||||
WCHAR DeviceBuffer[20];
|
||||
UNICODE_STRING DeviceName;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
ULONG Size, DeviceNumber;
|
||||
|
||||
DPRINT1("uhci: AddDevice called\n");
|
||||
|
||||
// Allocate driver extension now
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
if (DriverExtension == NULL)
|
||||
{
|
||||
Status = IoAllocateDriverObjectExtension(
|
||||
DriverObject,
|
||||
DriverObject,
|
||||
sizeof(OHCI_DRIVER_EXTENSION),
|
||||
(PVOID *)&DriverExtension);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Allocating DriverObjectExtension failed.\n");
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a unicode device name
|
||||
DeviceNumber = 0; //TODO: Allocate new device number every time
|
||||
swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
|
||||
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
|
||||
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
sizeof(OHCI_DEVICE_EXTENSION)/* + DriverExtension->InitializationData.HwDeviceExtensionSize*/,
|
||||
&DeviceName,
|
||||
FILE_DEVICE_CONTROLLER,
|
||||
0,
|
||||
FALSE,
|
||||
&fdo);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// zerofill device extension
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)pdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
|
||||
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
|
||||
|
||||
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
// Initialize device extension
|
||||
DeviceExtension->DeviceNumber = DeviceNumber;
|
||||
DeviceExtension->PhysicalDeviceObject = pdo;
|
||||
DeviceExtension->FunctionalDeviceObject = fdo;
|
||||
DeviceExtension->DriverExtension = DriverExtension;
|
||||
|
||||
/* Get bus number from the upper level bus driver. */
|
||||
Size = sizeof(ULONG);
|
||||
Status = IoGetDeviceProperty(
|
||||
pdo,
|
||||
DevicePropertyBusNumber,
|
||||
Size,
|
||||
&DeviceExtension->SystemIoBusNumber,
|
||||
&Size);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Couldn't get an information from bus driver. Panic!!!\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("Done AddDevice\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID STDCALL DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
DPRINT1("DriverUnload()\n");
|
||||
|
||||
// Exit usb device
|
||||
usb_exit();
|
||||
|
||||
// Remove device (ohci_pci_driver.remove)
|
||||
uhci_pci_driver.remove(dev);
|
||||
|
||||
ExFreePool(dev->slot_name);
|
||||
ExFreePool(dev);
|
||||
|
||||
// Perform some cleanup
|
||||
uhci_hcd_cleanup();
|
||||
}
|
||||
|
||||
NTSTATUS InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
// Fill generic linux structs
|
||||
dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_UHCI_TAG);
|
||||
|
||||
init_wrapper(dev);
|
||||
dev->irq = DeviceExtension->InterruptVector;
|
||||
dev->dev_ext = (PVOID)DeviceExtension;
|
||||
dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_UHCI_TAG); // 128 max len for slot name
|
||||
|
||||
strcpy(dev->dev.name, "UnivHCI PCI-USB Controller");
|
||||
strcpy(dev->slot_name, "UHCD PCI Slot");
|
||||
|
||||
// Init the OHCI HCD. Probe will be called automatically, but will fail because id=NULL
|
||||
Status = uhci_hcd_init();
|
||||
//FIXME: Check status returned value
|
||||
|
||||
// Init core usb
|
||||
usb_init();
|
||||
|
||||
// Probe device with real id now
|
||||
uhci_pci_driver.probe(dev, uhci_pci_ids);
|
||||
|
||||
DPRINT("InitLinuxWrapper() done\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
POHCI_DRIVER_EXTENSION DriverExtension;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
|
||||
/*
|
||||
* Get the initialization data we saved in VideoPortInitialize.
|
||||
*/
|
||||
DriverObject = DeviceObject->DriverObject;
|
||||
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
|
||||
DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/*
|
||||
* Store some resources in the DeviceExtension.
|
||||
*/
|
||||
AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
|
||||
if (AllocatedResources != NULL)
|
||||
{
|
||||
CM_FULL_RESOURCE_DESCRIPTOR *FullList;
|
||||
CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
|
||||
ULONG ResourceCount;
|
||||
ULONG ResourceListSize;
|
||||
|
||||
/* Save the resource list */
|
||||
ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
|
||||
ResourceListSize =
|
||||
FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
|
||||
PartialDescriptors[ResourceCount]);
|
||||
DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
|
||||
if (DeviceExtension->AllocatedResources == NULL)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlCopyMemory(DeviceExtension->AllocatedResources,
|
||||
AllocatedResources,
|
||||
ResourceListSize);
|
||||
|
||||
/* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
|
||||
for (FullList = AllocatedResources->List;
|
||||
FullList < AllocatedResources->List + AllocatedResources->Count;
|
||||
FullList++)
|
||||
{
|
||||
/* FIXME: Is this ASSERT ok for resources from the PNP manager? */
|
||||
/*ASSERT(FullList->InterfaceType == PCIBus &&
|
||||
FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
|
||||
1 == FullList->PartialResourceList.Version &&
|
||||
1 == FullList->PartialResourceList.Revision);*/
|
||||
DPRINT1("AllocRess->Count: %d, PartResList.Count: %d\n",
|
||||
AllocatedResources->Count, FullList->PartialResourceList.Count);
|
||||
|
||||
for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
|
||||
Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
|
||||
Descriptor++)
|
||||
{
|
||||
if (Descriptor->Type == CmResourceTypeInterrupt)
|
||||
{
|
||||
DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
|
||||
DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
|
||||
|
||||
DPRINT1("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
|
||||
DeviceExtension->InterruptLevel,
|
||||
DeviceExtension->InterruptVector);
|
||||
}
|
||||
else if (Descriptor->Type == CmResourceTypePort)
|
||||
{
|
||||
DeviceExtension->BaseAddress = Descriptor->u.Port.Start;
|
||||
DeviceExtension->BaseAddrLength = Descriptor->u.Port.Length;
|
||||
DeviceExtension->Flags = Descriptor->Flags;
|
||||
|
||||
((struct hc_driver *)uhci_pci_ids->driver_data)->flags &= ~HCD_MEMORY;
|
||||
|
||||
DPRINT1("I/O resource: start=0x%x, length=0x%x\n",
|
||||
DeviceExtension->BaseAddress.u.LowPart, DeviceExtension->BaseAddrLength);
|
||||
}
|
||||
else if (Descriptor->Type == CmResourceTypeMemory)
|
||||
{
|
||||
DeviceExtension->BaseAddress = Descriptor->u.Memory.Start;
|
||||
DeviceExtension->BaseAddrLength = Descriptor->u.Memory.Length;
|
||||
DeviceExtension->Flags = Descriptor->Flags;
|
||||
|
||||
((struct hc_driver *)uhci_pci_ids->driver_data)->flags |= HCD_MEMORY;
|
||||
|
||||
DPRINT1("Memory resource: start=0x%x, length=0x%x\n",
|
||||
DeviceExtension->BaseAddress.u.LowPart, DeviceExtension->BaseAddrLength);
|
||||
}
|
||||
else
|
||||
DPRINT1("Get resource type: %d, Generic start=0x%x Generic length=0x%x\n",
|
||||
Descriptor->Type, Descriptor->u.Generic.Start.u.LowPart, Descriptor->u.Generic.Length);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Init wrapper with this object
|
||||
*/
|
||||
return InitLinuxWrapper(DeviceObject);
|
||||
}
|
||||
|
||||
// Dispatch PNP
|
||||
NTSTATUS STDCALL DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
NTSTATUS Status;
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
switch (IrpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
|
||||
Status = OHCD_PnPStartDevice(DeviceObject, Irp);
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
|
||||
case IRP_MN_STOP_DEVICE:
|
||||
//Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
|
||||
//if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
IoDeleteDevice(DeviceObject); // just delete device for now
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_STOP_DEVICE:
|
||||
case IRP_MN_CANCEL_STOP_DEVICE:
|
||||
Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
|
||||
{
|
||||
DbgPrint("IRP_MJ_POWER dispatch\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
|
||||
{
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->DriverExtension->AddDevice = AddDevice;
|
||||
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
|
||||
DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
//#include <stdlib.h>
|
||||
//#include <ntos/types.h>
|
||||
//#include <ddk/extypes.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
|
||||
void wait_ms(int mils);
|
||||
|
||||
#include "linux/linux_wrapper.h"
|
||||
#define __KERNEL__
|
||||
#undef CONFIG_PCI
|
||||
#define CONFIG_PCI
|
||||
|
||||
#include "linux/usb.h"
|
||||
#include "linux/pci_ids.h"
|
||||
//#include <stdlib.h>
|
||||
//#include <ntos/types.h>
|
||||
//#include <ddk/extypes.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
|
||||
void wait_ms(int mils);
|
||||
|
||||
#include "linux/linux_wrapper.h"
|
||||
#define __KERNEL__
|
||||
#undef CONFIG_PCI
|
||||
#define CONFIG_PCI
|
||||
|
||||
#include "linux/usb.h"
|
||||
#include "linux/pci_ids.h"
|
||||
|
||||
|
|
|
@ -158,7 +158,6 @@ IntInitScreenInfo(
|
|||
ModeInfoPtr = ModeInfo;
|
||||
while (ModeCount-- > 0)
|
||||
{
|
||||
|
||||
if (ModeInfoPtr->Length > 0 &&
|
||||
pDevMode->dmPelsWidth == ModeInfoPtr->VisScreenWidth &&
|
||||
pDevMode->dmPelsHeight == ModeInfoPtr->VisScreenHeight &&
|
||||
|
@ -170,7 +169,8 @@ IntInitScreenInfo(
|
|||
break;
|
||||
}
|
||||
|
||||
ModeInfoPtr++;
|
||||
ModeInfoPtr = (PVIDEO_MODE_INFORMATION)
|
||||
(((PUCHAR)ModeInfoPtr) + ModeInfoSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,6 +383,7 @@ DrvGetModes(
|
|||
{
|
||||
if (ModeInfoPtr->Length == 0)
|
||||
{
|
||||
ModeInfoPtr = (PVIDEO_MODE_INFORMATION)(((ULONG_PTR)ModeInfoPtr) + ModeInfoSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -885,6 +885,14 @@ VBEQueryMode(
|
|||
VideoMode->YMillimeter = 0; /* FIXME */
|
||||
if (VBEMode->BitsPerPixel > 8)
|
||||
{
|
||||
/*
|
||||
* Always report 16bpp modes and not 15bpp mode...
|
||||
*/
|
||||
if (VBEMode->BitsPerPixel == 15 && VBEMode->NumberOfPlanes == 1)
|
||||
{
|
||||
VideoMode->BitsPerPlane = 16;
|
||||
}
|
||||
|
||||
if (DeviceExtension->VbeInfo.Version < 0x300)
|
||||
{
|
||||
VideoMode->NumberRedBits = VBEMode->RedMaskSize;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <ddk/ntapi.h>
|
||||
|
||||
#ifdef DBG
|
||||
#define DPRINT(arg) DbgPrint arg;
|
||||
#define DPRINT(arg) DbgPrint(arg)
|
||||
#else
|
||||
#define DPRINT(arg)
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <apic.h>
|
||||
#include <ioapic.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
@ -58,7 +58,7 @@ HaliMPIntSrcInfo(PMP_CONFIGURATION_INTSRC m)
|
|||
IRQCount++;
|
||||
}
|
||||
|
||||
static PCHAR
|
||||
PCHAR
|
||||
HaliMPFamily(ULONG Family,
|
||||
ULONG Model)
|
||||
{
|
||||
|
@ -275,9 +275,9 @@ HaliReadMPConfigTable(PMP_CONFIGURATION_TABLE Table)
|
|||
{
|
||||
PUCHAR pc = (PUCHAR)&Table->Signature;
|
||||
|
||||
DPRINT1("Bad MP configuration block signature: %c%c%c%c\n",
|
||||
DPRINT1("Bad MP configuration block signature: %c%c%c%c\n",
|
||||
pc[0], pc[1], pc[2], pc[3]);
|
||||
KEBUGCHECK(0);
|
||||
KEBUGCHECKEX(0, pc[0], pc[1], pc[2], pc[3]);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,43 @@ typedef NTSTATUS STDCALL_FUNC
|
|||
PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
PULONG BufferLength);
|
||||
|
||||
typedef struct _OBJECT_HANDLE_COUNT_ENTRY
|
||||
{
|
||||
struct _EPROCESS *Process;
|
||||
ULONG HandleCount;
|
||||
} OBJECT_HANDLE_COUNT_ENTRY, *POBJECT_HANDLE_COUNT_ENTRY;
|
||||
|
||||
typedef struct _OBJECT_HANDLE_COUNT_DATABASE
|
||||
{
|
||||
ULONG CountEntries;
|
||||
POBJECT_HANDLE_COUNT_ENTRY HandleCountEntries[1];
|
||||
} OBJECT_HANDLE_COUNT_DATABASE, *POBJECT_HANDLE_COUNT_DATABASE;
|
||||
|
||||
typedef struct _OBJECT_HEADER_HANDLE_INFO
|
||||
{
|
||||
union {
|
||||
POBJECT_HANDLE_COUNT_DATABASE HandleCountDatabase;
|
||||
OBJECT_HANDLE_COUNT_ENTRY SingleEntry;
|
||||
};
|
||||
} OBJECT_HEADER_HANDLE_INFO, *POBJECT_HEADER_HANDLE_INFO;
|
||||
|
||||
typedef struct _OBJECT_HEADER_CREATOR_INFO
|
||||
{
|
||||
LIST_ENTRY TypeList;
|
||||
PVOID CreatorUniqueProcess;
|
||||
USHORT CreatorBackTraceIndex;
|
||||
USHORT Reserved;
|
||||
} OBJECT_HEADER_CREATOR_INFO, *POBJECT_HEADER_CREATOR_INFO;
|
||||
|
||||
typedef struct _OBJECT_HEADER_NAME_INFO
|
||||
{
|
||||
struct _DIRECTORY_OBJECT *Directory;
|
||||
UNICODE_STRING Name;
|
||||
ULONG QueryReferences;
|
||||
ULONG Reserved2;
|
||||
ULONG DbgReferenceCount;
|
||||
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;
|
||||
|
||||
typedef struct _OBJECT_CREATE_INFORMATION
|
||||
{
|
||||
ULONG Attributes;
|
||||
|
|
|
@ -48,11 +48,19 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* TODO: Make the output of file/line and the debug message atomic */
|
||||
#ifdef DBG
|
||||
#define DPRINT1 DbgPrint("(%s:%d) ",__FILE__,__LINE__), DbgPrint
|
||||
#define CHECKPOINT1 do { DbgPrint("%s:%d\n",__FILE__,__LINE__); } while(0);
|
||||
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define DPRINT1(args...)
|
||||
#define CHECKPOINT1
|
||||
#else
|
||||
#define DPRINT1
|
||||
#define CHECKPOINT1
|
||||
#endif /* __GNUC__ */
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define DPRINT(args...) do { DbgPrint("(%s:%d) ",__FILE__,__LINE__); DbgPrint(args); } while(0);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue