Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

894 lines
22 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. pccardc.c
  5. Abstract:
  6. This module contains the C code to set up PcCard (pcmcia, cardbus)
  7. configuration data.
  8. Author:
  9. Neil Sandlin (neilsa) 16-Dec-1998
  10. (DetectIRQMap, ToggleIRQLine were copied from win9x)
  11. Revision History:
  12. --*/
  13. #include "hwdetect.h"
  14. #include "pccard.h"
  15. #include <string.h>
  16. extern UCHAR DisablePccardIrqScan;
  17. extern BOOLEAN SystemHas8259;
  18. extern BOOLEAN SystemHas8253;
  19. CARDBUS_BRIDGE_DEVTYPE CBTable[] = {
  20. {0x11101013, DEVTYPE_CL_PD6832},
  21. {0x11121013, DEVTYPE_CL_PD6834},
  22. {0x11111013, DEVTYPE_CL_PD6833},
  23. {0xAC12104C, DEVTYPE_TI_PCI1130},
  24. {0xAC15104C, DEVTYPE_TI_PCI1131},
  25. {0xAC13104C, DEVTYPE_TI_PCI1031},
  26. {0,0}};
  27. FPFWCONFIGURATION_COMPONENT_DATA ControllerList = NULL;
  28. #define LEGACY_BASE_LIST_SIZE 10
  29. USHORT LegacyBaseList[LEGACY_BASE_LIST_SIZE] = {0};
  30. USHORT LegacyBaseListCount = 0;
  31. VOID
  32. SetPcCardConfigurationData(
  33. PPCCARD_INFORMATION PcCardInfo
  34. )
  35. /*++
  36. Routine Description:
  37. This routine creates a structure containing the result of the
  38. irq detection, and links it onto our running list. This list
  39. eventually will show up in the registry under hardware
  40. descriptions.
  41. Arguments:
  42. PcCardInfo - Structure containing the results of detection
  43. Returns:
  44. None.
  45. --*/
  46. {
  47. FPFWCONFIGURATION_COMPONENT_DATA CurrentEntry;
  48. static FPFWCONFIGURATION_COMPONENT_DATA PreviousEntry = NULL;
  49. FPFWCONFIGURATION_COMPONENT Component;
  50. FPHWRESOURCE_DESCRIPTOR_LIST DescriptorList;
  51. CHAR Identifier[32];
  52. FPCHAR IdentifierString;
  53. USHORT Length;
  54. CM_PCCARD_DEVICE_DATA far *PcCardData;
  55. CurrentEntry = (FPFWCONFIGURATION_COMPONENT_DATA)HwAllocateHeap (
  56. sizeof(FWCONFIGURATION_COMPONENT_DATA), TRUE);
  57. if (!ControllerList) {
  58. ControllerList = CurrentEntry;
  59. }
  60. Component = &CurrentEntry->ComponentEntry;
  61. Component->Class = ControllerClass;
  62. Component->Type = OtherController;
  63. strcpy (Identifier, "PcCardController");
  64. Length = strlen(Identifier) + 1;
  65. IdentifierString = (FPCHAR)HwAllocateHeap(Length, FALSE);
  66. _fstrcpy(IdentifierString, Identifier);
  67. Component->IdentifierLength = Length;
  68. Component->Identifier = IdentifierString;
  69. Length = sizeof(HWRESOURCE_DESCRIPTOR_LIST) + sizeof(CM_PCCARD_DEVICE_DATA);
  70. DescriptorList = (FPHWRESOURCE_DESCRIPTOR_LIST)HwAllocateHeap(
  71. Length,
  72. TRUE);
  73. CurrentEntry->ConfigurationData = DescriptorList;
  74. Component->ConfigurationDataLength = Length;
  75. DescriptorList->Count = 1;
  76. DescriptorList->PartialDescriptors[0].Type = RESOURCE_DEVICE_DATA;
  77. DescriptorList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
  78. sizeof(CM_PCCARD_DEVICE_DATA);
  79. PcCardData = (CM_PCCARD_DEVICE_DATA far *)(DescriptorList + 1);
  80. PcCardData->Flags = PcCardInfo->Flags;
  81. PcCardData->ErrorCode = PcCardInfo->ErrorCode;
  82. PcCardData->DeviceId = PcCardInfo->DeviceId;
  83. PcCardData->LegacyBaseAddress = (ULONG) PcCardInfo->IoBase;
  84. if (PcCardInfo->Flags & PCCARD_DEVICE_PCI) {
  85. PcCardData->BusData = PcCardInfo->PciCfg1.u.bits.BusNumber |
  86. PcCardInfo->PciCfg1.u.bits.DeviceNumber << 8 |
  87. PcCardInfo->PciCfg1.u.bits.FunctionNumber << 16;
  88. }
  89. _fmemcpy(PcCardData->IRQMap, PcCardInfo->abIRQMap, 16);
  90. if (PreviousEntry) {
  91. PreviousEntry->Sibling = CurrentEntry;
  92. }
  93. PreviousEntry = CurrentEntry;
  94. }
  95. BOOLEAN
  96. IsOnLegacyBaseList(
  97. USHORT IoBase
  98. )
  99. /*++
  100. Routine Description:
  101. This routine runs our list of legacy base addresses to see if we
  102. have looked at the address before.
  103. Arguments:
  104. IoBase = base address to map
  105. Returns:
  106. TRUE if the base address is already on the list
  107. --*/
  108. {
  109. USHORT i;
  110. for (i = 0; i<LegacyBaseListCount; i++) {
  111. if (IoBase == LegacyBaseList[i]) {
  112. return TRUE;
  113. }
  114. }
  115. return FALSE;
  116. }
  117. BOOLEAN
  118. SetLegacyBaseList(
  119. USHORT IoBase
  120. )
  121. /*++
  122. Routine Description:
  123. This routine remembers the legacy base addresses that we have looked
  124. at so far so we don't keep mapping the same address.
  125. NOTE: We are using a DUMB mechanism that only builds the list in a
  126. fixed array. We could write some generic code which creates
  127. a linked list, but since the heap routines in ntdetect are also
  128. dumb, it makes it not possible to free the list. It's just not worth
  129. it.
  130. Arguments:
  131. IoBase = base address to map
  132. Returns:
  133. TRUE if the base address is unique to this point
  134. FALSE if the base address already exists on the list
  135. --*/
  136. {
  137. if (IsOnLegacyBaseList(IoBase)) {
  138. return FALSE;
  139. }
  140. if (LegacyBaseListCount < LEGACY_BASE_LIST_SIZE) {
  141. LegacyBaseList[LegacyBaseListCount++] = IoBase;
  142. }
  143. // note, we return true even if we overflow the list
  144. return TRUE;
  145. }
  146. VOID
  147. MapPcCardController(
  148. PPCCARD_INFORMATION PcCardInfo
  149. )
  150. /*++
  151. Routine Description:
  152. This routine is the entry for doing ISA IRQ detection for PcCard
  153. controllers.
  154. Arguments:
  155. PcCardInfo - Structure defining the device to run detection on
  156. Returns:
  157. None.
  158. --*/
  159. {
  160. USHORT wDetected;
  161. USHORT i;
  162. PcCardInfo->ErrorCode = 0;
  163. for (i=0; i<16; i++) {
  164. PcCardInfo->abIRQMap[i]=0;
  165. }
  166. if (!PcCardInfo->IoBase) {
  167. PcCardInfo->Flags |= PCCARD_MAP_ERROR;
  168. PcCardInfo->ErrorCode = PCCARD_NO_LEGACY_BASE;
  169. } else if (!SetLegacyBaseList(PcCardInfo->IoBase)) {
  170. PcCardInfo->Flags |= PCCARD_MAP_ERROR;
  171. PcCardInfo->ErrorCode = PCCARD_DUP_LEGACY_BASE;
  172. }
  173. if (!(PcCardInfo->Flags & PCCARD_MAP_ERROR)) {
  174. PcCardInfo->wValidIRQs = PCCARD_POSSIBLE_IRQS;
  175. #if DBG
  176. BlPrint("Going to detect...\n");
  177. #endif
  178. //
  179. // Do the IRQ detection
  180. //
  181. wDetected = DetectIRQMap(PcCardInfo);
  182. #if DBG
  183. BlPrint("Detect IRQ Map returns %x on iobase %x\n", wDetected, PcCardInfo->IoBase);
  184. #endif
  185. if (!wDetected) {
  186. PcCardInfo->ErrorCode = PCCARD_MAP_ZERO;
  187. }
  188. }
  189. #if DBG
  190. if (PcCardInfo->Flags & PCCARD_MAP_ERROR) {
  191. BlPrint("Error mapping device, code=%x\n", PcCardInfo->ErrorCode);
  192. }
  193. #endif
  194. //
  195. // Report the results
  196. //
  197. SetPcCardConfigurationData(PcCardInfo);
  198. }
  199. VOID
  200. LookForPciCardBusBridges(
  201. USHORT BusStart,
  202. USHORT BusEnd,
  203. )
  204. /*++
  205. Routine Description:
  206. This routine is the entry for doing ISA IRQ detection for PCI-based
  207. cardbus controllers.
  208. Arguments:
  209. Bus = PCI Bus number to scan
  210. Returns:
  211. None.
  212. --*/
  213. {
  214. PCCARD_INFORMATION PcCardInfo = {0};
  215. USHORT Device, Function;
  216. UCHAR HeaderType;
  217. UCHAR SecBus, SubBus;
  218. USHORT VendorId;
  219. USHORT DeviceId;
  220. ULONG LegacyBaseAddress;
  221. USHORT i;
  222. USHORT Bus;
  223. #if DBG
  224. BlPrint("LookForPciCardBusBridges %x-%x\n", BusStart, BusEnd);
  225. #endif
  226. for (Bus = BusStart; Bus <= BusEnd; Bus++) {
  227. PcCardInfo.PciCfg1.u.AsULONG = 0;
  228. PcCardInfo.PciCfg1.u.bits.BusNumber = Bus;
  229. PcCardInfo.PciCfg1.u.bits.Enable = TRUE;
  230. for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
  231. PcCardInfo.PciCfg1.u.bits.DeviceNumber = Device;
  232. for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
  233. PcCardInfo.PciCfg1.u.bits.FunctionNumber = Function;
  234. VendorId = 0xffff;
  235. GetPciConfigSpace(&PcCardInfo, CFGSPACE_VENDOR_ID, &VendorId, sizeof(VendorId));
  236. if ((VendorId == 0xffff) || (VendorId == 0)) {
  237. if (Function == 0) {
  238. break;
  239. } else {
  240. continue;
  241. }
  242. }
  243. GetPciConfigSpace(&PcCardInfo, CFGSPACE_DEVICE_ID, &DeviceId, sizeof(DeviceId));
  244. GetPciConfigSpace(&PcCardInfo, CFGSPACE_HEADER_TYPE, &HeaderType, sizeof(HeaderType));
  245. switch(HeaderType & 0x7f) {
  246. case PCI_CARDBUS_BRIDGE_TYPE:
  247. #if DBG
  248. BlPrint("%x.%x.%x : DeviceID = %lx (CardBus Bridge)\n", Bus, Device, Function, DeviceId);
  249. #endif
  250. PcCardInfo.DeviceId = (ULONG) (VendorId << 16) | DeviceId;
  251. PcCardInfo.Flags = PCCARD_DEVICE_PCI;
  252. //
  253. // See if this is a special cased controller
  254. //
  255. PcCardInfo.bDevType = DEVTYPE_GENERIC_CARDBUS;
  256. i = 0;
  257. while (CBTable[i].DeviceId != 0) {
  258. if (DeviceId == CBTable[i].DeviceId) {
  259. PcCardInfo.bDevType = CBTable[i].bDevType;
  260. break;
  261. }
  262. i++;
  263. }
  264. GetPciConfigSpace(&PcCardInfo, CFGSPACE_LEGACY_MODE_BASE_ADDR, &LegacyBaseAddress, 4);
  265. PcCardInfo.IoBase = (USHORT) (LegacyBaseAddress & ~1);
  266. MapPcCardController(&PcCardInfo);
  267. break;
  268. case PCI_BRIDGE_TYPE:
  269. #if DBG
  270. BlPrint("%x.%x.%x : DeviceID = %lx (Pci-Pci Bridge)\n", Bus, Device, Function, DeviceId);
  271. #endif
  272. GetPciConfigSpace(&PcCardInfo, CFGSPACE_SECONDARY_BUS, &SecBus, sizeof(SecBus));
  273. GetPciConfigSpace(&PcCardInfo, CFGSPACE_SUBORDINATE_BUS, &SubBus, sizeof(SubBus));
  274. if ((SecBus <= Bus) || (SubBus <= Bus) || (SubBus < SecBus)) {
  275. break;
  276. }
  277. //
  278. // Be conservative on stack space, only look one level deep
  279. //
  280. if (Bus > 0) {
  281. break;
  282. }
  283. LookForPciCardBusBridges(SecBus, SubBus);
  284. break;
  285. }
  286. }
  287. }
  288. }
  289. }
  290. VOID
  291. LookForPcicControllers(
  292. VOID
  293. )
  294. /*++
  295. Routine Description:
  296. This routine is the entry for doing ISA IRQ detection for PCIC
  297. controllers.
  298. Arguments:
  299. None.
  300. Returns:
  301. None.
  302. --*/
  303. {
  304. PCCARD_INFORMATION PcCardInfo = {0};
  305. USHORT IoBase;
  306. UCHAR id;
  307. for (IoBase = 0x3e0; IoBase < 0x3e6; IoBase+=2) {
  308. if (IsOnLegacyBaseList(IoBase)) {
  309. continue;
  310. }
  311. PcCardInfo.Flags = 0;
  312. PcCardInfo.IoBase = IoBase;
  313. PcCardInfo.bDevType = DEVTYPE_GENERIC_PCIC;
  314. id = PcicReadSocket(&PcCardInfo, EXCAREG_IDREV);
  315. switch (id) {
  316. case PCIC_REVISION:
  317. case PCIC_REVISION2:
  318. case PCIC_REVISION3:
  319. #if DBG
  320. BlPrint("Pcic Controller at base %x, rev(%x)\n", IoBase, id);
  321. #endif
  322. MapPcCardController(&PcCardInfo);
  323. break;
  324. #if DBG
  325. default:
  326. BlPrint("Not mapping base %x, return is (%x)\n", IoBase, id);
  327. #endif
  328. }
  329. }
  330. }
  331. FPFWCONFIGURATION_COMPONENT_DATA
  332. GetPcCardInformation(
  333. VOID
  334. )
  335. /*++
  336. Routine Description:
  337. This routine is the entry for doing ISA IRQ detection for PcCard
  338. controllers.
  339. Arguments:
  340. None.
  341. Returns:
  342. A pointer to a pccard component structure, if IRQ's were properly detected.
  343. Otherwise a NULL pointer is returned.
  344. --*/
  345. {
  346. PCCARD_INFORMATION PcCardInfo = {0};
  347. UCHAR ErrorCode = 0;
  348. //
  349. // Check for things which would prevent us from attempting
  350. // the irq detection
  351. //
  352. if (DisablePccardIrqScan == 1) {
  353. ErrorCode = PCCARD_SCAN_DISABLED;
  354. } else if (!SystemHas8259) {
  355. ErrorCode = PCCARD_NO_PIC;
  356. } else if (!SystemHas8253) {
  357. ErrorCode = PCCARD_NO_TIMER;
  358. }
  359. //
  360. // If things look ok so far, do the detection
  361. //
  362. if (!ErrorCode) {
  363. #if DBG
  364. BlPrint("press any key to continue...\n");
  365. while ( !HwGetKey() ) ; // wait until key pressed to continue
  366. clrscrn();
  367. BlPrint("Looking for PcCard Controllers...\n");
  368. #endif
  369. //
  370. // Look first for cardbus
  371. //
  372. LookForPciCardBusBridges(0,0);
  373. //
  374. // Now check for regular pcic devices
  375. //
  376. LookForPcicControllers();
  377. #if DBG
  378. BlPrint("press any key to continue...\n");
  379. while ( !HwGetKey() ) ; // wait until key pressed to continue
  380. #endif
  381. if (!ControllerList) {
  382. ErrorCode = PCCARD_NO_CONTROLLERS;
  383. }
  384. }
  385. if (ErrorCode) {
  386. //
  387. // Something when wrong, so write a single entry to
  388. // allow someone to see what the error was
  389. //
  390. PcCardInfo.Flags |= PCCARD_MAP_ERROR;
  391. PcCardInfo.ErrorCode = ErrorCode;
  392. SetPcCardConfigurationData(&PcCardInfo);
  393. }
  394. return ControllerList;
  395. }
  396. USHORT
  397. DetectIRQMap(
  398. PPCCARD_INFORMATION pa
  399. )
  400. /*++
  401. Routine Description:
  402. This routine detects the IRQ mapping of the specified cardbus controller.
  403. Note that the controller is in PCIC mode.
  404. Arguments:
  405. pa -> ADAPTER structure
  406. Returns:
  407. returns detected IRQ bit mask
  408. --*/
  409. {
  410. USHORT wRealIRQMask = 0;
  411. USHORT wData;
  412. UCHAR bData;
  413. BOOLEAN fTINMIBug = FALSE;
  414. UCHAR i;
  415. USHORT wIRQMask, wRealIRQ, w;
  416. if (pa->bDevType == DEVTYPE_CL_PD6832)
  417. {
  418. //enable CSC IRQ routing just for IRQ detection
  419. GetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
  420. wData |= BCTRL_CL_CSCIRQROUTING_ENABLE;
  421. SetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
  422. }
  423. else if ((pa->bDevType == DEVTYPE_CL_PD6834) ||
  424. (pa->bDevType == DEVTYPE_CL_PD6833))
  425. {
  426. //enable CSC IRQ routing just for IRQ detection
  427. GetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
  428. bData |= CL_CFGMISC1_ISACSC;
  429. SetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
  430. }
  431. else if ((pa->bDevType == DEVTYPE_TI_PCI1130) ||
  432. (pa->bDevType == DEVTYPE_TI_PCI1131) ||
  433. (pa->bDevType == DEVTYPE_TI_PCI1031))
  434. {
  435. GetPciConfigSpace(pa, CFGSPACE_TI_DEV_CTRL, &wData, sizeof(wData));
  436. if ((wData & DEVCTRL_INTMODE_MASK) == DEVCTRL_INTMODE_COMPAQ)
  437. {
  438. //
  439. // There is an errata on TI 1130, 1131 and 1031 in which if
  440. // the chip is programmed to use serial IRQ mode (i.e. COMPAQ
  441. // mode) and the SERIRQ pin is not pull up with a 1K resistor,
  442. // the SERIRQ line will rise too slowly after IRQ 15 is
  443. // deasserted so that it looks like NMI should be asserted.
  444. // This caused spurious NMI. This is a hardware problem.
  445. // Unfortunately, there are a large number of machines with
  446. // this problem on the street already, so CBSS has to work
  447. // around the problem by temporarily disabling NMI before
  448. // doing ISA IRQ detection.
  449. //
  450. fTINMIBug = TRUE;
  451. _asm in al,SYSCTRL_B
  452. _asm and al,0x0f
  453. _asm push ax
  454. //
  455. // Mask NMI
  456. //
  457. _asm or al,0x08
  458. _asm out SYSCTRL_B,al
  459. }
  460. }
  461. _asm pushf
  462. _asm cli //disable interrupt
  463. _asm in al,PIC2_IMR //save old IMRs
  464. _asm mov ah,al
  465. _asm in al,PIC1_IMR
  466. _asm push ax
  467. _asm mov al,0xff //mask all interrupt
  468. _asm out PIC2_IMR,al
  469. _asm out PIC1_IMR,al
  470. for (i = 0; i < 16; ++i)
  471. {
  472. w = (USHORT)(1 << i);
  473. if ((pa->wValidIRQs & w) &&
  474. ((wIRQMask = ToggleIRQLine(pa, i)) != 0))
  475. {
  476. _asm mov dx, wIRQMask
  477. _asm _emit 0x66
  478. _asm _emit 0x0f
  479. _asm _emit 0xbc
  480. _asm _emit 0xc2
  481. _asm mov wRealIRQ,ax
  482. pa->abIRQMap[wRealIRQ] = i;
  483. wRealIRQMask |= (USHORT)(1 << wRealIRQ);
  484. }
  485. }
  486. Clear_IR_Bits(wRealIRQMask);
  487. _asm pop ax
  488. _asm out PIC1_IMR,al
  489. _asm mov al,ah
  490. _asm out PIC2_IMR,al
  491. _asm popf
  492. if (fTINMIBug)
  493. {
  494. //
  495. // Restore NMI mask
  496. //
  497. _asm pop ax
  498. _asm out SYSCTRL_B,al
  499. }
  500. if (pa->bDevType == DEVTYPE_CL_PD6832)
  501. {
  502. //disable CSC IRQ routing (use PCI interrupt for CSC)
  503. GetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
  504. wData &= ~BCTRL_CL_CSCIRQROUTING_ENABLE;
  505. SetPciConfigSpace(pa, CFGSPACE_BRIDGE_CTRL, &wData, sizeof(wData));
  506. }
  507. else if ((pa->bDevType == DEVTYPE_CL_PD6834) ||
  508. (pa->bDevType == DEVTYPE_CL_PD6833))
  509. {
  510. //disable CSC IRQ routing (use PCI interrupt for CSC)
  511. GetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
  512. bData &= ~CL_CFGMISC1_ISACSC;
  513. SetPciConfigSpace(pa, CFGSPACE_CL_CFGMISC1, &bData, sizeof(bData));
  514. }
  515. return wRealIRQMask;
  516. } //DetectIRQMap
  517. USHORT
  518. ToggleIRQLine(
  519. PPCCARD_INFORMATION pa,
  520. UCHAR bIRQ
  521. )
  522. /*++
  523. Routine Description:
  524. This routine toggles the specified IRQ line from the adapter.
  525. Arguments:
  526. pa -> ADAPTER structure
  527. bIRQ - IRQ line to toggle
  528. Returns:
  529. returns the IRR mask from PIC
  530. --*/
  531. {
  532. UCHAR bOldIntCtrl, bOldIntCfg, bData;
  533. USHORT rc = 0, irr1, irr2, irr3;
  534. bOldIntCfg = PcicReadSocket(pa, EXCAREG_CSC_CFG);
  535. bOldIntCtrl = PcicReadSocket(pa, EXCAREG_INT_GENCTRL);
  536. //Set to a known state
  537. PcicWriteSocket(pa, EXCAREG_INT_GENCTRL, IGC_PCCARD_RESETLO);
  538. //Set irq number in interrupt control register and enable irq
  539. PcicWriteSocket(pa, EXCAREG_CSC_CFG, (UCHAR)((bIRQ << 4) | CSCFG_CD_ENABLE));
  540. //clear all pending interrupts
  541. bData = PcicReadSocket(pa, EXCAREG_CARD_STATUS);
  542. irr1 = GetPICIRR();
  543. if (PcicReadSocket(pa, EXCAREG_IDREV) != 0x82)
  544. {
  545. //This is not an A stepping part, try the undocumented interrupt
  546. //register. If this fails the other routine will be tried.
  547. PcicWriteSocket(pa, EXCAREG_CARDDET_GENCTRL, CDGC_SW_DET_INT);
  548. irr2 = GetPICIRR();
  549. //reset pending interrupt
  550. bData = PcicReadSocket(pa, EXCAREG_CARD_STATUS);
  551. irr3 = GetPICIRR();
  552. rc = (USHORT)((irr1 ^ irr2) & (irr2 ^ irr3));
  553. }
  554. if (rc == 0)
  555. {
  556. //Generate interrupt by de-asserting IRQ line so the PIC can pull it
  557. //high
  558. PcicWriteSocket(pa, EXCAREG_CSC_CFG, 0);
  559. //if (pa->dwfAdapter & AF_TI_SERIALIRQ)
  560. // TIReleaseSerialIRQ(pa, bIRQ);
  561. irr2 = GetPICIRR();
  562. //re-assert IRQ line
  563. PcicWriteSocket(pa, EXCAREG_CSC_CFG, (UCHAR)((bIRQ << 4) | CSCFG_CD_ENABLE));
  564. //reset pending interrupt
  565. bData = PcicReadSocket(pa, EXCAREG_CARD_STATUS);
  566. irr3 = GetPICIRR();
  567. rc = (USHORT)((irr1 ^ irr2) & (irr2 ^ irr3));
  568. }
  569. PcicWriteSocket(pa, EXCAREG_CSC_CFG, bOldIntCfg);
  570. PcicWriteSocket(pa, EXCAREG_INT_GENCTRL, bOldIntCtrl);
  571. return rc;
  572. } //ToggleIRQLine
  573. /***LP GetPICIRR - Read PIC IRR
  574. *
  575. * ENTRY
  576. * None
  577. *
  578. * EXIT
  579. * returns the IRR mask from PIC
  580. */
  581. USHORT GetPICIRR(VOID)
  582. {
  583. USHORT wData;
  584. //
  585. // Delay 2 usec before reading PIC because serial IRQ may be a bit slow.
  586. //
  587. TimeOut(4);
  588. _asm mov al,PIC_RD_IR
  589. _asm out PIC2_OCW3,al
  590. _asm in al,PIC2_OCW3
  591. _asm mov ah,al
  592. _asm mov al,PIC_RD_IR
  593. _asm out PIC1_OCW3,al
  594. _asm in al,PIC1_OCW3
  595. _asm mov wData,ax
  596. return wData;
  597. } //GetPICIRR
  598. UCHAR
  599. PcicReadSocket(
  600. PPCCARD_INFORMATION pa,
  601. USHORT Reg
  602. )
  603. {
  604. USHORT IoBase = pa->IoBase;
  605. UCHAR value;
  606. _asm {
  607. mov dx, IoBase
  608. mov ax, Reg
  609. out dx, al
  610. inc dx
  611. in al, dx
  612. mov value, al
  613. }
  614. return value;
  615. }
  616. VOID
  617. PcicWriteSocket(
  618. PPCCARD_INFORMATION pa,
  619. USHORT Reg,
  620. UCHAR value
  621. )
  622. {
  623. USHORT IoBase = pa->IoBase;
  624. _asm {
  625. mov dx, IoBase
  626. mov ax, Reg
  627. out dx, al
  628. inc dx
  629. mov al, value
  630. out dx, al
  631. }
  632. }
  633. UCHAR PCIDeref[4][4] = { {4,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
  634. VOID
  635. SetPciConfigSpace(
  636. PPCCARD_INFORMATION pa,
  637. USHORT Offset,
  638. PVOID pvBuffer,
  639. USHORT Length
  640. )
  641. {
  642. USHORT IoSize;
  643. PUCHAR Buffer = (PUCHAR) pvBuffer;
  644. //
  645. // Read it
  646. //
  647. while (Length) {
  648. pa->PciCfg1.u.bits.RegisterNumber = Offset / sizeof(ULONG);
  649. IoSize = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
  650. SetPCIType1Data (pa->PciCfg1.u.AsULONG,
  651. (Offset % sizeof(ULONG)),
  652. Buffer,
  653. IoSize);
  654. Offset += IoSize;
  655. Buffer += IoSize;
  656. Length -= IoSize;
  657. }
  658. }
  659. VOID
  660. GetPciConfigSpace(
  661. PPCCARD_INFORMATION pa,
  662. USHORT Offset,
  663. PVOID pvBuffer,
  664. USHORT Length
  665. )
  666. {
  667. USHORT IoSize;
  668. USHORT i;
  669. PUCHAR Buffer = (PUCHAR) pvBuffer;
  670. //
  671. // Zap input buffer
  672. //
  673. for (i=0; i < Length; i++) {
  674. Buffer[i] = 0xff;
  675. }
  676. //
  677. // Read it
  678. //
  679. while (Length) {
  680. pa->PciCfg1.u.bits.RegisterNumber = Offset / sizeof(ULONG);
  681. IoSize = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
  682. GetPCIType1Data (pa->PciCfg1.u.AsULONG,
  683. (Offset % sizeof(ULONG)),
  684. Buffer,
  685. IoSize);
  686. Offset += IoSize;
  687. Buffer += IoSize;
  688. Length -= IoSize;
  689. }
  690. }