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.

2795 lines
90 KiB

  1. /*++
  2. Copyright (c) 1990, 1991, 1992, 1993 - 1997 Microsoft Corporation
  3. Module Name :
  4. serial.h
  5. Abstract:
  6. Type definitions and data for the serial port driver
  7. Author:
  8. Anthony V. Ercolano April 8, 1991
  9. --*/
  10. #ifdef POOL_TAGGING
  11. #undef ExAllocatePool
  12. #undef ExAllocatePoolWithQuota
  13. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'XMOC')
  14. #define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,'XMOC')
  15. #endif
  16. //
  17. // The following definition is used to include/exclude changes made for power
  18. // support in the driver. If non-zero the support is included. If zero the
  19. // support is excluded.
  20. //
  21. #define POWER_SUPPORT 1
  22. //
  23. // The following is used to tell the serial driver to perform legacy detection
  24. // and initialization until PnP functionality can be fully implemented.
  25. //
  26. // #define FAKE_IT 1
  27. #define RM_PNP_CODE
  28. #if DBG
  29. #define SERDIAG1 ((ULONG)0x00000001)
  30. #define SERDIAG2 ((ULONG)0x00000002)
  31. #define SERDIAG3 ((ULONG)0x00000004)
  32. #define SERDIAG4 ((ULONG)0x00000008)
  33. #define SERDIAG5 ((ULONG)0x00000010)
  34. #define SERIRPPATH ((ULONG)0x00000020)
  35. #define SERINITCODE ((ULONG)0x00000040)
  36. #define SERTRACECALLS ((ULONG)0x00000040)
  37. #define SERPNPPOWER ((ULONG)0x00000100)
  38. #define SERFLOW ((ULONG)0x20000000)
  39. #define SERERRORS ((ULONG)0x40000000)
  40. #define SERBUGCHECK ((ULONG)0x80000000)
  41. #define SERDBGALL ((ULONG)0xFFFFFFFF)
  42. #define SER_DBG_DEFAULT SERDBGALL
  43. extern ULONG SerialDebugLevel;
  44. #if defined(NEC_98)
  45. //
  46. // DbgPrint header changed from SERIAL to SER71051
  47. //
  48. #define SerialDump(LEVEL,STRING) \
  49. do { \
  50. ULONG _level = (LEVEL); \
  51. if (SerialDebugLevel & _level) { \
  52. DbgPrint ("SER71051: "); \
  53. DbgPrint STRING; \
  54. } \
  55. if (_level == SERBUGCHECK) { \
  56. ASSERT(FALSE); \
  57. } \
  58. } while (0)
  59. #else
  60. #define SerialDump(LEVEL,STRING) \
  61. do { \
  62. ULONG _level = (LEVEL); \
  63. if (SerialDebugLevel & _level) { \
  64. DbgPrint STRING; \
  65. } \
  66. if (_level == SERBUGCHECK) { \
  67. ASSERT(FALSE); \
  68. } \
  69. } while (0)
  70. #endif //defined(NEC_98)
  71. #else
  72. #define SerialDump(LEVEL,STRING) do {NOTHING;} while (0)
  73. #endif
  74. //
  75. // Some default driver values. We will check the registry for
  76. // them first.
  77. //
  78. #define SERIAL_UNINITIALIZED_DEFAULT 1234567
  79. #define SERIAL_FORCE_FIFO_DEFAULT 1
  80. #define SERIAL_RX_FIFO_DEFAULT 8
  81. #define SERIAL_TX_FIFO_DEFAULT 14
  82. #define SERIAL_PERMIT_SHARE_DEFAULT 0
  83. #define SERIAL_LOG_FIFO_DEFAULT 0
  84. //
  85. // This define gives the default Object directory
  86. // that we should use to insert the symbolic links
  87. // between the NT device name and namespace used by
  88. // that object directory.
  89. #define DEFAULT_DIRECTORY L"DosDevices"
  90. //
  91. // For the above directory, the serial port will
  92. // use the following name as the suffix of the serial
  93. // ports for that directory. It will also append
  94. // a number onto the end of the name. That number
  95. // will start at 1.
  96. #define DEFAULT_SERIAL_NAME L"COM"
  97. //
  98. //
  99. // This define gives the default NT name for
  100. // for serial ports detected by the firmware.
  101. // This name will be appended to Device prefix
  102. // with a number following it. The number is
  103. // incremented each time encounter a serial
  104. // port detected by the firmware. Note that
  105. // on a system with multiple busses, this means
  106. // that the first port on a bus is not necessarily
  107. // \Device\Serial0.
  108. //
  109. #if defined(NEC_98)
  110. #define DEFAULT_NT_SUFFIX L"Ser71051"
  111. #else
  112. #define DEFAULT_NT_SUFFIX L"Serial"
  113. #endif //defined(NEC_98)
  114. #if defined(NEC_98)
  115. //
  116. // Out of offsets from the base register address of the
  117. // various registers for the 71051.
  118. //
  119. #define SYSTEM_PORT_C 0x35
  120. #define TIMER_MODE_REGISTER 0x77
  121. #define TIMER_COUNT_REGISTER 0x75
  122. #define COMMAND_SET 0x32
  123. #define MODE_SET 0x32
  124. #define IO_DELAY_REGISTER 0x5f
  125. #define CONFIG_INDEX_REGISTER 0x411
  126. #define CONFIG_DATA_REGISTER 0x413
  127. #define TRANSFER_CLOCK_ENABLE_ADDRESS (UCHAR)0x83
  128. #else
  129. #endif //defined(NEC_98)
  130. //
  131. // This value - which could be redefined at compile
  132. // time, define the stride between registers
  133. //
  134. #if !defined(SERIAL_REGISTER_STRIDE)
  135. #define SERIAL_REGISTER_STRIDE 1
  136. #endif
  137. //
  138. // Offsets from the base register address of the
  139. // various registers for the 8250 family of UARTS.
  140. //
  141. #define RECEIVE_BUFFER_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
  142. #define TRANSMIT_HOLDING_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
  143. #if defined(NEC_98)
  144. #define INTERRUPT_ENABLE_REGISTER ((ULONG)((0x08)*SERIAL_REGISTER_STRIDE))
  145. #define INTERRUPT_IDENT_REGISTER ((ULONG)((0x06)*SERIAL_REGISTER_STRIDE))
  146. #define FIFO_CONTROL_REGISTER ((ULONG)((0x08)*SERIAL_REGISTER_STRIDE))
  147. #define LINE_CONTROL_REGISTER ((ULONG)((0x03)*SERIAL_REGISTER_STRIDE))
  148. #define MODEM_CONTROL_REGISTER ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE))
  149. #define LINE_STATUS_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
  150. #define MODEM_STATUS_REGISTER ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE))
  151. #define DIVISOR_LATCH_LSB ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
  152. #define DIVISOR_LATCH_MSB ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
  153. #define VFAST_BAUDCLK_REGISTER ((ULONG)((0x0a)*SERIAL_REGISTER_STRIDE))
  154. #define SERIAL_REGISTER_SPAN ((ULONG)(10*SERIAL_REGISTER_STRIDE))
  155. #else
  156. #define INTERRUPT_ENABLE_REGISTER ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
  157. #define INTERRUPT_IDENT_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
  158. #define FIFO_CONTROL_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE))
  159. #define LINE_CONTROL_REGISTER ((ULONG)((0x03)*SERIAL_REGISTER_STRIDE))
  160. #define MODEM_CONTROL_REGISTER ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE))
  161. #define LINE_STATUS_REGISTER ((ULONG)((0x05)*SERIAL_REGISTER_STRIDE))
  162. #define MODEM_STATUS_REGISTER ((ULONG)((0x06)*SERIAL_REGISTER_STRIDE))
  163. #define DIVISOR_LATCH_LSB ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE))
  164. #define DIVISOR_LATCH_MSB ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE))
  165. #define SERIAL_REGISTER_SPAN ((ULONG)(7*SERIAL_REGISTER_STRIDE))
  166. #endif //defined(NEC_98)
  167. //
  168. // If we have an interrupt status register this is its assumed
  169. // length.
  170. //
  171. #define SERIAL_STATUS_LENGTH ((ULONG)(1*SERIAL_REGISTER_STRIDE))
  172. #if defined(NEC_98)
  173. //
  174. // 1stCCU Transfer Clock Enable Port
  175. //
  176. #define TXC_PERMIT ((UCHAR)0x00)
  177. #define TXC_PROHIBIT ((UCHAR)0x01)
  178. //
  179. // V.Fast mode buad rate clock
  180. //
  181. #define VFAST_BAUD_9600 ((SHORT)0x0c)
  182. #define VFAST_BAUD_19200 ((SHORT)0x06)
  183. #define VFAST_BAUD_38400 ((SHORT)0x03)
  184. #define VFAST_BAUD_57600 ((SHORT)0x02)
  185. #define VFAST_BAUD_115200 ((SHORT)0x01)
  186. //
  187. // V.Fast buad rate clock register
  188. //
  189. #define VFAST_ENABLE 0x80
  190. #define VFAST_DISABLE 0x00
  191. //
  192. // default control word to Timer Mode register
  193. //
  194. #define TIMER_DEFAULT_CONTROL ((UCHAR)0xb6)
  195. //
  196. // default out data to command set register
  197. //
  198. #define COMMAND_DEFAULT_SET ((UCHAR)0x15)
  199. #define COMMAND_ERROR_RESET ((UCHAR)0x40)
  200. //
  201. // default baud rate mode(x16) to Mode Set register
  202. //
  203. #define BAUDRATE_DEFAULT_MODE ((UCHAR)0x02)
  204. //
  205. // default out data to Io Delay register
  206. //
  207. #define IO_DELAY_DATA ((UCHAR)0x00)
  208. //
  209. // Fifo mode enable
  210. //
  211. #define DISABLE_FIFO_MODE ((UCHAR)0x00)
  212. #define SUPPORT_FIFO_MODE ((UCHAR)0x40)
  213. #define SUPPORT_FIFO_MASK ((UCHAR)0x60)
  214. //
  215. // Interrupt enable bit
  216. //
  217. #define MODEM_STATUS_INTERRUPT ((UCHAR)0x10)
  218. #define LINE_STATUS_INTERRUPT ((UCHAR)0x08)
  219. #define TRANSMIT_FIFO_INTERRUPT ((UCHAR)0x04)
  220. #define RECEIVE_FIFO_INTERRUPT ((UCHAR)0x01)
  221. //
  222. // These defines are used to set the line control register.
  223. //
  224. #define SER71051_PARITY_MASK ((UCHAR)0x18)
  225. #define SER71051_1_STOP ((UCHAR)0x40)
  226. #define SER71051_1_5_STOP ((UCHAR)0x80)
  227. #define SER71051_2_STOP ((UCHAR)0xc0)
  228. // This defines the bit used to control whether the device is sending
  229. // a break. When this bit is set the device is sending a space (logic 0).
  230. //
  231. #define SER71051_SEND_BREAK 0x08
  232. #else
  233. #endif //defined(NEC_98)
  234. //
  235. // Bitmask definitions for accessing the 8250 device registers.
  236. //
  237. //
  238. // These bits define the number of data bits trasmitted in
  239. // the Serial Data Unit (SDU - Start,data, parity, and stop bits)
  240. //
  241. #define SERIAL_DATA_LENGTH_5 0x00
  242. #define SERIAL_DATA_LENGTH_6 0x01
  243. #define SERIAL_DATA_LENGTH_7 0x02
  244. #define SERIAL_DATA_LENGTH_8 0x03
  245. //
  246. // These masks define the interrupts that can be enabled or disabled.
  247. //
  248. //
  249. // This interrupt is used to notify that there is new incomming
  250. // data available. The SERIAL_RDA interrupt is enabled by this bit.
  251. //
  252. #define SERIAL_IER_RDA 0x01
  253. //
  254. // This interrupt is used to notify that there is space available
  255. // in the transmitter for another character. The SERIAL_THR
  256. // interrupt is enabled by this bit.
  257. //
  258. #define SERIAL_IER_THR 0x02
  259. //
  260. // This interrupt is used to notify that some sort of error occured
  261. // with the incomming data. The SERIAL_RLS interrupt is enabled by
  262. // this bit.
  263. #define SERIAL_IER_RLS 0x04
  264. //
  265. // This interrupt is used to notify that some sort of change has
  266. // taken place in the modem control line. The SERIAL_MS interrupt is
  267. // enabled by this bit.
  268. //
  269. #define SERIAL_IER_MS 0x08
  270. //
  271. // These masks define the values of the interrupt identification
  272. // register. The low bit must be clear in the interrupt identification
  273. // register for any of these interrupts to be valid. The interrupts
  274. // are defined in priority order, with the highest value being most
  275. // important. See above for a description of what each interrupt
  276. // implies.
  277. //
  278. #define SERIAL_IIR_RLS 0x06
  279. #define SERIAL_IIR_RDA 0x04
  280. #define SERIAL_IIR_CTI 0x0c
  281. #define SERIAL_IIR_THR 0x02
  282. #define SERIAL_IIR_MS 0x00
  283. //
  284. // This bit mask get the value of the high two bits of the
  285. // interrupt id register. If this is a 16550 class chip
  286. // these bits will be a one if the fifo's are enbled, otherwise
  287. // they will always be zero.
  288. //
  289. #define SERIAL_IIR_FIFOS_ENABLED 0xc0
  290. //
  291. // If the low bit is logic one in the interrupt identification register
  292. // this implies that *NO* interrupts are pending on the device.
  293. //
  294. #define SERIAL_IIR_NO_INTERRUPT_PENDING 0x01
  295. //
  296. // These masks define access to the fifo control register.
  297. //
  298. //
  299. // Enabling this bit in the fifo control register will turn
  300. // on the fifos. If the fifos are enabled then the high two
  301. // bits of the interrupt id register will be set to one. Note
  302. // that this only occurs on a 16550 class chip. If the high
  303. // two bits in the interrupt id register are not one then
  304. // we know we have a lower model chip.
  305. //
  306. //
  307. #define SERIAL_FCR_ENABLE ((UCHAR)0x01)
  308. #define SERIAL_FCR_RCVR_RESET ((UCHAR)0x02)
  309. #define SERIAL_FCR_TXMT_RESET ((UCHAR)0x04)
  310. //
  311. // This set of values define the high water marks (when the
  312. // interrupts trip) for the receive fifo.
  313. //
  314. #define SERIAL_1_BYTE_HIGH_WATER ((UCHAR)0x00)
  315. #define SERIAL_4_BYTE_HIGH_WATER ((UCHAR)0x40)
  316. #define SERIAL_8_BYTE_HIGH_WATER ((UCHAR)0x80)
  317. #define SERIAL_14_BYTE_HIGH_WATER ((UCHAR)0xc0)
  318. //
  319. // These masks define access to the line control register.
  320. //
  321. //
  322. // This defines the bit used to control the definition of the "first"
  323. // two registers for the 8250. These registers are the input/output
  324. // register and the interrupt enable register. When the DLAB bit is
  325. // enabled these registers become the least significant and most
  326. // significant bytes of the divisor value.
  327. //
  328. #define SERIAL_LCR_DLAB 0x80
  329. //
  330. // This defines the bit used to control whether the device is sending
  331. // a break. When this bit is set the device is sending a space (logic 0).
  332. //
  333. // Most protocols will assume that this is a hangup.
  334. //
  335. #define SERIAL_LCR_BREAK 0x40
  336. //
  337. // These defines are used to set the line control register.
  338. //
  339. #define SERIAL_5_DATA ((UCHAR)0x00)
  340. #define SERIAL_6_DATA ((UCHAR)0x01)
  341. #define SERIAL_7_DATA ((UCHAR)0x02)
  342. #define SERIAL_8_DATA ((UCHAR)0x03)
  343. #define SERIAL_DATA_MASK ((UCHAR)0x03)
  344. #define SERIAL_1_STOP ((UCHAR)0x00)
  345. #define SERIAL_1_5_STOP ((UCHAR)0x04) // Only valid for 5 data bits
  346. #define SERIAL_2_STOP ((UCHAR)0x04) // Not valid for 5 data bits
  347. #define SERIAL_STOP_MASK ((UCHAR)0x04)
  348. #define SERIAL_NONE_PARITY ((UCHAR)0x00)
  349. #define SERIAL_ODD_PARITY ((UCHAR)0x08)
  350. #define SERIAL_EVEN_PARITY ((UCHAR)0x18)
  351. #define SERIAL_MARK_PARITY ((UCHAR)0x28)
  352. #define SERIAL_SPACE_PARITY ((UCHAR)0x38)
  353. #define SERIAL_PARITY_MASK ((UCHAR)0x38)
  354. //
  355. // These masks define access the modem control register.
  356. //
  357. //
  358. // This bit controls the data terminal ready (DTR) line. When
  359. // this bit is set the line goes to logic 0 (which is then inverted
  360. // by normal hardware). This is normally used to indicate that
  361. // the device is available to be used. Some odd hardware
  362. // protocols (like the kernel debugger) use this for handshaking
  363. // purposes.
  364. //
  365. #define SERIAL_MCR_DTR 0x01
  366. //
  367. // This bit controls the ready to send (RTS) line. When this bit
  368. // is set the line goes to logic 0 (which is then inverted by the normal
  369. // hardware). This is used for hardware handshaking. It indicates that
  370. // the hardware is ready to send data and it is waiting for the
  371. // receiving end to set clear to send (CTS).
  372. //
  373. #define SERIAL_MCR_RTS 0x02
  374. //
  375. // This bit is used for general purpose output.
  376. //
  377. #define SERIAL_MCR_OUT1 0x04
  378. //
  379. // This bit is used for general purpose output.
  380. //
  381. #define SERIAL_MCR_OUT2 0x08
  382. //
  383. // This bit controls the loopback testing mode of the device. Basically
  384. // the outputs are connected to the inputs (and vice versa).
  385. //
  386. #define SERIAL_MCR_LOOP 0x10
  387. //
  388. // These masks define access to the line status register. The line
  389. // status register contains information about the status of data
  390. // transfer. The first five bits deal with receive data and the
  391. // last two bits deal with transmission. An interrupt is generated
  392. // whenever bits 1 through 4 in this register are set.
  393. //
  394. //
  395. // This bit is the data ready indicator. It is set to indicate that
  396. // a complete character has been received. This bit is cleared whenever
  397. // the receive buffer register has been read.
  398. //
  399. #define SERIAL_LSR_DR 0x01
  400. //
  401. // This is the overrun indicator. It is set to indicate that the receive
  402. // buffer register was not read befor a new character was transferred
  403. // into the buffer. This bit is cleared when this register is read.
  404. //
  405. #define SERIAL_LSR_OE 0x02
  406. //
  407. // This is the parity error indicator. It is set whenever the hardware
  408. // detects that the incoming serial data unit does not have the correct
  409. // parity as defined by the parity select in the line control register.
  410. // This bit is cleared by reading this register.
  411. //
  412. #define SERIAL_LSR_PE 0x04
  413. //
  414. // This is the framing error indicator. It is set whenever the hardware
  415. // detects that the incoming serial data unit does not have a valid
  416. // stop bit. This bit is cleared by reading this register.
  417. //
  418. #define SERIAL_LSR_FE 0x08
  419. //
  420. // This is the break interrupt indicator. It is set whenever the data
  421. // line is held to logic 0 for more than the amount of time it takes
  422. // to send one serial data unit. This bit is cleared whenever the
  423. // this register is read.
  424. //
  425. #define SERIAL_LSR_BI 0x10
  426. //
  427. // This is the transmit holding register empty indicator. It is set
  428. // to indicate that the hardware is ready to accept another character
  429. // for transmission. This bit is cleared whenever a character is
  430. // written to the transmit holding register.
  431. //
  432. #define SERIAL_LSR_THRE 0x20
  433. //
  434. // This bit is the transmitter empty indicator. It is set whenever the
  435. // transmit holding buffer is empty and the transmit shift register
  436. // (a non-software accessable register that is used to actually put
  437. // the data out on the wire) is empty. Basically this means that all
  438. // data has been sent. It is cleared whenever the transmit holding or
  439. // the shift registers contain data.
  440. //
  441. #define SERIAL_LSR_TEMT 0x40
  442. //
  443. // This bit indicates that there is at least one error in the fifo.
  444. // The bit will not be turned off until there are no more errors
  445. // in the fifo.
  446. //
  447. #define SERIAL_LSR_FIFOERR 0x80
  448. //
  449. // These masks are used to access the modem status register.
  450. // Whenever one of the first four bits in the modem status
  451. // register changes state a modem status interrupt is generated.
  452. //
  453. //
  454. // This bit is the delta clear to send. It is used to indicate
  455. // that the clear to send bit (in this register) has *changed*
  456. // since this register was last read by the CPU.
  457. //
  458. #define SERIAL_MSR_DCTS 0x01
  459. //
  460. // This bit is the delta data set ready. It is used to indicate
  461. // that the data set ready bit (in this register) has *changed*
  462. // since this register was last read by the CPU.
  463. //
  464. #define SERIAL_MSR_DDSR 0x02
  465. //
  466. // This is the trailing edge ring indicator. It is used to indicate
  467. // that the ring indicator input has changed from a low to high state.
  468. //
  469. #define SERIAL_MSR_TERI 0x04
  470. //
  471. // This bit is the delta data carrier detect. It is used to indicate
  472. // that the data carrier bit (in this register) has *changed*
  473. // since this register was last read by the CPU.
  474. //
  475. #define SERIAL_MSR_DDCD 0x08
  476. //
  477. // This bit contains the (complemented) state of the clear to send
  478. // (CTS) line.
  479. //
  480. #define SERIAL_MSR_CTS 0x10
  481. //
  482. // This bit contains the (complemented) state of the data set ready
  483. // (DSR) line.
  484. //
  485. #define SERIAL_MSR_DSR 0x20
  486. //
  487. // This bit contains the (complemented) state of the ring indicator
  488. // (RI) line.
  489. //
  490. #define SERIAL_MSR_RI 0x40
  491. //
  492. // This bit contains the (complemented) state of the data carrier detect
  493. // (DCD) line.
  494. //
  495. #define SERIAL_MSR_DCD 0x80
  496. //
  497. // This should be more than enough space to hold then
  498. // numeric suffix of the device name.
  499. //
  500. #define DEVICE_NAME_DELTA 20
  501. //
  502. // Up to 16 Ports Per card. However for sixteen
  503. // port cards the interrupt status register must me
  504. // the indexing kind rather then the bitmask kind.
  505. //
  506. //
  507. #define SERIAL_MAX_PORTS_INDEXED (16)
  508. #define SERIAL_MAX_PORTS_NONINDEXED (8)
  509. typedef struct _CONFIG_DATA {
  510. PHYSICAL_ADDRESS Controller;
  511. PHYSICAL_ADDRESS TrController;
  512. PHYSICAL_ADDRESS InterruptStatus;
  513. PHYSICAL_ADDRESS TrInterruptStatus;
  514. ULONG SpanOfController;
  515. ULONG SpanOfInterruptStatus;
  516. ULONG PortIndex;
  517. ULONG ClockRate;
  518. ULONG BusNumber;
  519. ULONG AddressSpace;
  520. ULONG DisablePort;
  521. ULONG ForceFifoEnable;
  522. ULONG RxFIFO;
  523. ULONG TxFIFO;
  524. ULONG PermitShare;
  525. ULONG PermitSystemWideShare;
  526. ULONG LogFifo;
  527. ULONG MaskInverted;
  528. KINTERRUPT_MODE InterruptMode;
  529. INTERFACE_TYPE InterfaceType;
  530. ULONG OriginalVector;
  531. ULONG OriginalIrql;
  532. ULONG TrVector;
  533. ULONG TrIrql;
  534. ULONG Affinity;
  535. ULONG Indexed;
  536. BOOLEAN Jensen;
  537. } CONFIG_DATA,*PCONFIG_DATA;
  538. //
  539. // Serial ISR switch structure
  540. //
  541. typedef struct _SERIAL_CISR_SW {
  542. BOOLEAN (*IsrFunc)(PKINTERRUPT, PVOID);
  543. PVOID Context;
  544. LIST_ENTRY SharerList;
  545. } SERIAL_CISR_SW, *PSERIAL_CISR_SW;
  546. //
  547. // This structure contains configuration data, much of which
  548. // is read from the registry.
  549. //
  550. typedef struct _SERIAL_FIRMWARE_DATA {
  551. PDRIVER_OBJECT DriverObject;
  552. ULONG ControllersFound;
  553. ULONG ForceFifoEnableDefault;
  554. ULONG DebugLevel;
  555. ULONG ShouldBreakOnEntry;
  556. ULONG RxFIFODefault;
  557. ULONG TxFIFODefault;
  558. ULONG PermitShareDefault;
  559. ULONG PermitSystemWideShare;
  560. ULONG LogFifoDefault;
  561. UNICODE_STRING Directory;
  562. UNICODE_STRING NtNameSuffix;
  563. UNICODE_STRING DirectorySymbolicName;
  564. LIST_ENTRY ConfigList;
  565. BOOLEAN JensenDetected;
  566. } SERIAL_FIRMWARE_DATA,*PSERIAL_FIRMWARE_DATA;
  567. //
  568. // Default xon/xoff characters.
  569. //
  570. #define SERIAL_DEF_XON 0x11
  571. #define SERIAL_DEF_XOFF 0x13
  572. //
  573. // Reasons that recption may be held up.
  574. //
  575. #define SERIAL_RX_DTR ((ULONG)0x01)
  576. #define SERIAL_RX_XOFF ((ULONG)0x02)
  577. #define SERIAL_RX_RTS ((ULONG)0x04)
  578. #define SERIAL_RX_DSR ((ULONG)0x08)
  579. //
  580. // Reasons that transmission may be held up.
  581. //
  582. #define SERIAL_TX_CTS ((ULONG)0x01)
  583. #define SERIAL_TX_DSR ((ULONG)0x02)
  584. #define SERIAL_TX_DCD ((ULONG)0x04)
  585. #define SERIAL_TX_XOFF ((ULONG)0x08)
  586. #define SERIAL_TX_BREAK ((ULONG)0x10)
  587. //
  588. // These values are used by the routines that can be used
  589. // to complete a read (other than interval timeout) to indicate
  590. // to the interval timeout that it should complete.
  591. //
  592. #define SERIAL_COMPLETE_READ_CANCEL ((LONG)-1)
  593. #define SERIAL_COMPLETE_READ_TOTAL ((LONG)-2)
  594. #define SERIAL_COMPLETE_READ_COMPLETE ((LONG)-3)
  595. //
  596. // These are default values that shouldn't appear in the registry
  597. //
  598. #define SERIAL_BAD_VALUE ((ULONG)-1)
  599. typedef struct _SERIAL_DEVICE_STATE {
  600. //
  601. // TRUE if we need to set the state to open
  602. // on a powerup
  603. //
  604. BOOLEAN Reopen;
  605. //
  606. // Hardware registers
  607. //
  608. UCHAR IER;
  609. // FCR is known by other values
  610. UCHAR LCR;
  611. UCHAR MCR;
  612. // LSR is never written
  613. // MSR is never written
  614. // SCR is either scratch or interrupt status
  615. } SERIAL_DEVICE_STATE, *PSERIAL_DEVICE_STATE;
  616. #if DBG
  617. #define SerialLockPagableSectionByHandle(_secHandle) \
  618. { \
  619. MmLockPagableSectionByHandle((_secHandle)); \
  620. InterlockedIncrement(&SerialGlobals.PAGESER_Count); \
  621. }
  622. #define SerialUnlockPagableImageSection(_secHandle) \
  623. { \
  624. InterlockedDecrement(&SerialGlobals.PAGESER_Count); \
  625. MmUnlockPagableImageSection(_secHandle); \
  626. }
  627. #define SERIAL_LOCKED_PAGED_CODE() \
  628. if ((KeGetCurrentIrql() > APC_LEVEL) \
  629. && (SerialGlobals.PAGESER_Count == 0)) { \
  630. KdPrint(("SERIAL: Pageable code called at IRQL %d without lock \n", \
  631. KeGetCurrentIrql())); \
  632. ASSERT(FALSE); \
  633. }
  634. #else
  635. #define SerialLockPagableSectionByHandle(_secHandle) \
  636. { \
  637. MmLockPagableSectionByHandle((_secHandle)); \
  638. }
  639. #define SerialUnlockPagableImageSection(_secHandle) \
  640. { \
  641. MmUnlockPagableImageSection(_secHandle); \
  642. }
  643. #define SERIAL_LOCKED_PAGED_CODE()
  644. #endif // DBG
  645. #define SerialRemoveQueueDpc(_dpc, _pExt) \
  646. { \
  647. if (KeRemoveQueueDpc((_dpc))) { \
  648. InterlockedDecrement(&(_pExt)->DpcCount); \
  649. } \
  650. }
  651. typedef struct _SERIAL_DEVICE_EXTENSION {
  652. //
  653. // This holds the isr that should be called from our own
  654. // dispatching isr for "cards" that are trying to share the
  655. // same interrupt.
  656. //
  657. PKSERVICE_ROUTINE TopLevelOurIsr;
  658. //
  659. // This holds the context that should be used when we
  660. // call the above service routine.
  661. //
  662. PVOID TopLevelOurIsrContext;
  663. //
  664. // This links together all of the different "cards" that are
  665. // trying to share the same interrupt of a non-mca machine.
  666. //
  667. LIST_ENTRY TopLevelSharers;
  668. //
  669. // This circular doubly linked list links together all
  670. // devices that are using the same interrupt object.
  671. // NOTE: This does not mean that they are using the
  672. // same interrupt "dispatching" routine.
  673. //
  674. LIST_ENTRY CommonInterruptObject;
  675. //
  676. // This is to link together ports on the same multiport card
  677. //
  678. LIST_ENTRY MultiportSiblings;
  679. //
  680. // This links together all devobjs that this driver owns.
  681. // It is needed to search when starting a new device.
  682. //
  683. LIST_ENTRY AllDevObjs;
  684. //
  685. // For reporting resource usage, we keep around the physical
  686. // address we got from the registry.
  687. //
  688. PHYSICAL_ADDRESS OriginalController;
  689. //
  690. // For reporting resource usage, we keep around the physical
  691. // address we got from the registry.
  692. //
  693. PHYSICAL_ADDRESS OriginalInterruptStatus;
  694. //
  695. // This value is set by the read code to hold the time value
  696. // used for read interval timing. We keep it in the extension
  697. // so that the interval timer dpc routine determine if the
  698. // interval time has passed for the IO.
  699. //
  700. LARGE_INTEGER IntervalTime;
  701. //
  702. // These two values hold the "constant" time that we should use
  703. // to delay for the read interval time.
  704. //
  705. LARGE_INTEGER ShortIntervalAmount;
  706. LARGE_INTEGER LongIntervalAmount;
  707. //
  708. // This holds the value that we use to determine if we should use
  709. // the long interval delay or the short interval delay.
  710. //
  711. LARGE_INTEGER CutOverAmount;
  712. //
  713. // This holds the system time when we last time we had
  714. // checked that we had actually read characters. Used
  715. // for interval timing.
  716. //
  717. LARGE_INTEGER LastReadTime;
  718. //
  719. // We keep a pointer around to our device name for dumps
  720. // and for creating "external" symbolic links to this
  721. // device.
  722. //
  723. UNICODE_STRING DeviceName;
  724. //
  725. // This points to the object directory that we will place
  726. // a symbolic link to our device name.
  727. //
  728. UNICODE_STRING ObjectDirectory;
  729. //
  730. // This points to the device name for this device
  731. // sans device prefix.
  732. //
  733. UNICODE_STRING NtNameForPort;
  734. //
  735. // This points to the symbolic link name that will be
  736. // linked to the actual nt device name.
  737. //
  738. UNICODE_STRING SymbolicLinkName;
  739. //
  740. // This points to the pure "COMx" name
  741. //
  742. UNICODE_STRING DosName;
  743. //
  744. // This points the the delta time that we should use to
  745. // delay for interval timing.
  746. //
  747. PLARGE_INTEGER IntervalTimeToUse;
  748. //
  749. // Points to the device object that contains
  750. // this device extension.
  751. //
  752. PDEVICE_OBJECT DeviceObject;
  753. //
  754. // After initialization of the driver is complete, this
  755. // will either be NULL or point to the routine that the
  756. // kernel will call when an interrupt occurs.
  757. //
  758. // If the pointer is null then this is part of a list
  759. // of ports that are sharing an interrupt and this isn't
  760. // the first port that we configured for this interrupt.
  761. //
  762. // If the pointer is non-null then this routine has some
  763. // kind of structure that will "eventually" get us into
  764. // the real serial isr with a pointer to this device extension.
  765. //
  766. // NOTE: On an MCA bus (except for multiport cards) this
  767. // is always a pointer to the "real" serial isr.
  768. PKSERVICE_ROUTINE OurIsr;
  769. //
  770. // This will generally point right to this device extension.
  771. //
  772. // However, when the port that this device extension is
  773. // "managing" was the first port initialized on a chain
  774. // of ports that were trying to share an interrupt, this
  775. // will point to a structure that will enable dispatching
  776. // to any port on the chain of sharers of this interrupt.
  777. //
  778. PVOID OurIsrContext;
  779. //
  780. // The base address for the set of device registers
  781. // of the serial port.
  782. //
  783. PUCHAR Controller;
  784. //
  785. // The base address for interrupt status register.
  786. // This is only defined in the root extension.
  787. //
  788. PUCHAR InterruptStatus;
  789. //
  790. // Points to the interrupt object for used by this device.
  791. //
  792. PKINTERRUPT Interrupt;
  793. //
  794. // This list head is used to contain the time ordered list
  795. // of read requests. Access to this list is protected by
  796. // the global cancel spinlock.
  797. //
  798. LIST_ENTRY ReadQueue;
  799. //
  800. // This list head is used to contain the time ordered list
  801. // of write requests. Access to this list is protected by
  802. // the global cancel spinlock.
  803. //
  804. LIST_ENTRY WriteQueue;
  805. //
  806. // This list head is used to contain the time ordered list
  807. // of set and wait mask requests. Access to this list is protected by
  808. // the global cancel spinlock.
  809. //
  810. LIST_ENTRY MaskQueue;
  811. //
  812. // Holds the serialized list of purge requests.
  813. //
  814. LIST_ENTRY PurgeQueue;
  815. //
  816. // This points to the irp that is currently being processed
  817. // for the read queue. This field is initialized by the open to
  818. // NULL.
  819. //
  820. // This value is only set at dispatch level. It may be
  821. // read at interrupt level.
  822. //
  823. PIRP CurrentReadIrp;
  824. //
  825. // This points to the irp that is currently being processed
  826. // for the write queue.
  827. //
  828. // This value is only set at dispatch level. It may be
  829. // read at interrupt level.
  830. //
  831. PIRP CurrentWriteIrp;
  832. //
  833. // Points to the irp that is currently being processed to
  834. // affect the wait mask operations.
  835. //
  836. PIRP CurrentMaskIrp;
  837. //
  838. // Points to the irp that is currently being processed to
  839. // purge the read/write queues and buffers.
  840. //
  841. PIRP CurrentPurgeIrp;
  842. //
  843. // Points to the current irp that is waiting on a comm event.
  844. //
  845. PIRP CurrentWaitIrp;
  846. //
  847. // Points to the irp that is being used to send an immediate
  848. // character.
  849. //
  850. PIRP CurrentImmediateIrp;
  851. //
  852. // Points to the irp that is being used to count the number
  853. // of characters received after an xoff (as currently defined
  854. // by the IOCTL_SERIAL_XOFF_COUNTER ioctl) is sent.
  855. //
  856. PIRP CurrentXoffIrp;
  857. //
  858. // Holds the number of bytes remaining in the current write
  859. // irp.
  860. //
  861. // This location is only accessed while at interrupt level.
  862. //
  863. ULONG WriteLength;
  864. //
  865. // Holds a pointer to the current character to be sent in
  866. // the current write.
  867. //
  868. // This location is only accessed while at interrupt level.
  869. //
  870. PUCHAR WriteCurrentChar;
  871. //
  872. // This is a buffer for the read processing.
  873. //
  874. // The buffer works as a ring. When the character is read from
  875. // the device it will be place at the end of the ring.
  876. //
  877. // Characters are only placed in this buffer at interrupt level
  878. // although character may be read at any level. The pointers
  879. // that manage this buffer may not be updated except at interrupt
  880. // level.
  881. //
  882. PUCHAR InterruptReadBuffer;
  883. //
  884. // This is a pointer to the first character of the buffer into
  885. // which the interrupt service routine is copying characters.
  886. //
  887. PUCHAR ReadBufferBase;
  888. //
  889. // This is a count of the number of characters in the interrupt
  890. // buffer. This value is set and read at interrupt level. Note
  891. // that this value is only *incremented* at interrupt level so
  892. // it is safe to read it at any level. When characters are
  893. // copied out of the read buffer, this count is decremented by
  894. // a routine that synchronizes with the ISR.
  895. //
  896. ULONG CharsInInterruptBuffer;
  897. //
  898. // Points to the first available position for a newly received
  899. // character. This variable is only accessed at interrupt level and
  900. // buffer initialization code.
  901. //
  902. PUCHAR CurrentCharSlot;
  903. //
  904. // This variable is used to contain the last available position
  905. // in the read buffer. It is updated at open and at interrupt
  906. // level when switching between the users buffer and the interrupt
  907. // buffer.
  908. //
  909. PUCHAR LastCharSlot;
  910. //
  911. // This marks the first character that is available to satisfy
  912. // a read request. Note that while this always points to valid
  913. // memory, it may not point to a character that can be sent to
  914. // the user. This can occur when the buffer is empty.
  915. //
  916. PUCHAR FirstReadableChar;
  917. //
  918. // Pointer to the lock variable returned for this extension when
  919. // locking down the driver
  920. //
  921. PVOID LockPtr;
  922. //
  923. // This variable holds the size of whatever buffer we are currently
  924. // using.
  925. //
  926. ULONG BufferSize;
  927. //
  928. // This variable holds .8 of BufferSize. We don't want to recalculate
  929. // this real often - It's needed when so that an application can be
  930. // "notified" that the buffer is getting full.
  931. //
  932. ULONG BufferSizePt8;
  933. //
  934. // This value holds the number of characters desired for a
  935. // particular read. It is initially set by read length in the
  936. // IRP. It is decremented each time more characters are placed
  937. // into the "users" buffer buy the code that reads characters
  938. // out of the typeahead buffer into the users buffer. If the
  939. // typeahead buffer is exhausted by the read, and the reads buffer
  940. // is given to the isr to fill, this value is becomes meaningless.
  941. //
  942. ULONG NumberNeededForRead;
  943. //
  944. // This mask will hold the bitmask sent down via the set mask
  945. // ioctl. It is used by the interrupt service routine to determine
  946. // if the occurence of "events" (in the serial drivers understanding
  947. // of the concept of an event) should be noted.
  948. //
  949. ULONG IsrWaitMask;
  950. //
  951. // This mask will always be a subset of the IsrWaitMask. While
  952. // at device level, if an event occurs that is "marked" as interesting
  953. // in the IsrWaitMask, the driver will turn on that bit in this
  954. // history mask. The driver will then look to see if there is a
  955. // request waiting for an event to occur. If there is one, it
  956. // will copy the value of the history mask into the wait irp, zero
  957. // the history mask, and complete the wait irp. If there is no
  958. // waiting request, the driver will be satisfied with just recording
  959. // that the event occured. If a wait request should be queued,
  960. // the driver will look to see if the history mask is non-zero. If
  961. // it is non-zero, the driver will copy the history mask into the
  962. // irp, zero the history mask, and then complete the irp.
  963. //
  964. ULONG HistoryMask;
  965. //
  966. // This is a pointer to the where the history mask should be
  967. // placed when completing a wait. It is only accessed at
  968. // device level.
  969. //
  970. // We have a pointer here to assist us to synchronize completing a wait.
  971. // If this is non-zero, then we have wait outstanding, and the isr still
  972. // knows about it. We make this pointer null so that the isr won't
  973. // attempt to complete the wait.
  974. //
  975. // We still keep a pointer around to the wait irp, since the actual
  976. // pointer to the wait irp will be used for the "common" irp completion
  977. // path.
  978. //
  979. ULONG *IrpMaskLocation;
  980. //
  981. // This mask holds all of the reason that transmission
  982. // is not proceeding. Normal transmission can not occur
  983. // if this is non-zero.
  984. //
  985. // This is only written from interrupt level.
  986. // This could be (but is not) read at any level.
  987. //
  988. ULONG TXHolding;
  989. //
  990. // This mask holds all of the reason that reception
  991. // is not proceeding. Normal reception can not occur
  992. // if this is non-zero.
  993. //
  994. // This is only written from interrupt level.
  995. // This could be (but is not) read at any level.
  996. //
  997. ULONG RXHolding;
  998. //
  999. // This holds the reasons that the driver thinks it is in
  1000. // an error state.
  1001. //
  1002. // This is only written from interrupt level.
  1003. // This could be (but is not) read at any level.
  1004. //
  1005. ULONG ErrorWord;
  1006. //
  1007. // This keeps a total of the number of characters that
  1008. // are in all of the "write" irps that the driver knows
  1009. // about. It is only accessed with the cancel spinlock
  1010. // held.
  1011. //
  1012. ULONG TotalCharsQueued;
  1013. //
  1014. // This holds a count of the number of characters read
  1015. // the last time the interval timer dpc fired. It
  1016. // is a long (rather than a ulong) since the other read
  1017. // completion routines use negative values to indicate
  1018. // to the interval timer that it should complete the read
  1019. // if the interval timer DPC was lurking in some DPC queue when
  1020. // some other way to complete occurs.
  1021. //
  1022. LONG CountOnLastRead;
  1023. //
  1024. // This is a count of the number of characters read by the
  1025. // isr routine. It is *ONLY* written at isr level. We can
  1026. // read it at dispatch level.
  1027. //
  1028. ULONG ReadByIsr;
  1029. //
  1030. // This holds the current baud rate for the device.
  1031. //
  1032. ULONG CurrentBaud;
  1033. //
  1034. // This is the number of characters read since the XoffCounter
  1035. // was started. This variable is only accessed at device level.
  1036. // If it is greater than zero, it implies that there is an
  1037. // XoffCounter ioctl in the queue.
  1038. //
  1039. LONG CountSinceXoff;
  1040. //
  1041. // This ulong is incremented each time something trys to start
  1042. // the execution path that tries to lower the RTS line when
  1043. // doing transmit toggling. If it "bumps" into another path
  1044. // (indicated by a false return value from queueing a dpc
  1045. // and a TRUE return value tring to start a timer) it will
  1046. // decrement the count. These increments and decrements
  1047. // are all done at device level. Note that in the case
  1048. // of a bump while trying to start the timer, we have to
  1049. // go up to device level to do the decrement.
  1050. //
  1051. ULONG CountOfTryingToLowerRTS;
  1052. //
  1053. // This ULONG is used to keep track of the "named" (in ntddser.h)
  1054. // baud rates that this particular device supports.
  1055. //
  1056. ULONG SupportedBauds;
  1057. //
  1058. // This value holds the span (in units of bytes) of the register
  1059. // set controlling this port. This is constant over the life
  1060. // of the port.
  1061. //
  1062. ULONG SpanOfController;
  1063. //
  1064. // This value holds the span (in units of bytes) of the interrupt
  1065. // status register associated with this port. This is constant
  1066. // over the life of the port.
  1067. //
  1068. ULONG SpanOfInterruptStatus;
  1069. //
  1070. // Hold the clock rate input to the serial part.
  1071. //
  1072. ULONG ClockRate;
  1073. //
  1074. // The number of characters to push out if a fifo is present.
  1075. //
  1076. ULONG TxFifoAmount;
  1077. //
  1078. // Set to indicate that it is ok to share interrupts within the device.
  1079. //
  1080. ULONG PermitShare;
  1081. //
  1082. // Holds the timeout controls for the device. This value
  1083. // is set by the Ioctl processing.
  1084. //
  1085. // It should only be accessed under protection of the control
  1086. // lock since more than one request can be in the control dispatch
  1087. // routine at one time.
  1088. //
  1089. SERIAL_TIMEOUTS Timeouts;
  1090. //
  1091. // This holds the various characters that are used
  1092. // for replacement on errors and also for flow control.
  1093. //
  1094. // They are only set at interrupt level.
  1095. //
  1096. SERIAL_CHARS SpecialChars;
  1097. //
  1098. // This structure holds the handshake and control flow
  1099. // settings for the serial driver.
  1100. //
  1101. // It is only set at interrupt level. It can be
  1102. // be read at any level with the control lock held.
  1103. //
  1104. SERIAL_HANDFLOW HandFlow;
  1105. //
  1106. // Holds performance statistics that applications can query.
  1107. // Reset on each open. Only set at device level.
  1108. //
  1109. SERIALPERF_STATS PerfStats;
  1110. //
  1111. // This holds what we beleive to be the current value of
  1112. // the line control register.
  1113. //
  1114. // It should only be accessed under protection of the control
  1115. // lock since more than one request can be in the control dispatch
  1116. // routine at one time.
  1117. //
  1118. UCHAR LineControl;
  1119. //
  1120. // We keep track of whether the somebody has the device currently
  1121. // opened with a simple boolean. We need to know this so that
  1122. // spurious interrupts from the device (especially during initialization)
  1123. // will be ignored. This value is only accessed in the ISR and
  1124. // is only set via synchronization routines. We may be able
  1125. // to get rid of this boolean when the code is more fleshed out.
  1126. //
  1127. BOOLEAN DeviceIsOpened;
  1128. //
  1129. // Set at intialization to indicate that on the current
  1130. // architecture we need to unmap the base register address
  1131. // when we unload the driver.
  1132. //
  1133. BOOLEAN UnMapRegisters;
  1134. //
  1135. // Set at intialization to indicate that on the current
  1136. // architecture we need to unmap the interrupt status address
  1137. // when we unload the driver.
  1138. //
  1139. BOOLEAN UnMapStatus;
  1140. //
  1141. // This is only accessed at interrupt level. It keeps track
  1142. // of whether the holding register is empty.
  1143. //
  1144. BOOLEAN HoldingEmpty;
  1145. //
  1146. // This variable is only accessed at interrupt level. It
  1147. // indicates that we want to transmit a character immediately.
  1148. // That is - in front of any characters that could be transmitting
  1149. // from a normal write.
  1150. //
  1151. BOOLEAN TransmitImmediate;
  1152. //
  1153. // This variable is only accessed at interrupt level. Whenever
  1154. // a wait is initiated this variable is set to false.
  1155. // Whenever any kind of character is written it is set to true.
  1156. // Whenever the write queue is found to be empty the code that
  1157. // is processing that completing irp will synchonize with the interrupt.
  1158. // If this synchronization code finds that the variable is true and that
  1159. // there is a wait on the transmit queue being empty then it is
  1160. // certain that the queue was emptied and that it has happened since
  1161. // the wait was initiated.
  1162. //
  1163. BOOLEAN EmptiedTransmit;
  1164. //
  1165. // This simply indicates that the port associated with this
  1166. // extension is part of a multiport card.
  1167. //
  1168. BOOLEAN PortOnAMultiportCard;
  1169. //
  1170. // We keep the following values around so that we can connect
  1171. // to the interrupt and report resources after the configuration
  1172. // record is gone.
  1173. //
  1174. //
  1175. // Translated vector
  1176. //
  1177. ULONG Vector;
  1178. //
  1179. // Translated Irql
  1180. //
  1181. KIRQL Irql;
  1182. //
  1183. // Untranslated vector
  1184. //
  1185. ULONG OriginalVector;
  1186. //
  1187. // Untranslated irql
  1188. //
  1189. ULONG OriginalIrql;
  1190. //
  1191. // Address space
  1192. //
  1193. ULONG AddressSpace;
  1194. //
  1195. // Bus number
  1196. //
  1197. ULONG BusNumber;
  1198. //
  1199. // Interface type
  1200. //
  1201. INTERFACE_TYPE InterfaceType;
  1202. //
  1203. // Port index no for multiport devices
  1204. //
  1205. ULONG PortIndex;
  1206. //
  1207. // Indexed flag for multiport devices
  1208. //
  1209. BOOLEAN Indexed;
  1210. //
  1211. // Mask inverted mask for multiport devices
  1212. //
  1213. ULONG MaskInverted;
  1214. //
  1215. // Needed to add new devices to multiport boards
  1216. //
  1217. ULONG NewPortIndex;
  1218. ULONG NewMaskInverted;
  1219. PVOID NewExtension;
  1220. //
  1221. // We hold the character that should be transmitted immediately.
  1222. //
  1223. // Note that we can't use this to determine whether there is
  1224. // a character to send because the character to send could be
  1225. // zero.
  1226. //
  1227. UCHAR ImmediateChar;
  1228. //
  1229. // This holds the mask that will be used to mask off unwanted
  1230. // data bits of the received data (valid data bits can be 5,6,7,8)
  1231. // The mask will normally be 0xff. This is set while the control
  1232. // lock is held since it wouldn't have adverse effects on the
  1233. // isr if it is changed in the middle of reading characters.
  1234. // (What it would do to the app is another question - but then
  1235. // the app asked the driver to do it.)
  1236. //
  1237. UCHAR ValidDataMask;
  1238. //
  1239. // The application can turn on a mode,via the
  1240. // IOCTL_SERIAL_LSRMST_INSERT ioctl, that will cause the
  1241. // serial driver to insert the line status or the modem
  1242. // status into the RX stream. The parameter with the ioctl
  1243. // is a pointer to a UCHAR. If the value of the UCHAR is
  1244. // zero, then no insertion will ever take place. If the
  1245. // value of the UCHAR is non-zero (and not equal to the
  1246. // xon/xoff characters), then the serial driver will insert.
  1247. //
  1248. UCHAR EscapeChar;
  1249. //
  1250. // These two booleans are used to indicate to the isr transmit
  1251. // code that it should send the xon or xoff character. They are
  1252. // only accessed at open and at interrupt level.
  1253. //
  1254. BOOLEAN SendXonChar;
  1255. BOOLEAN SendXoffChar;
  1256. //
  1257. // This boolean will be true if a 16550 is present *and* enabled.
  1258. //
  1259. BOOLEAN FifoPresent;
  1260. //
  1261. // This denotes that this particular port is an on the motherboard
  1262. // port for the Jensen hardware. On these ports the OUT2 bit
  1263. // which is used to enable/disable interrupts is always hight.
  1264. //
  1265. BOOLEAN Jensen;
  1266. //
  1267. // This is the water mark that the rxfifo should be
  1268. // set to when the fifo is turned on. This is not the actual
  1269. // value, but the encoded value that goes into the register.
  1270. //
  1271. UCHAR RxFifoTrigger;
  1272. //
  1273. // Says whether this device can share interrupts with devices
  1274. // other than serial devices.
  1275. //
  1276. BOOLEAN InterruptShareable;
  1277. //
  1278. // Records whether we actually created the symbolic link name
  1279. // at driver load time. If we didn't create it, we won't try
  1280. // to destroy it when we unload.
  1281. //
  1282. BOOLEAN CreatedSymbolicLink;
  1283. //
  1284. // Records whether we actually created an entry in SERIALCOMM
  1285. // at driver load time. If we didn't create it, we won't try
  1286. // to destroy it when the device is removed.
  1287. //
  1288. BOOLEAN CreatedSerialCommEntry;
  1289. //
  1290. // We place all of the kernel and Io subsystem "opaque" structures
  1291. // at the end of the extension. We don't care about their contents.
  1292. //
  1293. //
  1294. // This lock will be used to protect various fields in
  1295. // the extension that are set (& read) in the extension
  1296. // by the io controls.
  1297. //
  1298. KSPIN_LOCK ControlLock;
  1299. //
  1300. // This lock will be used to protect the accept / reject state
  1301. // transitions and flags of the driver It must be acquired
  1302. // before a cancel lock
  1303. //
  1304. KSPIN_LOCK FlagsLock;
  1305. //
  1306. // This points to a DPC used to complete read requests.
  1307. //
  1308. KDPC CompleteWriteDpc;
  1309. //
  1310. // This points to a DPC used to complete read requests.
  1311. //
  1312. KDPC CompleteReadDpc;
  1313. //
  1314. // This dpc is fired off if the timer for the total timeout
  1315. // for the read expires. It will execute a dpc routine that
  1316. // will cause the current read to complete.
  1317. //
  1318. //
  1319. KDPC TotalReadTimeoutDpc;
  1320. //
  1321. // This dpc is fired off if the timer for the interval timeout
  1322. // expires. If no more characters have been read then the
  1323. // dpc routine will cause the read to complete. However, if
  1324. // more characters have been read then the dpc routine will
  1325. // resubmit the timer.
  1326. //
  1327. KDPC IntervalReadTimeoutDpc;
  1328. //
  1329. // This dpc is fired off if the timer for the total timeout
  1330. // for the write expires. It will execute a dpc routine that
  1331. // will cause the current write to complete.
  1332. //
  1333. //
  1334. KDPC TotalWriteTimeoutDpc;
  1335. //
  1336. // This dpc is fired off if a comm error occurs. It will
  1337. // execute a dpc routine that will cancel all pending reads
  1338. // and writes.
  1339. //
  1340. KDPC CommErrorDpc;
  1341. //
  1342. // This dpc is fired off if an event occurs and there was
  1343. // a irp waiting on that event. A dpc routine will execute
  1344. // that completes the irp.
  1345. //
  1346. KDPC CommWaitDpc;
  1347. //
  1348. // This dpc is fired off when the transmit immediate char
  1349. // character is given to the hardware. It will simply complete
  1350. // the irp.
  1351. //
  1352. KDPC CompleteImmediateDpc;
  1353. //
  1354. // This dpc is fired off if the transmit immediate char
  1355. // character times out. The dpc routine will "grab" the
  1356. // irp from the isr and time it out.
  1357. //
  1358. KDPC TotalImmediateTimeoutDpc;
  1359. //
  1360. // This dpc is fired off if the timer used to "timeout" counting
  1361. // the number of characters received after the Xoff ioctl is started
  1362. // expired.
  1363. //
  1364. KDPC XoffCountTimeoutDpc;
  1365. //
  1366. // This dpc is fired off if the xoff counter actually runs down
  1367. // to zero.
  1368. //
  1369. KDPC XoffCountCompleteDpc;
  1370. //
  1371. // This dpc is fired off only from device level to start off
  1372. // a timer that will queue a dpc to check if the RTS line
  1373. // should be lowered when we are doing transmit toggling.
  1374. //
  1375. KDPC StartTimerLowerRTSDpc;
  1376. //
  1377. // This dpc is fired off when a timer expires (after one
  1378. // character time), so that code can be invoked that will
  1379. // check to see if we should lower the RTS line when
  1380. // doing transmit toggling.
  1381. //
  1382. KDPC PerhapsLowerRTSDpc;
  1383. //
  1384. // This DPC is fired to set an event stating that all other
  1385. // DPC's have been finish for this device extension so that
  1386. // paged code may be unlocked.
  1387. //
  1388. KDPC IsrUnlockPagesDpc;
  1389. //
  1390. // This is the kernal timer structure used to handle
  1391. // total read request timing.
  1392. //
  1393. KTIMER ReadRequestTotalTimer;
  1394. //
  1395. // This is the kernal timer structure used to handle
  1396. // interval read request timing.
  1397. //
  1398. KTIMER ReadRequestIntervalTimer;
  1399. //
  1400. // This is the kernal timer structure used to handle
  1401. // total time request timing.
  1402. //
  1403. KTIMER WriteRequestTotalTimer;
  1404. //
  1405. // This is the kernal timer structure used to handle
  1406. // total time request timing.
  1407. //
  1408. KTIMER ImmediateTotalTimer;
  1409. //
  1410. // This timer is used to timeout the xoff counter
  1411. // io.
  1412. //
  1413. KTIMER XoffCountTimer;
  1414. //
  1415. // This timer is used to invoke a dpc one character time
  1416. // after the timer is set. That dpc will be used to check
  1417. // whether we should lower the RTS line if we are doing
  1418. // transmit toggling.
  1419. //
  1420. KTIMER LowerRTSTimer;
  1421. //
  1422. // This is a pointer to the next lower device in the IRP stack.
  1423. //
  1424. PDEVICE_OBJECT LowerDeviceObject;
  1425. //
  1426. // This is where keep track of the power state the device is in.
  1427. //
  1428. DEVICE_POWER_STATE PowerState;
  1429. //
  1430. // Pointer to the driver object
  1431. //
  1432. PDRIVER_OBJECT DriverObject;
  1433. //
  1434. // Event used to do some synchronization with the devices underneath me
  1435. // (namely ACPI)
  1436. //
  1437. KEVENT SerialSyncEvent;
  1438. //
  1439. // String where we keep the symbolic link that is returned to us when we
  1440. // register our device under the COMM class with the Plug and Play manager.
  1441. //
  1442. UNICODE_STRING DeviceClassSymbolicName;
  1443. //
  1444. // Serial ISR switch structure
  1445. //
  1446. PSERIAL_CISR_SW CIsrSw;
  1447. //
  1448. // Count of pending IRP's
  1449. //
  1450. ULONG PendingIRPCnt;
  1451. //
  1452. // Accepting requests?
  1453. //
  1454. ULONG DevicePNPAccept;
  1455. //
  1456. // No IRP's pending event
  1457. //
  1458. KEVENT PendingIRPEvent;
  1459. //
  1460. // PNP State
  1461. //
  1462. ULONG PNPState;
  1463. //
  1464. // Misc Flags
  1465. //
  1466. ULONG Flags;
  1467. //
  1468. // Open count
  1469. //
  1470. LONG OpenCount;
  1471. //
  1472. // Start sync event
  1473. //
  1474. KEVENT SerialStartEvent;
  1475. //
  1476. // Current state during powerdown
  1477. //
  1478. SERIAL_DEVICE_STATE DeviceState;
  1479. //
  1480. // Device stack capabilites
  1481. //
  1482. DEVICE_POWER_STATE DeviceStateMap[PowerSystemMaximum];
  1483. //
  1484. // Event to signal transition to D0 completion
  1485. //
  1486. KEVENT PowerD0Event;
  1487. //
  1488. // List of stalled IRP's
  1489. //
  1490. LIST_ENTRY StalledIrpQueue;
  1491. //
  1492. // Mutex on open status
  1493. //
  1494. FAST_MUTEX OpenMutex;
  1495. //
  1496. // Mutex on close
  1497. //
  1498. FAST_MUTEX CloseMutex;
  1499. //
  1500. // TRUE if we own power policy
  1501. //
  1502. BOOLEAN OwnsPowerPolicy;
  1503. //
  1504. // SystemWake from devcaps
  1505. //
  1506. SYSTEM_POWER_STATE SystemWake;
  1507. //
  1508. // DeviceWake from devcaps
  1509. //
  1510. DEVICE_POWER_STATE DeviceWake;
  1511. //
  1512. // Our PDO
  1513. //
  1514. PDEVICE_OBJECT Pdo;
  1515. //
  1516. // Should we enable wakeup
  1517. //
  1518. BOOLEAN SendWaitWake;
  1519. //
  1520. // Pending wait wake IRP
  1521. //
  1522. PIRP PendingWakeIrp;
  1523. //
  1524. // WMI Information
  1525. //
  1526. WMILIB_CONTEXT WmiLibInfo;
  1527. //
  1528. // Name to use as WMI identifier
  1529. //
  1530. UNICODE_STRING WmiIdentifier;
  1531. //
  1532. // WMI Comm Data
  1533. //
  1534. SERIAL_WMI_COMM_DATA WmiCommData;
  1535. //
  1536. // WMI HW Data
  1537. //
  1538. SERIAL_WMI_HW_DATA WmiHwData;
  1539. //
  1540. // WMI Performance Data
  1541. //
  1542. SERIAL_WMI_PERF_DATA WmiPerfData;
  1543. //
  1544. // Pending DPC count
  1545. //
  1546. ULONG DpcCount;
  1547. //
  1548. // Pending DPC event
  1549. //
  1550. KEVENT PendingDpcEvent;
  1551. //
  1552. // Should we expose external interfaces?
  1553. //
  1554. ULONG SkipNaming;
  1555. #if defined(NEC_98)
  1556. //
  1557. // write data to divisor latch register (for 16550)
  1558. //
  1559. SHORT DivisorLatch16550;
  1560. //
  1561. // write data to modem control register (for 16550)
  1562. //
  1563. UCHAR ModemControl16550;
  1564. //
  1565. // write data to line control register (for 16550)
  1566. //
  1567. UCHAR LineControl16550;
  1568. //
  1569. // out data to mode set register (for 71051)
  1570. //
  1571. UCHAR ModeSet71051;
  1572. //
  1573. // out data to command set register (for 71051)
  1574. //
  1575. UCHAR CommandSet71051;
  1576. #else
  1577. #endif //defined(NEC_98)
  1578. } SERIAL_DEVICE_EXTENSION,*PSERIAL_DEVICE_EXTENSION;
  1579. #define SERIAL_PNPACCEPT_OK 0x0L
  1580. #define SERIAL_PNPACCEPT_REMOVING 0x1L
  1581. #define SERIAL_PNPACCEPT_STOPPING 0x2L
  1582. #define SERIAL_PNPACCEPT_STOPPED 0x4L
  1583. #define SERIAL_PNPACCEPT_SURPRISE_REMOVING 0x8L
  1584. #define SERIAL_PNP_ADDED 0x0L
  1585. #define SERIAL_PNP_STARTED 0x1L
  1586. #define SERIAL_PNP_QSTOP 0x2L
  1587. #define SERIAL_PNP_STOPPING 0x3L
  1588. #define SERIAL_PNP_QREMOVE 0x4L
  1589. #define SERIAL_PNP_REMOVING 0x5L
  1590. #define SERIAL_PNP_RESTARTING 0x6L
  1591. #define SERIAL_FLAGS_CLEAR 0x0L
  1592. #define SERIAL_FLAGS_STARTED 0x1L
  1593. #define SERIAL_FLAGS_STOPPED 0x2L
  1594. #define SERIAL_FLAGS_BROKENHW 0x4L
  1595. //
  1596. // When dealing with a multi-port device (that is possibly
  1597. // daisy chained with other multi-port device), the interrupt
  1598. // service routine will actually be a routine that determines
  1599. // which port on which board is actually causing the interrupt.
  1600. //
  1601. // The following structure is used so that only one device
  1602. // extension will actually need to connect to the interrupt.
  1603. // The following structure which is passed to the interrupt
  1604. // service routine contains the addresses of all of the
  1605. // interrupt status registers (there will be multiple
  1606. // status registers when multi-port cards are chained). It
  1607. // will contain the addresses of all the extensions whose
  1608. // devices are being serviced by this interrupt.
  1609. //
  1610. typedef struct _SERIAL_MULTIPORT_DISPATCH {
  1611. PUCHAR InterruptStatus;
  1612. PSERIAL_DEVICE_EXTENSION Extensions[SERIAL_MAX_PORTS_INDEXED];
  1613. ULONG MaskInverted;
  1614. UCHAR UsablePortMask;
  1615. } SERIAL_MULTIPORT_DISPATCH,*PSERIAL_MULTIPORT_DISPATCH;
  1616. #if defined(NEC_98)
  1617. _inline
  1618. UCHAR
  1619. SerialGetInterruptEnable(
  1620. IN PUCHAR BaseAddress
  1621. )
  1622. {
  1623. UCHAR InterruptEnable = 0;
  1624. UCHAR FifoControl;
  1625. UCHAR FifoInterruptControl;
  1626. FifoControl = READ_PORT_UCHAR(BaseAddress);
  1627. FifoInterruptControl = READ_PORT_UCHAR((PUCHAR)SYSTEM_PORT_C);
  1628. //
  1629. // D3: Modem Status D4:INTERRUPT_ENABLE_REG
  1630. // D2: Receiver Line Status D3:INTERRUPT_ENABLE_REG
  1631. // D1: Transmit Holding Register Empty D2:SYSTEM_PORT_C
  1632. // D0: Received Data Available D0:SYSTEM_PORT_C
  1633. //
  1634. InterruptEnable |= (FifoControl & (MODEM_STATUS_INTERRUPT | LINE_STATUS_INTERRUPT)) >> 1;
  1635. InterruptEnable |= (FifoInterruptControl & TRANSMIT_FIFO_INTERRUPT) >> 1;
  1636. InterruptEnable |= (FifoInterruptControl & RECEIVE_FIFO_INTERRUPT);
  1637. return(InterruptEnable);
  1638. }
  1639. _inline
  1640. UCHAR
  1641. SerialGetLineStatus(
  1642. IN PUCHAR BaseAddress
  1643. )
  1644. {
  1645. UCHAR LineStatus = 0;
  1646. UCHAR FifoStatus;
  1647. FifoStatus = READ_PORT_UCHAR(BaseAddress);
  1648. //
  1649. // D7: Error in Receive FIFO D7:LINE_STATUS_REG
  1650. // D6: Transmitter shift Register empty D0:LINE_STATUS_REG
  1651. // D5: Transmitter holding Register empty D1:LINE_STATUS_REG
  1652. // D4: Break interrupt D6:LINE_STATUS_REG
  1653. // D3: Framing error D5:LINE_STATUS_REG
  1654. // D2: Parity error D3:LINE_STATUS_REG
  1655. // D1: Overrun error D4:LINE_STATUS_REG
  1656. // D0: Receive Data Ready D2:LINE_STATUS_REG
  1657. //
  1658. LineStatus |= (FifoStatus & 0x80); // Error in Receive FIFO
  1659. LineStatus |= (FifoStatus & 0x01) << 6; // Transmitter shift Register empty
  1660. LineStatus |= (FifoStatus & 0x02) << 4; // Transmitter holding Register empty
  1661. LineStatus |= (FifoStatus & 0x40) >> 2; // Break interrupt
  1662. LineStatus |= (FifoStatus & 0x20) >> 2; // Framing error
  1663. LineStatus |= (FifoStatus & 0x08) >> 1; // Parity error
  1664. LineStatus |= (FifoStatus & 0x10) >> 3; // Overrun error
  1665. LineStatus |= (FifoStatus & 0x04) >> 2; // Receive Data Ready
  1666. return(LineStatus);
  1667. }
  1668. #define WRITE_IO_DELAY(Counter) \
  1669. do \
  1670. { \
  1671. ULONG i; \
  1672. for (i = 0; i < Counter; i++) { \
  1673. WRITE_PORT_UCHAR( \
  1674. (PUCHAR)IO_DELAY_REGISTER, \
  1675. IO_DELAY_DATA \
  1676. ); \
  1677. } \
  1678. } while (0)
  1679. /* #define WRITE_PORT_UCHAR(BaseAddress, Value) */ \
  1680. /* do */ \
  1681. /* { */ \
  1682. /* WRITE_PORT_UCHAR(BaseAddress, Value); */ \
  1683. /* WRITE_PORT_UCHAR( */ \
  1684. /* (PUCHAR)IO_DELAY_REGISTER, */ \
  1685. /* IO_DELAY_DATA */ \
  1686. /* ); */ \
  1687. /* } while (0) */
  1688. #define READ_DIVISOR_LATCH(BaseAddress,PDesiredDivisor) \
  1689. do \
  1690. { \
  1691. *PDesiredDivisor = Extension->DivisorLatch16550; \
  1692. } while (0)
  1693. #define READ_INTERRUPT_ENABLE(BaseAddress) \
  1694. (SerialGetInterruptEnable((BaseAddress)+INTERRUPT_ENABLE_REGISTER))
  1695. #define WRITE_INTERRUPT_ENABLE(BaseAddress,Values) \
  1696. do \
  1697. { \
  1698. UCHAR FifoControl = 0; \
  1699. UCHAR FifoInterruptControl = 0; \
  1700. FifoControl = READ_PORT_UCHAR((BaseAddress)+INTERRUPT_ENABLE_REGISTER); \
  1701. if (Values & SERIAL_IER_MS) { \
  1702. FifoControl |= MODEM_STATUS_INTERRUPT; \
  1703. } else { \
  1704. FifoControl &= ~MODEM_STATUS_INTERRUPT; \
  1705. } \
  1706. if (Values & SERIAL_IER_RLS) { \
  1707. FifoControl |= LINE_STATUS_INTERRUPT; \
  1708. } else { \
  1709. FifoControl &= ~LINE_STATUS_INTERRUPT; \
  1710. } \
  1711. WRITE_PORT_UCHAR( \
  1712. (BaseAddress)+INTERRUPT_ENABLE_REGISTER, \
  1713. FifoControl \
  1714. ); \
  1715. FifoInterruptControl = READ_PORT_UCHAR((PUCHAR)SYSTEM_PORT_C); \
  1716. if (Values & SERIAL_IER_THR) { \
  1717. FifoInterruptControl |= TRANSMIT_FIFO_INTERRUPT; \
  1718. } else { \
  1719. FifoInterruptControl &= ~TRANSMIT_FIFO_INTERRUPT; \
  1720. } \
  1721. if (Values & SERIAL_IER_RDA) { \
  1722. FifoInterruptControl |= RECEIVE_FIFO_INTERRUPT; \
  1723. } else { \
  1724. FifoInterruptControl &= ~RECEIVE_FIFO_INTERRUPT; \
  1725. } \
  1726. WRITE_PORT_UCHAR( \
  1727. (PUCHAR)SYSTEM_PORT_C, \
  1728. FifoInterruptControl \
  1729. ); \
  1730. } while (0)
  1731. #define DISABLE_ALL_INTERRUPTS(BaseAddress) \
  1732. do \
  1733. { \
  1734. WRITE_INTERRUPT_ENABLE(BaseAddress,0); \
  1735. } while (0)
  1736. #define ENABLE_ALL_INTERRUPTS(BaseAddress) \
  1737. do \
  1738. { \
  1739. \
  1740. WRITE_INTERRUPT_ENABLE( \
  1741. (BaseAddress), \
  1742. (UCHAR)(SERIAL_IER_RDA | SERIAL_IER_THR | \
  1743. SERIAL_IER_RLS | SERIAL_IER_MS) \
  1744. ); \
  1745. \
  1746. } while (0)
  1747. #define READ_INTERRUPT_ID_REG(BaseAddress) \
  1748. (((READ_PORT_UCHAR((BaseAddress)+INTERRUPT_IDENT_REGISTER)) & 0x0f) | SERIAL_IIR_FIFOS_ENABLED)
  1749. #define READ_MODEM_CONTROL(BaseAddress) \
  1750. (Extension->ModemControl16550)
  1751. #define READ_MODEM_STATUS(BaseAddress) \
  1752. (READ_PORT_UCHAR((BaseAddress)+MODEM_STATUS_REGISTER))
  1753. #define READ_RECEIVE_BUFFER(BaseAddress) \
  1754. (READ_PORT_UCHAR((BaseAddress)+RECEIVE_BUFFER_REGISTER))
  1755. #define READ_LINE_STATUS(BaseAddress) \
  1756. (SerialGetLineStatus((BaseAddress)+LINE_STATUS_REGISTER))
  1757. #define READ_LINE_CONTROL(BaseAddress) \
  1758. (Extension->LineControl16550)
  1759. #define WRITE_TRANSMIT_HOLDING(BaseAddress,TransmitChar) \
  1760. do \
  1761. { \
  1762. WRITE_PORT_UCHAR( \
  1763. (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \
  1764. (TransmitChar) \
  1765. ); \
  1766. } while (0)
  1767. #define WRITE_TRANSMIT_FIFO_HOLDING(BaseAddress,TransmitChars,TxN) \
  1768. do \
  1769. { \
  1770. PUCHAR TransmitBuffer = TransmitChars; \
  1771. ULONG i; \
  1772. for (i = 0; i < TxN; i++, TransmitBuffer++) { \
  1773. WRITE_PORT_UCHAR( \
  1774. (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \
  1775. (UCHAR)(*TransmitBuffer) \
  1776. ); \
  1777. } \
  1778. } while (0)
  1779. #define ENTER_LEGACY_MODE(BaseAddress, InterruptEnable, FifoControl) \
  1780. do \
  1781. { \
  1782. *InterruptEnable = READ_INTERRUPT_ENABLE(BaseAddress); \
  1783. DISABLE_ALL_INTERRUPTS(BaseAddress); \
  1784. *FifoControl = READ_PORT_UCHAR((BaseAddress)+FIFO_CONTROL_REGISTER); \
  1785. WRITE_PORT_UCHAR( \
  1786. (BaseAddress)+FIFO_CONTROL_REGISTER, \
  1787. DISABLE_FIFO_MODE \
  1788. ); \
  1789. } while (0)
  1790. #define EXIT_LEGACY_MODE(BaseAddress, InterruptEnable, FifoControl) \
  1791. do \
  1792. { \
  1793. WRITE_PORT_UCHAR( \
  1794. (BaseAddress)+FIFO_CONTROL_REGISTER, \
  1795. (UCHAR)(*FifoControl) \
  1796. ); \
  1797. WRITE_INTERRUPT_ENABLE( \
  1798. (BaseAddress), \
  1799. (UCHAR)(*InterruptEnable) \
  1800. ); \
  1801. } while (0)
  1802. #define RESET_71051(ModeSet) \
  1803. do \
  1804. { \
  1805. WRITE_PORT_UCHAR((PUCHAR)COMMAND_SET, (UCHAR)0); \
  1806. WRITE_IO_DELAY(1); \
  1807. WRITE_PORT_UCHAR((PUCHAR)COMMAND_SET, (UCHAR)0); \
  1808. WRITE_IO_DELAY(1); \
  1809. WRITE_PORT_UCHAR((PUCHAR)COMMAND_SET, (UCHAR)0); \
  1810. WRITE_IO_DELAY(1); \
  1811. WRITE_PORT_UCHAR((PUCHAR)COMMAND_SET, COMMAND_ERROR_RESET); \
  1812. WRITE_IO_DELAY(2); \
  1813. WRITE_PORT_UCHAR( \
  1814. (PUCHAR)MODE_SET, \
  1815. (ModeSet) \
  1816. ); \
  1817. WRITE_IO_DELAY(1); \
  1818. WRITE_PORT_UCHAR( \
  1819. (PUCHAR)COMMAND_SET, \
  1820. (UCHAR)Extension->CommandSet71051 \
  1821. ); \
  1822. WRITE_IO_DELAY(1); \
  1823. } while (0)
  1824. #define WRITE_DIVISOR_LATCH(BaseAddress,DesiredDivisor) \
  1825. do \
  1826. { \
  1827. PUCHAR Address = BaseAddress; \
  1828. SHORT Divisor = DesiredDivisor; \
  1829. ULONG denominator; \
  1830. LONG DesiredBaud; \
  1831. UCHAR InterruptControl = 0; \
  1832. UCHAR FifoControl = 0; \
  1833. Extension->DivisorLatch16550 = Divisor; \
  1834. denominator = 1843200 / Divisor; \
  1835. DesiredBaud = denominator / (ULONG)16; \
  1836. ENTER_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1837. if (DesiredBaud < 9600) { \
  1838. /* V.Fast mode -> 98 mode */ \
  1839. WRITE_PORT_UCHAR( \
  1840. (BaseAddress)+VFAST_BAUDCLK_REGISTER, \
  1841. (UCHAR)VFAST_DISABLE \
  1842. ); \
  1843. /* Baud rate set on 98 mode */ \
  1844. Divisor = (SHORT)(153600 / DesiredBaud); \
  1845. WRITE_PORT_UCHAR( \
  1846. (PUCHAR)TIMER_MODE_REGISTER, \
  1847. TIMER_DEFAULT_CONTROL \
  1848. ); \
  1849. WRITE_PORT_UCHAR( \
  1850. (PUCHAR)TIMER_COUNT_REGISTER, \
  1851. (UCHAR)(Divisor & 0xff) \
  1852. ); \
  1853. WRITE_PORT_UCHAR( \
  1854. (PUCHAR)TIMER_COUNT_REGISTER, \
  1855. (UCHAR)((Divisor & 0xff00) >> 8) \
  1856. ); \
  1857. } else { \
  1858. /* RS syncronize clock TXC prohibit */ \
  1859. WRITE_PORT_UCHAR( \
  1860. (PUCHAR)CONFIG_INDEX_REGISTER, \
  1861. TRANSFER_CLOCK_ENABLE_ADDRESS \
  1862. ); \
  1863. WRITE_PORT_UCHAR( \
  1864. (PUCHAR)CONFIG_DATA_REGISTER, \
  1865. TXC_PROHIBIT \
  1866. ); \
  1867. /* 98 mode -> V.Fast mode, and Baud rate set */ \
  1868. switch (DesiredBaud) { \
  1869. case 9600: Divisor = VFAST_BAUD_9600; \
  1870. break; \
  1871. case 19200: Divisor = VFAST_BAUD_19200; \
  1872. break; \
  1873. case 38400: Divisor = VFAST_BAUD_38400; \
  1874. break; \
  1875. case 57600: Divisor = VFAST_BAUD_57600; \
  1876. break; \
  1877. case 115200: Divisor = VFAST_BAUD_115200; \
  1878. } \
  1879. WRITE_PORT_UCHAR( \
  1880. (BaseAddress)+VFAST_BAUDCLK_REGISTER, \
  1881. (UCHAR)(Divisor | VFAST_ENABLE) \
  1882. ); \
  1883. } \
  1884. RESET_71051(Extension->ModeSet71051); \
  1885. EXIT_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1886. if (DesiredBaud < 9600) { \
  1887. /* RS syncronize clock TXC permit */ \
  1888. WRITE_PORT_UCHAR( \
  1889. (PUCHAR)CONFIG_INDEX_REGISTER, \
  1890. TRANSFER_CLOCK_ENABLE_ADDRESS \
  1891. ); \
  1892. WRITE_PORT_UCHAR( \
  1893. (PUCHAR)CONFIG_DATA_REGISTER, \
  1894. TXC_PERMIT \
  1895. ); \
  1896. } \
  1897. } while (0)
  1898. #define WRITE_LINE_CONTROL(BaseAddress,NewLineControl) \
  1899. do \
  1900. { \
  1901. UCHAR InterruptControl = 0; \
  1902. UCHAR FifoControl = 0; \
  1903. UCHAR OutLineControl = BAUDRATE_DEFAULT_MODE; \
  1904. ENTER_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1905. /* character length */ \
  1906. OutLineControl |= (NewLineControl & SERIAL_DATA_MASK) << 2; \
  1907. /* parity enable and parity mode */ \
  1908. OutLineControl |= (NewLineControl & SER71051_PARITY_MASK) << 1; \
  1909. /* stop bit */ \
  1910. if (NewLineControl & SERIAL_STOP_MASK) { \
  1911. if (NewLineControl & SERIAL_DATA_MASK) { \
  1912. OutLineControl |= SER71051_1_5_STOP; \
  1913. } else { \
  1914. OutLineControl |= SER71051_2_STOP; \
  1915. } \
  1916. } else { \
  1917. OutLineControl |= SER71051_1_STOP; \
  1918. } \
  1919. Extension->ModeSet71051 = OutLineControl; \
  1920. RESET_71051(OutLineControl); \
  1921. /* break character */ \
  1922. if (NewLineControl & SERIAL_LCR_BREAK) { \
  1923. if (!(Extension->LineControl16550 & SERIAL_LCR_BREAK)) { \
  1924. Extension->CommandSet71051 |= SER71051_SEND_BREAK; \
  1925. WRITE_PORT_UCHAR( \
  1926. (PUCHAR)COMMAND_SET, \
  1927. (UCHAR)Extension->CommandSet71051 \
  1928. ); \
  1929. } \
  1930. } else { \
  1931. if (Extension->LineControl16550 & SERIAL_LCR_BREAK) { \
  1932. Extension->CommandSet71051 &= ~SER71051_SEND_BREAK; \
  1933. WRITE_PORT_UCHAR( \
  1934. (PUCHAR)COMMAND_SET, \
  1935. (UCHAR)Extension->CommandSet71051 \
  1936. ); \
  1937. } \
  1938. } \
  1939. Extension->LineControl16550 = NewLineControl; \
  1940. EXIT_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1941. } while (0)
  1942. #define WRITE_FIFO_CONTROL(BaseAddress,ControlValue) \
  1943. do \
  1944. { \
  1945. UCHAR InterruptControl = 0; \
  1946. UCHAR FifoControl = 0; \
  1947. UCHAR OutValue = ControlValue; \
  1948. ENTER_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1949. OutValue &= ~(MODEM_STATUS_INTERRUPT | LINE_STATUS_INTERRUPT); \
  1950. WRITE_PORT_UCHAR( \
  1951. (BaseAddress)+FIFO_CONTROL_REGISTER, \
  1952. (OutValue) \
  1953. ); \
  1954. FifoControl = READ_PORT_UCHAR((BaseAddress)+FIFO_CONTROL_REGISTER); \
  1955. /* always Fifo mode on PC98 */ \
  1956. FifoControl |= SERIAL_FCR_ENABLE; \
  1957. EXIT_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1958. } while (0)
  1959. #define WRITE_MODEM_CONTROL(BaseAddress,ModemControl) \
  1960. do \
  1961. { \
  1962. UCHAR InterruptControl = 0; \
  1963. UCHAR FifoControl = 0; \
  1964. /* command default:ER, RXE, TxE -> ON */ \
  1965. UCHAR CommandSet = COMMAND_DEFAULT_SET; \
  1966. Extension->ModemControl16550 = ModemControl; \
  1967. ENTER_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1968. CommandSet |= (ModemControl & SERIAL_MCR_DTR) << 1; \
  1969. CommandSet |= (ModemControl & SERIAL_MCR_RTS) << 4; \
  1970. Extension->CommandSet71051 = CommandSet; \
  1971. WRITE_PORT_UCHAR( \
  1972. (PUCHAR)COMMAND_SET, \
  1973. (CommandSet) \
  1974. ); \
  1975. EXIT_LEGACY_MODE(BaseAddress, &InterruptControl, &FifoControl); \
  1976. } while (0)
  1977. #else
  1978. //
  1979. // Sets the divisor latch register. The divisor latch register
  1980. // is used to control the baud rate of the 8250.
  1981. //
  1982. // As with all of these routines it is assumed that it is called
  1983. // at a safe point to access the hardware registers. In addition
  1984. // it also assumes that the data is correct.
  1985. //
  1986. // Arguments:
  1987. //
  1988. // BaseAddress - A pointer to the address from which the hardware
  1989. // device registers are located.
  1990. //
  1991. // DesiredDivisor - The value to which the divisor latch register should
  1992. // be set.
  1993. //
  1994. #define WRITE_DIVISOR_LATCH(BaseAddress,DesiredDivisor) \
  1995. do \
  1996. { \
  1997. PUCHAR Address = BaseAddress; \
  1998. SHORT Divisor = DesiredDivisor; \
  1999. UCHAR LineControl; \
  2000. LineControl = READ_PORT_UCHAR(Address+LINE_CONTROL_REGISTER); \
  2001. WRITE_PORT_UCHAR( \
  2002. Address+LINE_CONTROL_REGISTER, \
  2003. (UCHAR)(LineControl | SERIAL_LCR_DLAB) \
  2004. ); \
  2005. WRITE_PORT_UCHAR( \
  2006. Address+DIVISOR_LATCH_LSB, \
  2007. (UCHAR)(Divisor & 0xff) \
  2008. ); \
  2009. WRITE_PORT_UCHAR( \
  2010. Address+DIVISOR_LATCH_MSB, \
  2011. (UCHAR)((Divisor & 0xff00) >> 8) \
  2012. ); \
  2013. WRITE_PORT_UCHAR( \
  2014. Address+LINE_CONTROL_REGISTER, \
  2015. LineControl \
  2016. ); \
  2017. } while (0)
  2018. //
  2019. // Reads the divisor latch register. The divisor latch register
  2020. // is used to control the baud rate of the 8250.
  2021. //
  2022. // As with all of these routines it is assumed that it is called
  2023. // at a safe point to access the hardware registers. In addition
  2024. // it also assumes that the data is correct.
  2025. //
  2026. // Arguments:
  2027. //
  2028. // BaseAddress - A pointer to the address from which the hardware
  2029. // device registers are located.
  2030. //
  2031. // DesiredDivisor - A pointer to the 2 byte word which will contain
  2032. // the value of the divisor.
  2033. //
  2034. #define READ_DIVISOR_LATCH(BaseAddress,PDesiredDivisor) \
  2035. do \
  2036. { \
  2037. PUCHAR Address = BaseAddress; \
  2038. PSHORT PDivisor = PDesiredDivisor; \
  2039. UCHAR LineControl; \
  2040. UCHAR Lsb; \
  2041. UCHAR Msb; \
  2042. LineControl = READ_PORT_UCHAR(Address+LINE_CONTROL_REGISTER); \
  2043. WRITE_PORT_UCHAR( \
  2044. Address+LINE_CONTROL_REGISTER, \
  2045. (UCHAR)(LineControl | SERIAL_LCR_DLAB) \
  2046. ); \
  2047. Lsb = READ_PORT_UCHAR(Address+DIVISOR_LATCH_LSB); \
  2048. Msb = READ_PORT_UCHAR(Address+DIVISOR_LATCH_MSB); \
  2049. *PDivisor = Lsb; \
  2050. *PDivisor = *PDivisor | (((USHORT)Msb) << 8); \
  2051. WRITE_PORT_UCHAR( \
  2052. Address+LINE_CONTROL_REGISTER, \
  2053. LineControl \
  2054. ); \
  2055. } while (0)
  2056. //
  2057. // This macro reads the interrupt enable register.
  2058. //
  2059. // Arguments:
  2060. //
  2061. // BaseAddress - A pointer to the address from which the hardware
  2062. // device registers are located.
  2063. //
  2064. #define READ_INTERRUPT_ENABLE(BaseAddress) \
  2065. (READ_PORT_UCHAR((BaseAddress)+INTERRUPT_ENABLE_REGISTER))
  2066. //
  2067. // This macro writes the interrupt enable register.
  2068. //
  2069. // Arguments:
  2070. //
  2071. // BaseAddress - A pointer to the address from which the hardware
  2072. // device registers are located.
  2073. //
  2074. // Values - The values to write to the interrupt enable register.
  2075. //
  2076. #define WRITE_INTERRUPT_ENABLE(BaseAddress,Values) \
  2077. do \
  2078. { \
  2079. WRITE_PORT_UCHAR( \
  2080. BaseAddress+INTERRUPT_ENABLE_REGISTER, \
  2081. Values \
  2082. ); \
  2083. } while (0)
  2084. //
  2085. // This macro disables all interrupts on the hardware.
  2086. //
  2087. // Arguments:
  2088. //
  2089. // BaseAddress - A pointer to the address from which the hardware
  2090. // device registers are located.
  2091. //
  2092. //
  2093. #define DISABLE_ALL_INTERRUPTS(BaseAddress) \
  2094. do \
  2095. { \
  2096. WRITE_INTERRUPT_ENABLE(BaseAddress,0); \
  2097. } while (0)
  2098. //
  2099. // This macro enables all interrupts on the hardware.
  2100. //
  2101. // Arguments:
  2102. //
  2103. // BaseAddress - A pointer to the address from which the hardware
  2104. // device registers are located.
  2105. //
  2106. //
  2107. #define ENABLE_ALL_INTERRUPTS(BaseAddress) \
  2108. do \
  2109. { \
  2110. \
  2111. WRITE_INTERRUPT_ENABLE( \
  2112. (BaseAddress), \
  2113. (UCHAR)(SERIAL_IER_RDA | SERIAL_IER_THR | \
  2114. SERIAL_IER_RLS | SERIAL_IER_MS) \
  2115. ); \
  2116. \
  2117. } while (0)
  2118. //
  2119. // This macro reads the interrupt identification register
  2120. //
  2121. // Arguments:
  2122. //
  2123. // BaseAddress - A pointer to the address from which the hardware
  2124. // device registers are located.
  2125. //
  2126. // Note that this routine potententially quites a transmitter
  2127. // empty interrupt. This is because one way that the transmitter
  2128. // empty interrupt is cleared is to simply read the interrupt id
  2129. // register.
  2130. //
  2131. //
  2132. #define READ_INTERRUPT_ID_REG(BaseAddress) \
  2133. (READ_PORT_UCHAR((BaseAddress)+INTERRUPT_IDENT_REGISTER))
  2134. //
  2135. // This macro reads the modem control register
  2136. //
  2137. // Arguments:
  2138. //
  2139. // BaseAddress - A pointer to the address from which the hardware
  2140. // device registers are located.
  2141. //
  2142. //
  2143. #define READ_MODEM_CONTROL(BaseAddress) \
  2144. (READ_PORT_UCHAR((BaseAddress)+MODEM_CONTROL_REGISTER))
  2145. //
  2146. // This macro reads the modem status register
  2147. //
  2148. // Arguments:
  2149. //
  2150. // BaseAddress - A pointer to the address from which the hardware
  2151. // device registers are located.
  2152. //
  2153. //
  2154. #define READ_MODEM_STATUS(BaseAddress) \
  2155. (READ_PORT_UCHAR((BaseAddress)+MODEM_STATUS_REGISTER))
  2156. //
  2157. // This macro reads a value out of the receive buffer
  2158. //
  2159. // Arguments:
  2160. //
  2161. // BaseAddress - A pointer to the address from which the hardware
  2162. // device registers are located.
  2163. //
  2164. //
  2165. #define READ_RECEIVE_BUFFER(BaseAddress) \
  2166. (READ_PORT_UCHAR((BaseAddress)+RECEIVE_BUFFER_REGISTER))
  2167. //
  2168. // This macro reads the line status register
  2169. //
  2170. // Arguments:
  2171. //
  2172. // BaseAddress - A pointer to the address from which the hardware
  2173. // device registers are located.
  2174. //
  2175. //
  2176. #define READ_LINE_STATUS(BaseAddress) \
  2177. (READ_PORT_UCHAR((BaseAddress)+LINE_STATUS_REGISTER))
  2178. //
  2179. // This macro writes the line control register
  2180. //
  2181. // Arguments:
  2182. //
  2183. // BaseAddress - A pointer to the address from which the hardware
  2184. // device registers are located.
  2185. //
  2186. //
  2187. #define WRITE_LINE_CONTROL(BaseAddress,NewLineControl) \
  2188. do \
  2189. { \
  2190. WRITE_PORT_UCHAR( \
  2191. (BaseAddress)+LINE_CONTROL_REGISTER, \
  2192. (NewLineControl) \
  2193. ); \
  2194. } while (0)
  2195. //
  2196. // This macro reads the line control register
  2197. //
  2198. // Arguments:
  2199. //
  2200. // BaseAddress - A pointer to the address from which the hardware
  2201. // device registers are located.
  2202. //
  2203. //
  2204. #define READ_LINE_CONTROL(BaseAddress) \
  2205. (READ_PORT_UCHAR((BaseAddress)+LINE_CONTROL_REGISTER))
  2206. //
  2207. // This macro writes to the transmit register
  2208. //
  2209. // Arguments:
  2210. //
  2211. // BaseAddress - A pointer to the address from which the hardware
  2212. // device registers are located.
  2213. //
  2214. // TransmitChar - The character to send down the wire.
  2215. //
  2216. //
  2217. #define WRITE_TRANSMIT_HOLDING(BaseAddress,TransmitChar) \
  2218. do \
  2219. { \
  2220. WRITE_PORT_UCHAR( \
  2221. (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \
  2222. (TransmitChar) \
  2223. ); \
  2224. } while (0)
  2225. //
  2226. // This macro writes to the transmit FIFO register
  2227. //
  2228. // Arguments:
  2229. //
  2230. // BaseAddress - A pointer to the address from which the hardware
  2231. // device registers are located.
  2232. //
  2233. // TransmitChars - Pointer to the characters to send down the wire.
  2234. //
  2235. // TxN - number of charactes to send.
  2236. //
  2237. //
  2238. #define WRITE_TRANSMIT_FIFO_HOLDING(BaseAddress,TransmitChars,TxN) \
  2239. do \
  2240. { \
  2241. WRITE_PORT_BUFFER_UCHAR( \
  2242. (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \
  2243. (TransmitChars), \
  2244. (TxN) \
  2245. ); \
  2246. } while (0)
  2247. //
  2248. // This macro writes to the control register
  2249. //
  2250. // Arguments:
  2251. //
  2252. // BaseAddress - A pointer to the address from which the hardware
  2253. // device registers are located.
  2254. //
  2255. // ControlValue - The value to set the fifo control register too.
  2256. //
  2257. //
  2258. #define WRITE_FIFO_CONTROL(BaseAddress,ControlValue) \
  2259. do \
  2260. { \
  2261. WRITE_PORT_UCHAR( \
  2262. (BaseAddress)+FIFO_CONTROL_REGISTER, \
  2263. (ControlValue) \
  2264. ); \
  2265. } while (0)
  2266. //
  2267. // This macro writes to the modem control register
  2268. //
  2269. // Arguments:
  2270. //
  2271. // BaseAddress - A pointer to the address from which the hardware
  2272. // device registers are located.
  2273. //
  2274. // ModemControl - The control bits to send to the modem control.
  2275. //
  2276. //
  2277. #define WRITE_MODEM_CONTROL(BaseAddress,ModemControl) \
  2278. do \
  2279. { \
  2280. WRITE_PORT_UCHAR( \
  2281. (BaseAddress)+MODEM_CONTROL_REGISTER, \
  2282. (ModemControl) \
  2283. ); \
  2284. } while (0)
  2285. #endif //defined(NEC_98)
  2286. //
  2287. // We use this to query into the registry as to whether we
  2288. // should break at driver entry.
  2289. //
  2290. extern SERIAL_FIRMWARE_DATA driverDefaults;
  2291. //
  2292. // This is exported from the kernel. It is used to point
  2293. // to the address that the kernel debugger is using.
  2294. //
  2295. extern PUCHAR *KdComPortInUse;
  2296. typedef enum _SERIAL_MEM_COMPARES {
  2297. AddressesAreEqual,
  2298. AddressesOverlap,
  2299. AddressesAreDisjoint
  2300. } SERIAL_MEM_COMPARES,*PSERIAL_MEM_COMPARES;
  2301. typedef struct _SERIAL_LIST_DATA {
  2302. PLIST_ENTRY destList;
  2303. PLIST_ENTRY newElement;
  2304. } SERIAL_LIST_DATA, *PSERIAL_LIST_DATA;
  2305. typedef struct _SERIAL_GLOBALS {
  2306. LIST_ENTRY AllDevObjs;
  2307. PVOID PAGESER_Handle;
  2308. UNICODE_STRING RegistryPath;
  2309. #if DBG
  2310. ULONG PAGESER_Count;
  2311. #endif // DBG
  2312. } SERIAL_GLOBALS, *PSERIAL_GLOBALS;
  2313. extern SERIAL_GLOBALS SerialGlobals;
  2314. typedef struct _SERIAL_USER_DATA {
  2315. PHYSICAL_ADDRESS UserPort;
  2316. PHYSICAL_ADDRESS UserInterruptStatus;
  2317. ULONG UserVector;
  2318. UNICODE_STRING UserSymbolicLink;
  2319. ULONG UserPortIndex;
  2320. ULONG UserBusNumber;
  2321. ULONG UserInterfaceType;
  2322. ULONG UserClockRate;
  2323. ULONG UserIndexed;
  2324. ULONG UserInterruptMode;
  2325. ULONG UserAddressSpace;
  2326. ULONG UserLevel;
  2327. ULONG DefaultPermitSystemWideShare;
  2328. ULONG DisablePort;
  2329. ULONG RxFIFO;
  2330. ULONG RxFIFODefault;
  2331. ULONG TxFIFO;
  2332. ULONG TxFIFODefault;
  2333. ULONG ForceFIFOEnable;
  2334. ULONG ForceFIFOEnableDefault;
  2335. ULONG PermitShareDefault;
  2336. ULONG LogFIFODefault;
  2337. ULONG MaskInverted;
  2338. } SERIAL_USER_DATA, *PSERIAL_USER_DATA;
  2339. typedef struct _SERIAL_PTR_CTX {
  2340. ULONG isPointer;
  2341. PHYSICAL_ADDRESS Port;
  2342. ULONG Vector;
  2343. } SERIAL_PTR_CTX, *PSERIAL_PTR_CTX;
  2344. #define DEVICE_OBJECT_NAME_LENGTH 128
  2345. #define SYMBOLIC_NAME_LENGTH 128
  2346. #define SERIAL_PNP_ID_STR L"*PNP0501"
  2347. #define SERIAL_PNP_MULTI_ID_STR L"*PNP0502"
  2348. #define SERIAL_DEVICE_MAP L"SERIALCOMM"
  2349. //
  2350. // Return values for mouse detection callback
  2351. //
  2352. #define SERIAL_FOUNDPOINTER_PORT 1
  2353. #define SERIAL_FOUNDPOINTER_VECTOR 2
  2354. #define SerialCompleteRequest(PDevExt, PIrp, PriBoost) \
  2355. { \
  2356. IoCompleteRequest((PIrp), (PriBoost)); \
  2357. SerialIRPEpilogue((PDevExt)); \
  2358. }
  2359. #define SERIAL_WMI_GUID_LIST_SIZE 5
  2360. extern WMIGUIDREGINFO SerialWmiGuidList[SERIAL_WMI_GUID_LIST_SIZE];