Windows NT 4.0 source code leak
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.

338 lines
8.7 KiB

4 years ago
  1. /*
  2. * vidcio.c
  3. *
  4. * 32-bit Video Capture driver
  5. *
  6. * chip register access functions for Bravado card
  7. *
  8. * Geraint Davies, Feb 93
  9. */
  10. #include <vckernel.h>
  11. #include <bravado.h>
  12. #include "hardware.h"
  13. #include "vidcio.h"
  14. /*
  15. * the vckernel library does not synchronise calls to the
  16. * InterruptAcknowledge or CaptureService functions with calls to the
  17. * other h/w callbacks (all the other callback functions are synchronised
  18. * with each other).
  19. *
  20. * The interrupt ack function does not do much, but it does access the
  21. * PCVideo chip, and thus could change the index register between a write to
  22. * the index reg and a write to the data.
  23. * Thus we need to sync calls to functions in this module with
  24. * the interrupt. We do this using the vckernel wrapper function
  25. * VC_SynchronizeExecution - on NT this will be a call to KeSynchronizeExecution,
  26. * and on Win-16 this would be a disable-interrupt.
  27. *
  28. * Calls to HW_SetPCVideoReg, HW_Set9051Reg, HW_Set4680Reg and HW_GetPCVideoReg
  29. * thus package up their arguments and call this function: this function
  30. * will disable the interrupts as appropriate and call back to
  31. * the relevant HW_Set*Reg_Sync function to do the operation.
  32. *
  33. */
  34. /* -- forward declarations -------------------------------------------------*/
  35. BOOLEAN HW_Set9051Reg_Sync(PSYNC_REG_ARG);
  36. BOOLEAN HW_Set4680Reg_Sync(PSYNC_REG_ARG);
  37. BOOLEAN HW_SetPCVideoReg_Sync(PSYNC_REG_ARG);
  38. BOOLEAN HW_GetPCVideoReg_Sync(PSYNC_REG_ARG);
  39. /* -- external functions --------------------------------------------------*/
  40. VOID
  41. HW_Set9051Reg(PDEVICE_INFO pDevInfo, BYTE bRegister, BYTE bData)
  42. {
  43. SYNC_REG_ARG SyncArg;
  44. if (bRegister > NR_REG_9051) {
  45. dprintf(("bad register nr for 9051"));
  46. return;
  47. }
  48. SyncArg.pDevInfo = pDevInfo;
  49. SyncArg.bRegister = bRegister;
  50. SyncArg.bData = bData;
  51. VC_SynchronizeExecution(pDevInfo, (PSYNC_ROUTINE) HW_Set9051Reg_Sync, &SyncArg);
  52. }
  53. VOID
  54. HW_Set4680Reg(PDEVICE_INFO pDevInfo, BYTE bRegister, BYTE bData)
  55. {
  56. SYNC_REG_ARG SyncArg;
  57. if (bRegister > NR_REG_4680) {
  58. dprintf(("bad register nr for 4680"));
  59. return;
  60. }
  61. SyncArg.pDevInfo = pDevInfo;
  62. SyncArg.bRegister = bRegister;
  63. SyncArg.bData = bData;
  64. VC_SynchronizeExecution(pDevInfo, (PSYNC_ROUTINE) HW_Set4680Reg_Sync, &SyncArg);
  65. }
  66. /*
  67. * set a register on the main PCVideo chip
  68. */
  69. VOID HW_SetPCVideoReg(PDEVICE_INFO pDevInfo, BYTE bRegister, BYTE bData)
  70. {
  71. SYNC_REG_ARG SyncArg;
  72. SyncArg.pDevInfo = pDevInfo;
  73. SyncArg.bRegister = bRegister;
  74. SyncArg.bData = bData;
  75. VC_SynchronizeExecution(pDevInfo, (PSYNC_ROUTINE) HW_SetPCVideoReg_Sync, &SyncArg);
  76. }
  77. /* get back the value of a PCVideo register */
  78. BYTE
  79. HW_GetPCVideoReg(PDEVICE_INFO pDevInfo, BYTE bRegister)
  80. {
  81. SYNC_REG_ARG SyncArg;
  82. SyncArg.pDevInfo = pDevInfo;
  83. SyncArg.bRegister = bRegister;
  84. VC_SynchronizeExecution(pDevInfo, (PSYNC_ROUTINE) HW_GetPCVideoReg_Sync, &SyncArg);
  85. return(SyncArg.bData);
  86. }
  87. /*--- internal device-access functions ------------------------------*/
  88. /*
  89. * all the devices on the board with the exception of the PCVideo chip
  90. * are accessed via the I2C bus. This is a 1-bit serial bus, so for
  91. * each output we need to individually clock out onto the bus one
  92. * bit at a time a master(device) address, a sub address (the device reg) and
  93. * the data
  94. *
  95. * We put the data onto the data bit with the clock low, and then set the
  96. * clock high. The data must be stable during clock-high, except for start bits
  97. * and stop bits. A data high-to-low transition during clock-high is a
  98. * start bit, and a data low-to-high transition during clock-high is a stop bit.
  99. *
  100. * An output sequence consists of a start bit, three bytes (chip address,
  101. * register address and data) and then a stop bit. Each of the three bytes
  102. * is sent msb first, and is followed by an immediate ack bit before the
  103. * next byte starts.
  104. *
  105. * For efficiency, we set the PCV_INDEX register to point to the
  106. * I2C control register once at the start of the sequence.
  107. */
  108. typedef enum _i2c_types {ClockBit, DataBit} i2c_types;
  109. /*
  110. * this function writes one clock or data bit onto the I2C bus
  111. */
  112. VOID
  113. HW_WriteI2C(PDEVICE_INFO pDevInfo, i2c_types type, BOOL bData)
  114. {
  115. /* assume I2C control register selected on PCV */
  116. if (type == ClockBit) {
  117. VC_Out(pDevInfo, PCV_DATA,
  118. (BYTE) ((VC_In(pDevInfo, PCV_DATA) & 0xfe) | (bData ? 1 : 0)));
  119. } else {
  120. VC_Out(pDevInfo, PCV_DATA,
  121. (BYTE) ((VC_In(pDevInfo, PCV_DATA) & 0xfd) | (bData ? 0x2 : 0)));
  122. }
  123. }
  124. /*
  125. * read back the value of the clock or data bit
  126. */
  127. UINT HW_ReadI2C(PDEVICE_INFO pDevInfo, i2c_types type)
  128. {
  129. UINT uVal;
  130. /* assume I2C control regiseter selected on PCV */
  131. uVal = VC_In(pDevInfo, PCV_DATA);
  132. if (type == ClockBit) {
  133. return(uVal & 0x1);
  134. } else {
  135. return((uVal >> 1) & 0x1);
  136. }
  137. }
  138. /*
  139. * clock one whole byte onto the I2C bus not including start or stop
  140. * bits (since these are sent round a whole transmission, not each byte)
  141. *
  142. */
  143. void HW_ByteToI2C(PDEVICE_INFO pDevInfo, BYTE bData)
  144. {
  145. int i;
  146. /* write each bit, MSB first.
  147. * fortunately HW_WriteI2C takes a BOOL to save us the trouble
  148. * of reversing the bits
  149. */
  150. for (i = 0; i < 8; i++, bData <<= 1) {
  151. /* write data bit */
  152. HW_WriteI2C(pDevInfo, DataBit, bData & 0x80);
  153. /* turn clock on and off */
  154. HW_WriteI2C(pDevInfo, ClockBit, TRUE);
  155. KeStallExecutionProcessor(5);
  156. HW_WriteI2C(pDevInfo, ClockBit, FALSE);
  157. KeStallExecutionProcessor(4);
  158. }
  159. /* ack sequence */
  160. HW_WriteI2C(pDevInfo, DataBit, TRUE);
  161. HW_WriteI2C(pDevInfo, ClockBit, TRUE);
  162. KeStallExecutionProcessor(1);
  163. HW_ReadI2C(pDevInfo, ClockBit);
  164. HW_WriteI2C(pDevInfo, ClockBit, FALSE);
  165. }
  166. /* write data to a given register on a given device on the I2C bus */
  167. VOID
  168. HW_SetI2CReg(PDEVICE_INFO pDevInfo, BYTE bAddress, BYTE bSubAddress, BYTE bData)
  169. {
  170. /* the HW_WriteI2C and HW_ByteToI2C functions assume that
  171. * the PCV_INDEX register is already set up to point to the
  172. * I2C control register.
  173. */
  174. VC_Out(pDevInfo, PCV_INDEX, REG_I2C);
  175. /* start bit */
  176. HW_WriteI2C(pDevInfo, DataBit, TRUE);
  177. HW_WriteI2C(pDevInfo, ClockBit, TRUE);
  178. KeStallExecutionProcessor(5);
  179. HW_WriteI2C(pDevInfo, DataBit, FALSE);
  180. KeStallExecutionProcessor(5);
  181. HW_WriteI2C(pDevInfo, ClockBit, FALSE);
  182. HW_ByteToI2C(pDevInfo, bAddress);
  183. HW_ByteToI2C(pDevInfo, bSubAddress);
  184. HW_ByteToI2C(pDevInfo, bData);
  185. /* stop bit */
  186. HW_WriteI2C(pDevInfo, DataBit, FALSE);
  187. HW_WriteI2C(pDevInfo, ClockBit, TRUE);
  188. KeStallExecutionProcessor(5);
  189. HW_WriteI2C(pDevInfo, DataBit, TRUE);
  190. KeStallExecutionProcessor(5);
  191. }
  192. /*
  193. * set a register on the 9051 signal digitiser chip that controls signal
  194. * capture - this is done via the I2C bus and so we also keep a copy
  195. * of the data in the HWInfo since its easier than struggling to get bytes
  196. * back over the I2C bus.
  197. */
  198. BOOLEAN
  199. HW_Set9051Reg_Sync(PSYNC_REG_ARG pSync)
  200. {
  201. if (pSync->bRegister > NR_REG_9051) {
  202. dprintf(("bad register nr for 9051"));
  203. return FALSE;
  204. }
  205. HW_SetI2CReg(pSync->pDevInfo, ADDR_9051, pSync->bRegister, pSync->bData);
  206. ((PHWINFO) VC_GetHWInfo(pSync->pDevInfo))->bReg9051[pSync->bRegister]
  207. = pSync->bData;
  208. return(TRUE);
  209. }
  210. /* get back the value of a 9051 register -
  211. * use the copy in the HWInfo struct.
  212. */
  213. BYTE
  214. HW_Get9051Reg(PDEVICE_INFO pDevInfo, BYTE bRegister)
  215. {
  216. if (bRegister > NR_REG_9051) {
  217. dprintf(("bad register nr for 9051"));
  218. return(0);
  219. }
  220. return( ((PHWINFO)VC_GetHWInfo(pDevInfo))->bReg9051[bRegister]);
  221. }
  222. /*
  223. * set a register on the 4680 chip that controls overlay display
  224. */
  225. BOOLEAN
  226. HW_Set4680Reg_Sync(PSYNC_REG_ARG pSync)
  227. {
  228. if (pSync->bRegister > NR_REG_4680) {
  229. dprintf(("bad register nr for 4680"));
  230. return FALSE;
  231. }
  232. HW_SetI2CReg(pSync->pDevInfo, ADDR_4680, pSync->bRegister, pSync->bData);
  233. ((PHWINFO) VC_GetHWInfo(pSync->pDevInfo))->bReg4680[pSync->bRegister]
  234. = pSync->bData;
  235. return(TRUE);
  236. }
  237. /* get back the value of a 4680 register */
  238. BYTE
  239. HW_Get4680Reg(PDEVICE_INFO pDevInfo, BYTE bRegister)
  240. {
  241. if (bRegister > NR_REG_4680) {
  242. dprintf(("bad register nr for 4680"));
  243. return(0);
  244. }
  245. return( ((PHWINFO)VC_GetHWInfo(pDevInfo))->bReg4680[bRegister] );
  246. }
  247. /*
  248. * set a register on the main PCVideo chip
  249. */
  250. BOOLEAN
  251. HW_SetPCVideoReg_Sync(PSYNC_REG_ARG pSync)
  252. {
  253. VC_Out(pSync->pDevInfo, PCV_INDEX, pSync->bRegister);
  254. VC_Out(pSync->pDevInfo, PCV_DATA, pSync->bData);
  255. if (pSync->bRegister < NR_REG_PCVIDEO) {
  256. ((PHWINFO)VC_GetHWInfo(pSync->pDevInfo))->bRegPCVideo[pSync->bRegister]
  257. = pSync->bData;
  258. }
  259. return(TRUE);
  260. }
  261. /* get back the value of a PCVideo register */
  262. BOOLEAN
  263. HW_GetPCVideoReg_Sync(PSYNC_REG_ARG pSync)
  264. {
  265. VC_Out(pSync->pDevInfo, PCV_INDEX, pSync->bRegister);
  266. pSync->bData = VC_In(pSync->pDevInfo, PCV_DATA);
  267. return(TRUE);
  268. }