3 * PROJECT: ReactOS ISA PnP Bus driver
5 * PURPOSE: Driver entry
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * NOTE: Parts adapted from linux ISA PnP driver
9 * 01-05-2001 CSH Created
11 #include <ddk/ntddk.h>
20 // Make the initialization routines discardable, so that they
23 #pragma alloc_text(init, DriverEntry)
25 // Make the PASSIVE_LEVEL routines pageable, so that they don't
26 // waste nonpaged memory
28 #pragma alloc_text(page, ACPIDispatchOpenClose)
29 #pragma alloc_text(page, ACPIDispatchRead)
30 #pragma alloc_text(page, ACPIDispatchWrite)
32 #endif /* ALLOC_PRAGMA */
35 PUCHAR IsaPnPReadPort;
38 #define UCHAR2USHORT(v0, v1) \
41 #define UCHAR2ULONG(v0, v1, v2, v3) \
42 ((UCHAR2USHORT(v2, v3) << 16) | UCHAR2USHORT(v0, v1))
51 {"Unknown Small Tag"},
52 {"ISAPNP_SRIN_VERSION"},
53 {"ISAPNP_SRIN_LDEVICE_ID"},
54 {"ISAPNP_SRIN_CDEVICE_ID"},
55 {"ISAPNP_SRIN_IRQ_FORMAT"},
56 {"ISAPNP_SRIN_DMA_FORMAT"},
57 {"ISAPNP_SRIN_START_DFUNCTION"},
58 {"ISAPNP_SRIN_END_DFUNCTION"},
59 {"ISAPNP_SRIN_IO_DESCRIPTOR"},
60 {"ISAPNP_SRIN_FL_IO_DESCRIPOTOR"},
61 {"Reserved Small Tag"},
62 {"Reserved Small Tag"},
63 {"Reserved Small Tag"},
64 {"Reserved Small Tag"},
65 {"ISAPNP_SRIN_VENDOR_DEFINED"},
66 {"ISAPNP_SRIN_END_TAG"}
73 {"Unknown Large Tag"},
74 {"ISAPNP_LRIN_MEMORY_RANGE"},
75 {"ISAPNP_LRIN_ID_STRING_ANSI"},
76 {"ISAPNP_LRIN_ID_STRING_UNICODE"},
77 {"ISAPNP_LRIN_VENDOR_DEFINED"},
78 {"ISAPNP_LRIN_MEMORY_RANGE32"},
79 {"ISAPNP_LRIN_FL_MEMORY_RANGE32"}
82 PCSZ TagName(ULONG Tag, BOOLEAN Small)
84 if (Small && (Tag <= ISAPNP_SRIN_END_TAG)) {
85 return SmallTags[Tag].Name;
86 } else if (Tag <= ISAPNP_LRIN_FL_MEMORY_RANGE32){
87 return LargeTags[Tag].Name;
95 static inline VOID WriteData(UCHAR Value)
97 WRITE_PORT_UCHAR((PUCHAR)ISAPNP_WRITE_PORT, Value);
100 static inline VOID WriteAddress(UCHAR Value)
102 WRITE_PORT_UCHAR((PUCHAR)ISAPNP_ADDRESS_PORT, Value);
103 KeStallExecutionProcessor(20);
106 static inline UCHAR ReadData(VOID)
108 return READ_PORT_UCHAR(IsaPnPReadPort);
111 UCHAR ReadUchar(UCHAR Index)
117 USHORT ReadUshort(UCHAR Index)
121 Value = ReadUchar(Index);
122 Value = (Value << 8) + ReadUchar(Index + 1);
126 ULONG ReadUlong(UCHAR Index)
130 Value = ReadUchar(Index);
131 Value = (Value << 8) + ReadUchar(Index + 1);
132 Value = (Value << 8) + ReadUchar(Index + 2);
133 Value = (Value << 8) + ReadUchar(Index + 3);
137 VOID WriteUchar(UCHAR Index, UCHAR Value)
143 VOID WriteUshort(UCHAR Index, USHORT Value)
145 WriteUchar(Index, Value >> 8);
146 WriteUchar(Index + 1, Value);
149 VOID WriteUlong(UCHAR Index, ULONG Value)
151 WriteUchar(Index, Value >> 24);
152 WriteUchar(Index + 1, Value >> 16);
153 WriteUchar(Index + 2, Value >> 8);
154 WriteUchar(Index + 3, Value);
157 static inline VOID SetReadDataPort(ULONG Port)
159 IsaPnPReadPort = (PUCHAR)Port;
160 WriteUchar(0x00, Port >> 2);
161 KeStallExecutionProcessor(100);
164 static VOID SendKey(VOID)
170 /* FIXME: Is there something better? */
171 KeStallExecutionProcessor(1000);
177 for (i = 1; i < 32; i++) {
178 msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
179 code = (code >> 1) | msb;
184 /* Place all PnP cards in wait-for-key state */
185 static VOID SendWait(VOID)
187 WriteUchar(0x02, 0x02);
190 VOID SendWake(UCHAR csn)
192 WriteUchar(ISAPNP_CARD_WAKECSN, csn);
195 VOID SelectLogicalDevice(UCHAR LogicalDevice)
197 WriteUchar(ISAPNP_CARD_LOG_DEVICE_NUM, LogicalDevice);
200 VOID ActivateLogicalDevice(UCHAR LogicalDevice)
202 SelectLogicalDevice(LogicalDevice);
203 WriteUchar(ISAPNP_CONTROL_ACTIVATE, 0x1);
204 KeStallExecutionProcessor(250);
207 VOID DeactivateLogicalDevice(UCHAR LogicalDevice)
209 SelectLogicalDevice(LogicalDevice);
210 WriteUchar(ISAPNP_CONTROL_ACTIVATE, 0x0);
211 KeStallExecutionProcessor(500);
214 #define READ_DATA_PORT_STEP 32 /* Minimum is 4 */
216 static ULONG FindNextReadPort(VOID)
220 Port = (ULONG)IsaPnPReadPort;
\r
222 Port += READ_DATA_PORT_STEP;
\r
224 if (Port > ISAPNP_MAX_READ_PORT)
\r
230 * We cannot use NE2000 probe spaces for
\r
231 * ISAPnP or we will lock up machines
\r
233 if ((Port < 0x280) || (Port > 0x380))
\r
240 static BOOLEAN IsolateReadDataPortSelect(VOID)
247 /* Control: reset CSN and conditionally everything else too */
248 WriteUchar(0x02, 0x05);
249 KeStallExecutionProcessor(2000);
255 Port = FindNextReadPort();
261 SetReadDataPort(Port);
262 KeStallExecutionProcessor(1000);
264 KeStallExecutionProcessor(1000);
269 * Isolate (assign uniqued CSN) to all ISA PnP devices
271 static ULONG IsolatePnPCards(VOID)
273 UCHAR checksum = 0x6a;
283 IsaPnPReadPort = (PUCHAR)ISAPNP_MIN_READ_PORT;
284 if (!IsolateReadDataPortSelect()) {
285 DPRINT("Could not set read data port\n");
290 for (i = 1; i <= 64; i++) {
291 data = ReadData() << 8;
292 KeStallExecutionProcessor(250);
293 data = data | ReadData();
294 KeStallExecutionProcessor(250);
297 checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
300 for (i = 65; i <= 72; i++) {
301 data = ReadData() << 8;
302 KeStallExecutionProcessor(250);
303 data = data | ReadData();
304 KeStallExecutionProcessor(250);
306 chksum |= (1 << (i - 65));
308 if ((checksum != 0x00) && (checksum == chksum)) {
311 WriteUchar(0x06, csn);
312 KeStallExecutionProcessor(250);
315 SetReadDataPort((ULONG)IsaPnPReadPort);
316 KeStallExecutionProcessor(1000);
318 KeStallExecutionProcessor(1000);
321 if (iteration == 1) {
322 IsaPnPReadPort += READ_DATA_PORT_STEP;
323 if (!IsolateReadDataPortSelect()) {
324 DPRINT("Could not set read data port\n");
327 } else if (iteration > 1) {
340 VOID Peek(PUCHAR Data, ULONG Count)
345 for (i = 1; i <= Count; i++) {
346 for (j = 0; j < 20; j++) {
350 KeStallExecutionProcessor(100);
357 d = ReadUchar(0x04); /* PRESDI */
365 * Skip specified number of bytes from stream
367 static VOID Skip(ULONG Count)
374 * Read one tag from stream
376 static BOOLEAN ReadTag(PUCHAR Type,
385 DPRINT("Invalid tag with value 0\n");
392 if (tag & ISAPNP_RESOURCE_ITEM_TYPE) {
393 /* Large resource item */
394 *Type = (tag & 0x7f);
396 *Size = UCHAR2USHORT(tmp[0], tmp[1]);
399 if (*Type > ISAPNP_LRIN_FL_MEMORY_RANGE32) {
400 DPRINT("Invalid large tag with value 0x%X\n", *Type);
405 /* Small resource item */
406 *Type = (tag >> 3) & 0x0f;
410 if (*Type > ISAPNP_SRIN_END_TAG) {
411 DPRINT("Invalid small tag with value 0x%X\n", *Type);
417 DPRINT("Tag = 0x%X, Type = 0x%X, Size = %d (%s)\n",
418 tag, *Type, *Size, TagName(*Type, *Small));
420 /* Probably invalid data */
421 if ((*Type == 0xff) && (*Size == 0xffff)) {
422 DPRINT("Invalid data (Type 0x%X Size 0x%X)\n", *Type, *Size);
432 * Parse ANSI name for ISA PnP logical device
434 static NTSTATUS ParseAnsiName(PUNICODE_STRING Name, PUSHORT Size)
436 ANSI_STRING AnsiString;
440 size1 = (*Size >= sizeof(Buffer)) ? (sizeof(Buffer) - 1) : *Size;
443 Buffer[size1] = '\0';
446 /* Clean whitespace from end of string */
447 while ((size1 > 0) && (Buffer[--size1] == ' '))
448 Buffer[size1] = '\0';
450 DPRINT("ANSI name: %s\n", Buffer);
452 RtlInitAnsiString(&AnsiString, (PCSZ)&Buffer);
453 return RtlAnsiStringToUnicodeString(Name, &AnsiString, TRUE);
458 * Add a resource list to the
459 * resource lists of a logical device
461 static NTSTATUS AddResourceList(
462 PISAPNP_LOGICAL_DEVICE LogicalDevice,
464 PISAPNP_CONFIGURATION_LIST *NewList)
466 PISAPNP_CONFIGURATION_LIST List;
469 DPRINT("Adding resource list for logical device %d on card %d (Priority %d)\n",
470 LogicalDevice->Number,
471 LogicalDevice->Card->CardId,
474 List = (PISAPNP_CONFIGURATION_LIST)
475 ExAllocatePool(PagedPool, sizeof(ISAPNP_CONFIGURATION_LIST));
477 return STATUS_INSUFFICIENT_RESOURCES;
479 RtlZeroMemory(List, sizeof(ISAPNP_CONFIGURATION_LIST));
481 List->Priority = Priority;
483 InitializeListHead(&List->ListHead);
485 InsertTailList(&LogicalDevice->Configuration, &List->ListEntry);
489 return STATUS_SUCCESS;
494 * Add a resource entry to the
495 * resource list of a logical device
497 static NTSTATUS AddResourceDescriptor(
498 PISAPNP_LOGICAL_DEVICE LogicalDevice,
501 PISAPNP_DESCRIPTOR *Descriptor)
503 PLIST_ENTRY CurrentEntry;
504 PISAPNP_CONFIGURATION_LIST List;
505 PISAPNP_DESCRIPTOR d;
508 DPRINT("Adding resource descriptor for logical device %d on card %d (%d of %d)\n",
509 LogicalDevice->Number,
510 LogicalDevice->Card->CardId,
511 LogicalDevice->CurrentDescriptorCount,
512 LogicalDevice->DescriptorCount);
514 d = (PISAPNP_DESCRIPTOR)
515 ExAllocatePool(PagedPool, sizeof(ISAPNP_DESCRIPTOR));
517 return STATUS_NO_MEMORY;
519 RtlZeroMemory(d, sizeof(ISAPNP_DESCRIPTOR));
521 d->Descriptor.Option = Option;
525 CurrentEntry = LogicalDevice->Configuration.Flink;
526 while (CurrentEntry != &LogicalDevice->Configuration) {
527 List = CONTAINING_RECORD(
528 CurrentEntry, ISAPNP_CONFIGURATION_LIST, ListEntry);
530 if (List->Priority == Priority) {
532 LogicalDevice->ConfigurationSize += sizeof(IO_RESOURCE_DESCRIPTOR);
533 InsertTailList(&List->ListHead, &d->ListEntry);
534 LogicalDevice->CurrentDescriptorCount++;
535 if (LogicalDevice->DescriptorCount <
536 LogicalDevice->CurrentDescriptorCount) {
537 LogicalDevice->DescriptorCount =
538 LogicalDevice->CurrentDescriptorCount;
541 return STATUS_SUCCESS;
543 CurrentEntry = CurrentEntry->Flink;
546 Status = AddResourceList(LogicalDevice, Priority, &List);
547 if (NT_SUCCESS(Status)) {
548 LogicalDevice->ConfigurationSize += sizeof(IO_RESOURCE_LIST);
549 LogicalDevice->CurrentDescriptorCount = 0;
550 InsertTailList(&List->ListHead, &d->ListEntry);
558 * Add IRQ resource to resources list
560 static NTSTATUS AddIrqResource(
561 PISAPNP_LOGICAL_DEVICE LogicalDevice,
566 PISAPNP_DESCRIPTOR Descriptor;
574 irq = UCHAR2USHORT(tmp[0], tmp[0]);
576 DPRINT("IRQ bitmask: 0x%X\n", irq);
579 for (i = 0; i < 16; i++) {
580 if (!found && (irq & (1 << i))) {
585 if ((found && !(irq & (1 << i))) || (irq & (1 << i) && (i == 15))) {
586 Status = AddResourceDescriptor(LogicalDevice,
587 Priority, Option, &Descriptor);
588 if (!NT_SUCCESS(Status))
590 Descriptor->Descriptor.Type = CmResourceTypeInterrupt;
591 Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
592 Descriptor->Descriptor.u.Interrupt.MinimumVector = last;
594 if ((irq & (1 << i)) && (i == 15))
595 Descriptor->Descriptor.u.Interrupt.MaximumVector = i;
597 Descriptor->Descriptor.u.Interrupt.MaximumVector = i - 1;
599 DPRINT("Found IRQ range %d - %d for logical device %d on card %d\n",
600 Descriptor->Descriptor.u.Interrupt.MinimumVector,
601 Descriptor->Descriptor.u.Interrupt.MaximumVector,
602 LogicalDevice->Number,
603 LogicalDevice->Card->CardId);
609 return STATUS_SUCCESS;
613 * Add DMA resource to resources list
615 static NTSTATUS AddDmaResource(
616 PISAPNP_LOGICAL_DEVICE LogicalDevice,
621 PISAPNP_DESCRIPTOR Descriptor;
623 ULONG dma, flags, i, last;
632 DPRINT("DMA bitmask: 0x%X\n", dma);
635 for (i = 0; i < 8; i++) {
636 if (!found && (dma & (1 << i))) {
641 if ((found && !(dma & (1 << i))) || (dma & (1 << i) && (i == 15))) {
642 Status = AddResourceDescriptor(LogicalDevice,
643 Priority, Option, &Descriptor);
644 if (!NT_SUCCESS(Status))
646 Descriptor->Descriptor.Type = CmResourceTypeDma;
647 Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
648 Descriptor->Descriptor.u.Dma.MinimumChannel = last;
650 if ((dma & (1 << i)) && (i == 15))
651 Descriptor->Descriptor.u.Dma.MaximumChannel = i;
653 Descriptor->Descriptor.u.Dma.MaximumChannel = i - 1;
655 /* FIXME: Parse flags */
657 DPRINT("Found DMA range %d - %d for logical device %d on card %d\n",
658 Descriptor->Descriptor.u.Dma.MinimumChannel,
659 Descriptor->Descriptor.u.Dma.MaximumChannel,
660 LogicalDevice->Number,
661 LogicalDevice->Card->CardId);
667 return STATUS_SUCCESS;
671 * Add port resource to resources list
673 static NTSTATUS AddIOPortResource(
674 PISAPNP_LOGICAL_DEVICE LogicalDevice,
680 DPRINT("I/O port: size 0x%X\n", Size);
683 PISAPNP_DESCRIPTOR Descriptor;
689 Status = AddResourceDescriptor(LogicalDevice,
690 Priority, Option, &Descriptor);
691 if (!NT_SUCCESS(Status))
693 Descriptor->Descriptor.Type = CmResourceTypePort;
694 Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
695 Descriptor->Descriptor.u.Port.Length = tmp[6];
696 /* FIXME: Parse flags */
697 Descriptor->Descriptor.u.Port.Alignment = 0;
698 Descriptor->Descriptor.u.Port.MinimumAddress.QuadPart = UCHAR2USHORT(tmp[1], tmp[2]);
699 Descriptor->Descriptor.u.Port.MaximumAddress.QuadPart = UCHAR2USHORT(tmp[4], tmp[4]);
701 DPRINT("Found I/O port range 0x%X - 0x%X for logical device %d on card %d\n",
702 Descriptor->Descriptor.u.Port.MinimumAddress,
703 Descriptor->Descriptor.u.Port.MaximumAddress,
704 LogicalDevice->Number,
705 LogicalDevice->Card->CardId);
707 return STATUS_SUCCESS;
711 * Add fixed port resource to resources list
713 static NTSTATUS AddFixedIOPortResource(
714 PISAPNP_LOGICAL_DEVICE LogicalDevice,
720 DPRINT("Fixed I/O port: size 0x%X\n", Size);
723 PISAPNP_DESCRIPTOR Descriptor;
729 Status = AddResourceDescriptor(LogicalDevice,
730 Priority, Option, &Descriptor);
731 if (!NT_SUCCESS(Status))
733 Descriptor->Descriptor.Type = CmResourceTypePort;
734 Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
735 Descriptor->Descriptor.u.Port.Length = tmp[2];
736 Descriptor->Descriptor.u.Port.Alignment = 0;
737 Descriptor->Descriptor.u.Port.MinimumAddress.QuadPart = UCHAR2USHORT(tmp[0], tmp[1]);
738 Descriptor->Descriptor.u.Port.MaximumAddress.QuadPart = UCHAR2USHORT(tmp[0], tmp[1]);
740 DPRINT("Found fixed I/O port range 0x%X - 0x%X for logical device %d on card %d\n",
741 Descriptor->Descriptor.u.Port.MinimumAddress,
742 Descriptor->Descriptor.u.Port.MaximumAddress,
743 LogicalDevice->Number,
744 LogicalDevice->Card->CardId);
746 return STATUS_SUCCESS;
750 * Add memory resource to resources list
752 static NTSTATUS AddMemoryResource(
753 PISAPNP_LOGICAL_DEVICE LogicalDevice,
759 DPRINT("Memory range: size 0x%X\n", Size);
762 PISAPNP_DESCRIPTOR Descriptor;
768 Status = AddResourceDescriptor(LogicalDevice,
769 Priority, Option, &Descriptor);
770 if (!NT_SUCCESS(Status))
772 Descriptor->Descriptor.Type = CmResourceTypeMemory;
773 Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
774 Descriptor->Descriptor.u.Memory.Length = UCHAR2USHORT(tmp[7], tmp[8]) << 8;
775 Descriptor->Descriptor.u.Memory.Alignment = UCHAR2USHORT(tmp[5], tmp[6]);
776 Descriptor->Descriptor.u.Memory.MinimumAddress.QuadPart = UCHAR2USHORT(tmp[1], tmp[2]) << 8;
777 Descriptor->Descriptor.u.Memory.MaximumAddress.QuadPart = UCHAR2USHORT(tmp[3], tmp[4]) << 8;
779 DPRINT("Found memory range 0x%X - 0x%X for logical device %d on card %d\n",
780 Descriptor->Descriptor.u.Memory.MinimumAddress,
781 Descriptor->Descriptor.u.Memory.MaximumAddress,
782 LogicalDevice->Number,
783 LogicalDevice->Card->CardId);
785 return STATUS_SUCCESS;
789 * Add 32-bit memory resource to resources list
791 static NTSTATUS AddMemory32Resource(
792 PISAPNP_LOGICAL_DEVICE LogicalDevice,
798 DPRINT("Memory32 range: size 0x%X\n", Size);
801 PISAPNP_DESCRIPTOR Descriptor;
807 Status = AddResourceDescriptor(LogicalDevice,
808 Priority, Option, &Descriptor);
809 if (!NT_SUCCESS(Status))
811 Descriptor->Descriptor.Type = CmResourceTypeMemory;
812 Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
813 Descriptor->Descriptor.u.Memory.Length =
814 UCHAR2ULONG(tmp[13], tmp[14], tmp[15], tmp[16]);
815 Descriptor->Descriptor.u.Memory.Alignment =
816 UCHAR2ULONG(tmp[9], tmp[10], tmp[11], tmp[12]);
817 Descriptor->Descriptor.u.Memory.MinimumAddress.QuadPart =
818 UCHAR2ULONG(tmp[1], tmp[2], tmp[3], tmp[4]);
819 Descriptor->Descriptor.u.Memory.MaximumAddress.QuadPart =
820 UCHAR2ULONG(tmp[5], tmp[6], tmp[7], tmp[8]);
822 DPRINT("Found memory32 range 0x%X - 0x%X for logical device %d on card %d\n",
823 Descriptor->Descriptor.u.Memory.MinimumAddress,
824 Descriptor->Descriptor.u.Memory.MaximumAddress,
825 LogicalDevice->Number,
826 LogicalDevice->Card->CardId);
828 return STATUS_SUCCESS;
832 * Add 32-bit fixed memory resource to resources list
834 static NTSTATUS AddFixedMemory32Resource(
835 PISAPNP_LOGICAL_DEVICE LogicalDevice,
841 DPRINT("Memory32 range: size 0x%X\n", Size);
844 PISAPNP_DESCRIPTOR Descriptor;
850 Status = AddResourceDescriptor(LogicalDevice,
851 Priority, Option, &Descriptor);
852 if (!NT_SUCCESS(Status))
854 Descriptor->Descriptor.Type = CmResourceTypeMemory;
855 Descriptor->Descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
856 Descriptor->Descriptor.u.Memory.Length =
857 UCHAR2ULONG(tmp[9], tmp[10], tmp[11], tmp[12]);
858 Descriptor->Descriptor.u.Memory.Alignment =
859 UCHAR2ULONG(tmp[5], tmp[6], tmp[7], tmp[8]);
860 Descriptor->Descriptor.u.Memory.MinimumAddress.QuadPart =
861 UCHAR2ULONG(tmp[1], tmp[2], tmp[3], tmp[4]);
862 Descriptor->Descriptor.u.Memory.MaximumAddress.QuadPart =
863 UCHAR2ULONG(tmp[1], tmp[2], tmp[3], tmp[4]);
865 DPRINT("Found fixed memory32 range 0x%X - 0x%X for logical device %d on card %d\n",
866 Descriptor->Descriptor.u.Memory.MinimumAddress,
867 Descriptor->Descriptor.u.Memory.MaximumAddress,
868 LogicalDevice->Number,
869 LogicalDevice->Card->CardId);
871 return STATUS_SUCCESS;
876 * Parse logical device tag
878 static PISAPNP_LOGICAL_DEVICE ParseLogicalDevice(
879 PISAPNP_DEVICE_EXTENSION DeviceExtension,
885 PISAPNP_LOGICAL_DEVICE LogicalDevice;
887 DPRINT("Card %d Number %d\n", Card->CardId, Number);
891 LogicalDevice = (PISAPNP_LOGICAL_DEVICE)ExAllocatePool(
892 PagedPool, sizeof(ISAPNP_LOGICAL_DEVICE));
896 RtlZeroMemory(LogicalDevice, sizeof(ISAPNP_LOGICAL_DEVICE));
898 LogicalDevice->Number = Number;
899 LogicalDevice->VendorId = UCHAR2USHORT(tmp[0], tmp[1]);
900 LogicalDevice->DeviceId = UCHAR2USHORT(tmp[2], tmp[3]);
901 LogicalDevice->Regs = tmp[4];
902 LogicalDevice->Card = Card;
904 LogicalDevice->Regs |= tmp[5] << 8;
906 InitializeListHead(&LogicalDevice->Configuration);
908 ExInterlockedInsertTailList(&Card->LogicalDevices,
909 &LogicalDevice->CardListEntry,
910 &Card->LogicalDevicesLock);
912 ExInterlockedInsertTailList(&DeviceExtension->DeviceListHead,
913 &LogicalDevice->DeviceListEntry,
914 &DeviceExtension->GlobalListLock);
916 DeviceExtension->DeviceListCount++;
918 return LogicalDevice;
923 * Parse resource map for logical device
925 static BOOLEAN CreateLogicalDevice(PISAPNP_DEVICE_EXTENSION DeviceExtension,
926 PISAPNP_CARD Card, USHORT Size)
928 ULONG number = 0, skip = 0, compat = 0;
930 PISAPNP_LOGICAL_DEVICE LogicalDevice;
933 ULONG Option = IO_RESOURCE_REQUIRED;
935 DPRINT("Card %d Size %d\n", Card->CardId, Size);
937 LogicalDevice = ParseLogicalDevice(DeviceExtension, Card, Size, number++);
942 if (!ReadTag(&type, &Size, &Small))
945 if (skip && !(Small && (type == ISAPNP_SRIN_LDEVICE_ID)
946 || (type == ISAPNP_SRIN_END_TAG)))
951 case ISAPNP_SRIN_LDEVICE_ID:
952 if ((Size >= 5) && (Size <= 6)) {
953 LogicalDevice = ParseLogicalDevice(
954 DeviceExtension, Card, Size, number++);
963 Option = IO_RESOURCE_REQUIRED;
967 case ISAPNP_SRIN_CDEVICE_ID:
968 if ((Size == 4) && (compat < MAX_COMPATIBLE_ID)) {
970 LogicalDevice->CVendorId[compat] = UCHAR2USHORT(tmp[0], tmp[1]);
971 LogicalDevice->CDeviceId[compat] = UCHAR2USHORT(tmp[2], tmp[3]);
977 case ISAPNP_SRIN_IRQ_FORMAT:
978 if ((Size < 2) || (Size > 3))
980 AddIrqResource(LogicalDevice, Size, Priority, Option);
984 case ISAPNP_SRIN_DMA_FORMAT:
987 AddDmaResource(LogicalDevice, Size, Priority, Option);
991 case ISAPNP_SRIN_START_DFUNCTION:
999 /* FIXME: Maybe use IO_RESOURCE_PREFERRED for some */
1000 Option = IO_RESOURCE_ALTERNATIVE;
1003 Option = IO_RESOURCE_ALTERNATIVE;
1006 DPRINT(" Start priority %d \n", Priority);
1008 LogicalDevice->CurrentDescriptorCount = 0;
1012 case ISAPNP_SRIN_END_DFUNCTION:
1014 DPRINT(" End priority %d \n", Priority);
1019 Option = IO_RESOURCE_REQUIRED;
1020 LogicalDevice->CurrentDescriptorCount = 0;
1023 case ISAPNP_SRIN_IO_DESCRIPTOR:
1026 AddIOPortResource(LogicalDevice, Size, Priority, Option);
1030 case ISAPNP_SRIN_FL_IO_DESCRIPOTOR:
1033 AddFixedIOPortResource(LogicalDevice, Size, Priority, Option);
1037 case ISAPNP_SRIN_VENDOR_DEFINED:
1040 case ISAPNP_SRIN_END_TAG:
1046 DPRINT("Ignoring small tag of type 0x%X for logical device %d on card %d\n",
1047 type, LogicalDevice->Number, Card->CardId);
1051 case ISAPNP_LRIN_MEMORY_RANGE:
1054 AddMemoryResource(LogicalDevice, Size, Priority, Option);
1058 case ISAPNP_LRIN_ID_STRING_ANSI:
1059 ParseAnsiName(&LogicalDevice->Name, &Size);
1062 case ISAPNP_LRIN_ID_STRING_UNICODE:
1065 case ISAPNP_LRIN_VENDOR_DEFINED:
1068 case ISAPNP_LRIN_MEMORY_RANGE32:
1071 AddMemory32Resource(LogicalDevice, Size, Priority, Option);
1075 case ISAPNP_LRIN_FL_MEMORY_RANGE32:
1078 AddFixedMemory32Resource(LogicalDevice, Size, Priority, Option);
1083 DPRINT("Ignoring large tag of type 0x%X for logical device %d on card %d\n",
1084 type, LogicalDevice->Number, Card->CardId);
1097 * Parse resource map for ISA PnP card
1099 static BOOLEAN ParseResourceMap(PISAPNP_DEVICE_EXTENSION DeviceExtension,
1102 UCHAR type, tmp[17];
1106 DPRINT("Card %d\n", Card->CardId);
1109 if (!ReadTag(&type, &size, &Small))
1114 case ISAPNP_SRIN_VERSION:
1118 Card->PNPVersion = tmp[0];
1119 Card->ProductVersion = tmp[1];
1123 case ISAPNP_SRIN_LDEVICE_ID:
1124 if ((size >= 5) && (size <= 6)) {
1125 if (!CreateLogicalDevice(DeviceExtension, Card, size))
1131 case ISAPNP_SRIN_CDEVICE_ID:
1132 /* FIXME: Parse compatible IDs */
1135 case ISAPNP_SRIN_END_TAG:
1141 DPRINT("Ignoring small tag Type 0x%X for Card %d\n", type, Card->CardId);
1145 case ISAPNP_LRIN_ID_STRING_ANSI:
1146 ParseAnsiName(&Card->Name, &size);
1150 DPRINT("Ignoring large tag Type 0x%X for Card %d\n",
1151 type, Card->CardId);
1164 * Compute ISA PnP checksum for first eight bytes
1166 static UCHAR Checksum(PUCHAR data)
1169 UCHAR checksum = 0x6a, bit, b;
1171 for (i = 0; i < 8; i++) {
1173 for (j = 0; j < 8; j++) {
1177 checksum = ((((checksum ^ (checksum >> 1)) &
1178 0x01) ^ bit) << 7) | (checksum >> 1);
1186 * Build a resource list for a logical ISA PnP device
1188 static NTSTATUS BuildResourceList(PISAPNP_LOGICAL_DEVICE LogicalDevice,
1189 PIO_RESOURCE_LIST DestinationList,
1192 PLIST_ENTRY CurrentEntry, Entry;
1193 PISAPNP_CONFIGURATION_LIST List;
1194 PISAPNP_DESCRIPTOR Descriptor;
1198 if (IsListEmpty(&LogicalDevice->Configuration))
1199 return STATUS_NOT_FOUND;
1201 CurrentEntry = LogicalDevice->Configuration.Flink;
1202 while (CurrentEntry != &LogicalDevice->Configuration) {
1203 List = CONTAINING_RECORD(
1204 CurrentEntry, ISAPNP_CONFIGURATION_LIST, ListEntry);
1206 if (List->Priority == Priority) {
1208 DPRINT("Logical device %d DestinationList 0x%X\n",
1209 LogicalDevice->Number,
1212 DestinationList->Version = 1;
1213 DestinationList->Revision = 1;
1214 DestinationList->Count = LogicalDevice->DescriptorCount;
1217 Entry = List->ListHead.Flink;
1218 while (Entry != &List->ListHead) {
1219 Descriptor = CONTAINING_RECORD(
1220 Entry, ISAPNP_DESCRIPTOR, ListEntry);
1222 DPRINT("Logical device %d Destination 0x%X(%d)\n",
1223 LogicalDevice->Number,
1224 &DestinationList->Descriptors[i],
1227 RtlCopyMemory(&DestinationList->Descriptors[i],
1228 &Descriptor->Descriptor,
1229 sizeof(IO_RESOURCE_DESCRIPTOR));
1233 Entry = Entry->Flink;
1236 RemoveEntryList(&List->ListEntry);
1240 return STATUS_SUCCESS;
1243 CurrentEntry = CurrentEntry->Flink;
1246 return STATUS_UNSUCCESSFUL;
1251 * Build resource lists for a logical ISA PnP device
1253 static NTSTATUS BuildResourceLists(PISAPNP_LOGICAL_DEVICE LogicalDevice)
1257 ULONG SingleListSize;
1258 PIO_RESOURCE_LIST p;
1261 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
1262 - sizeof(IO_RESOURCE_LIST)
1263 + LogicalDevice->ConfigurationSize;
1265 DPRINT("Logical device %d ListSize 0x%X ConfigurationSize 0x%X DescriptorCount %d\n",
1266 LogicalDevice->Number, ListSize,
1267 LogicalDevice->ConfigurationSize,
1268 LogicalDevice->DescriptorCount);
1270 LogicalDevice->ResourceLists =
1271 (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(
1272 PagedPool, ListSize);
1273 if (!LogicalDevice->ResourceLists)
1274 return STATUS_INSUFFICIENT_RESOURCES;
1276 RtlZeroMemory(LogicalDevice->ResourceLists, ListSize);
1278 SingleListSize = sizeof(IO_RESOURCE_LIST) +
1279 (LogicalDevice->DescriptorCount - 1) *
1280 sizeof(IO_RESOURCE_DESCRIPTOR);
1282 DPRINT("SingleListSize %d\n", SingleListSize);
1285 p = &LogicalDevice->ResourceLists->List[0];
1287 Status = BuildResourceList(LogicalDevice, p, Priority);
1288 if (NT_SUCCESS(Status)) {
1289 p = (PIO_RESOURCE_LIST)((ULONG)p + SingleListSize);
1292 } while (Status != STATUS_NOT_FOUND);
1294 LogicalDevice->ResourceLists->ListSize = ListSize;
1295 LogicalDevice->ResourceLists->AlternativeLists = Priority + 1;
1297 return STATUS_SUCCESS;
1302 * Build resource lists for a ISA PnP card
1304 static NTSTATUS BuildResourceListsForCard(PISAPNP_CARD Card)
1306 PISAPNP_LOGICAL_DEVICE LogicalDevice;
1307 PLIST_ENTRY CurrentEntry;
1310 CurrentEntry = Card->LogicalDevices.Flink;
1311 while (CurrentEntry != &Card->LogicalDevices) {
1312 LogicalDevice = CONTAINING_RECORD(
1313 CurrentEntry, ISAPNP_LOGICAL_DEVICE, CardListEntry);
1314 Status = BuildResourceLists(LogicalDevice);
1315 if (!NT_SUCCESS(Status))
1317 CurrentEntry = CurrentEntry->Flink;
1320 return STATUS_SUCCESS;
1325 * Build resource lists for all present ISA PnP cards
1327 static NTSTATUS BuildResourceListsForAll(
1328 PISAPNP_DEVICE_EXTENSION DeviceExtension)
1330 PLIST_ENTRY CurrentEntry;
1334 CurrentEntry = DeviceExtension->CardListHead.Flink;
1335 while (CurrentEntry != &DeviceExtension->CardListHead) {
1336 Card = CONTAINING_RECORD(
1337 CurrentEntry, ISAPNP_CARD, ListEntry);
1338 Status = BuildResourceListsForCard(Card);
1339 if (!NT_SUCCESS(Status))
1341 CurrentEntry = CurrentEntry->Flink;
1344 return STATUS_SUCCESS;
1349 * Build device list for all present ISA PnP cards
1351 static NTSTATUS BuildDeviceList(PISAPNP_DEVICE_EXTENSION DeviceExtension)
1354 UCHAR header[9], checksum;
1362 for (csn = 1; csn <= 10; csn++) {
1365 checksum = Checksum(header);
1367 if (checksum == 0x00 || checksum != header[8]) /* Invalid CSN */
1370 DPRINT("VENDOR: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
1371 header[0], header[1], header[2], header[3],
1372 header[4], header[5], header[6], header[7], header[8]);
1374 Card = (PISAPNP_CARD)ExAllocatePool(
1375 PagedPool, sizeof(ISAPNP_CARD));
1377 return STATUS_INSUFFICIENT_RESOURCES;
1379 RtlZeroMemory(Card, sizeof(ISAPNP_CARD));
1382 Card->VendorId = (header[1] << 8) | header[0];
1383 Card->DeviceId = (header[3] << 8) | header[2];
1384 Card->Serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
1386 InitializeListHead(&Card->LogicalDevices);
1387 KeInitializeSpinLock(&Card->LogicalDevicesLock);
1389 ParseResourceMap(DeviceExtension, Card);
1391 ExInterlockedInsertTailList(&DeviceExtension->CardListHead,
1393 &DeviceExtension->GlobalListLock);
1396 return STATUS_SUCCESS;
1401 ISAPNPQueryBusRelations(
1402 IN PDEVICE_OBJECT DeviceObject,
1404 PIO_STACK_LOCATION IrpSp)
1406 PISAPNP_DEVICE_EXTENSION DeviceExtension;
1407 PISAPNP_LOGICAL_DEVICE LogicalDevice;
1408 PDEVICE_RELATIONS Relations;
1409 PLIST_ENTRY CurrentEntry;
1416 DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1418 if (Irp->IoStatus.Information) {
1419 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
1420 structure so we must merge this structure with our own */
1423 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
1424 (DeviceExtension->DeviceListCount - 1);
1425 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
1427 return STATUS_INSUFFICIENT_RESOURCES;
1429 Relations->Count = DeviceExtension->DeviceListCount;
1432 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
1433 while (CurrentEntry != &DeviceExtension->DeviceListHead) {
1434 LogicalDevice = CONTAINING_RECORD(
1435 CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceListEntry);
1437 if (!LogicalDevice->Pdo) {
1438 /* Create a physical device object for the
1439 device as it does not already have one */
1440 Status = IoCreateDevice(DeviceObject->DriverObject, 0,
1441 NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &LogicalDevice->Pdo);
1442 if (!NT_SUCCESS(Status)) {
1443 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
1444 ExFreePool(Relations);
1448 LogicalDevice->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
1451 /* Reference the physical device object. The PnP manager
1452 will dereference it again when it is no longer needed */
1453 ObReferenceObject(LogicalDevice->Pdo);
1455 Relations->Objects[i] = LogicalDevice->Pdo;
1459 CurrentEntry = CurrentEntry->Flink;
1462 Irp->IoStatus.Information = (ULONG)Relations;
1469 ISAPNPQueryDeviceRelations(
1470 IN PDEVICE_OBJECT DeviceObject,
1472 PIO_STACK_LOCATION IrpSp)
1474 PISAPNP_DEVICE_EXTENSION DeviceExtension;
1479 DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1481 if (DeviceExtension->State == dsStopped)
1482 return STATUS_UNSUCCESSFUL;
1484 switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
1486 Status = ISAPNPQueryBusRelations(DeviceObject, Irp, IrpSp);
1490 Status = STATUS_NOT_IMPLEMENTED;
1499 IN PDEVICE_OBJECT DeviceObject,
1501 PIO_STACK_LOCATION IrpSp)
1503 PISAPNP_DEVICE_EXTENSION DeviceExtension;
1509 DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1511 if (DeviceExtension->State == dsStarted)
1512 return STATUS_SUCCESS;
1514 NumCards = IsolatePnPCards();
1516 DPRINT("Number of ISA PnP cards found: %d\n", NumCards);
1518 Status = BuildDeviceList(DeviceExtension);
1519 if (!NT_SUCCESS(Status)) {
1520 DPRINT("BuildDeviceList() failed with status 0x%X\n", Status);
1524 Status = BuildResourceListsForAll(DeviceExtension);
1525 if (!NT_SUCCESS(Status)) {
1526 DPRINT("BuildResourceListsForAll() failed with status 0x%X\n", Status);
1530 DeviceExtension->State = dsStarted;
1532 return STATUS_SUCCESS;
1538 IN PDEVICE_OBJECT DeviceObject,
1540 PIO_STACK_LOCATION IrpSp)
1542 PISAPNP_DEVICE_EXTENSION DeviceExtension;
1546 DeviceExtension = (PISAPNP_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1548 if (DeviceExtension->State != dsStopped) {
1549 /* FIXME: Stop device */
1550 DeviceExtension->State = dsStopped;
1553 return STATUS_SUCCESS;
1559 ISAPNPDispatchOpenClose(
1560 IN PDEVICE_OBJECT DeviceObject,
1565 Irp->IoStatus.Status = STATUS_SUCCESS;
1566 Irp->IoStatus.Information = FILE_OPENED;
1567 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1569 return STATUS_SUCCESS;
1575 ISAPNPDispatchReadWrite(
1576 IN PDEVICE_OBJECT PhysicalDeviceObject,
1581 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1582 Irp->IoStatus.Information = 0;
1583 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1585 return STATUS_UNSUCCESSFUL;
1591 ISAPNPDispatchDeviceControl(
1592 IN PDEVICE_OBJECT DeviceObject,
1595 PIO_STACK_LOCATION IrpSp;
1600 Irp->IoStatus.Information = 0;
1602 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1603 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
1605 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1606 Status = STATUS_NOT_IMPLEMENTED;
1610 if (Status != STATUS_PENDING) {
1611 Irp->IoStatus.Status = Status;
1612 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1615 DPRINT("Leaving. Status 0x%X\n", Status);
1624 IN PDEVICE_OBJECT DeviceObject,
1627 PIO_STACK_LOCATION IrpSp;
1632 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1633 switch (IrpSp->MinorFunction) {
1634 case IRP_MN_QUERY_DEVICE_RELATIONS:
1635 Status = ISAPNPQueryDeviceRelations(DeviceObject, Irp, IrpSp);
1638 case IRP_MN_START_DEVICE:
1639 Status = ISAPNPStartDevice(DeviceObject, Irp, IrpSp);
1642 case IRP_MN_STOP_DEVICE:
1643 Status = ISAPNPStopDevice(DeviceObject, Irp, IrpSp);
1647 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1648 Status = STATUS_NOT_IMPLEMENTED;
1652 if (Status != STATUS_PENDING) {
1653 Irp->IoStatus.Status = Status;
1654 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1657 DPRINT("Leaving. Status 0x%X\n", Status);
1666 IN PDRIVER_OBJECT DriverObject,
1667 IN PDEVICE_OBJECT PhysicalDeviceObject)
1669 PISAPNP_DEVICE_EXTENSION DeviceExtension;
1675 Status = IoCreateDevice(DriverObject, sizeof(ISAPNP_DEVICE_EXTENSION),
1676 NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
1677 if (!NT_SUCCESS(Status)) {
1678 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
1682 DeviceExtension = (PISAPNP_DEVICE_EXTENSION)Fdo->DeviceExtension;
1684 DeviceExtension->Pdo = PhysicalDeviceObject;
1686 DeviceExtension->Ldo =
1687 IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
1689 InitializeListHead(&DeviceExtension->CardListHead);
1690 InitializeListHead(&DeviceExtension->DeviceListHead);
1691 DeviceExtension->DeviceListCount = 0;
1692 KeInitializeSpinLock(&DeviceExtension->GlobalListLock);
1694 DeviceExtension->State = dsStopped;
1696 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
1698 DPRINT("Done AddDevice\n");
1700 return STATUS_SUCCESS;
1707 IN PDRIVER_OBJECT DriverObject,
1708 IN PUNICODE_STRING RegistryPath)
1710 DbgPrint("ISA Plug and Play Bus Driver\n");
1712 DriverObject->MajorFunction[IRP_MJ_CREATE] = ISAPNPDispatchOpenClose;
1713 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ISAPNPDispatchOpenClose;
1714 DriverObject->MajorFunction[IRP_MJ_READ] = ISAPNPDispatchReadWrite;
1715 DriverObject->MajorFunction[IRP_MJ_WRITE] = ISAPNPDispatchReadWrite;
1716 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ISAPNPDispatchDeviceControl;
1717 DriverObject->MajorFunction[IRP_MJ_PNP] = ISAPNPControl;
1718 DriverObject->DriverExtension->AddDevice = ISAPNPAddDevice;
1720 return STATUS_SUCCESS;