lynxpoint.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. package main
  2. import "fmt"
  3. type LPVariant int
  4. const (
  5. LYNX_POINT_MOBILE LPVariant = iota
  6. LYNX_POINT_DESKTOP
  7. LYNX_POINT_SERVER
  8. LYNX_POINT_ULT
  9. )
  10. type lynxpoint struct {
  11. variant LPVariant
  12. node *DevTreeNode
  13. }
  14. func lpPchGetFlashSize(ctx Context) {
  15. inteltool := ctx.InfoSource.GetInteltool()
  16. /* In LP PCH, Boot BIOS Straps field in GCS has only one bit. */
  17. switch (inteltool.RCBA[0x3410] >> 10) & 1 {
  18. case 0:
  19. ROMProtocol = "SPI"
  20. highflkb := uint32(0)
  21. for reg := uint16(0); reg < 5; reg++ {
  22. fl := (inteltool.RCBA[0x3854+4*reg] >> 16) & 0x1fff
  23. flkb := (fl + 1) << 2
  24. if flkb > highflkb {
  25. highflkb = flkb
  26. }
  27. }
  28. ROMSizeKB = int(highflkb)
  29. FlashROMSupport = "y"
  30. }
  31. }
  32. func (b lynxpoint) GetGPIOHeader() string {
  33. return "southbridge/intel/lynxpoint/pch.h"
  34. }
  35. func (b lynxpoint) EnableGPE(in int) {
  36. if b.variant != LYNX_POINT_ULT {
  37. b.node.Registers[fmt.Sprintf("gpi%d_routing", in)] = "2"
  38. }
  39. }
  40. func (b lynxpoint) EncodeGPE(in int) int {
  41. return in + 0x10
  42. }
  43. func (b lynxpoint) DecodeGPE(in int) int {
  44. return in - 0x10
  45. }
  46. func (b lynxpoint) NeedRouteGPIOManually() {
  47. b.node.Comment += ", FIXME: set gpiX_routing for EC support"
  48. }
  49. func GetLptDesktopEHCISetting(loc_param uint32, txamp uint32) (string, int) {
  50. var port_pos string
  51. var port_length int
  52. if loc_param == 4 {
  53. port_pos = "USB_PORT_BACK_PANEL"
  54. if txamp <= 2 {
  55. port_length = 0x40
  56. } else if txamp >= 4 {
  57. port_length = 0x140
  58. } else {
  59. port_length = 0x110
  60. }
  61. } else {
  62. port_pos = "USB_PORT_FLEX"
  63. port_length = 0x40
  64. }
  65. return port_pos, port_length
  66. }
  67. func GetLptMobileEHCISetting(loc_param uint32, txamp uint32) (string, int) {
  68. var port_pos string
  69. var port_length int
  70. if loc_param == 4 {
  71. port_pos = "USB_PORT_DOCK"
  72. if txamp <= 1 {
  73. port_length = 0x40
  74. } else {
  75. port_length = 0x80
  76. }
  77. } else if loc_param == 6 {
  78. /* not internal, not dock, port_length >= 0x70 */
  79. port_pos = "USB_PORT_BACK_PANEL"
  80. if txamp <= 2 {
  81. port_length = 0x80
  82. } else {
  83. port_length = 0x110
  84. }
  85. } else {
  86. port_pos = "USB_PORT_BACK_PANEL"
  87. port_length = 0x40
  88. }
  89. return port_pos, port_length
  90. }
  91. func GetLptLPEHCISetting(loc_param uint32, txamp uint32) (string, int) {
  92. var port_pos string
  93. var port_length int
  94. if loc_param == 6 {
  95. /* back panel or mini pcie, length >= 0x70 */
  96. port_pos = "USB_PORT_MINI_PCIE"
  97. if txamp <= 2 {
  98. port_length = 0x80
  99. } else {
  100. port_length = 0x110
  101. }
  102. } else if loc_param == 4 {
  103. port_pos = "USB_PORT_DOCK"
  104. if txamp <= 1 {
  105. port_length = 0x40
  106. } else {
  107. port_length = 0x80
  108. }
  109. } else {
  110. port_pos = "USB_PORT_BACK_PANEL"
  111. port_length = 0x40
  112. }
  113. return port_pos, port_length
  114. }
  115. func (b lynxpoint) Scan(ctx Context, addr PCIDevData) {
  116. SouthBridge = &b
  117. inteltool := ctx.InfoSource.GetInteltool()
  118. isULT := (b.variant == LYNX_POINT_ULT)
  119. if isULT {
  120. Lynxpoint_LP_GPIO(ctx, inteltool)
  121. } else {
  122. GPIO(ctx, inteltool)
  123. }
  124. KconfigBool["SOUTHBRIDGE_INTEL_LYNXPOINT"] = true
  125. if isULT {
  126. KconfigBool["INTEL_LYNXPOINT_LP"] = true
  127. }
  128. KconfigBool["SERIRQ_CONTINUOUS_MODE"] = true
  129. if isULT {
  130. KconfigInt["USBDEBUG_HCD_INDEX"] = 1
  131. } else {
  132. KconfigInt["USBDEBUG_HCD_INDEX"] = 2
  133. KconfigComment["USBDEBUG_HCD_INDEX"] = "FIXME: check this"
  134. }
  135. if isULT {
  136. lpPchGetFlashSize(ctx)
  137. } else {
  138. ich9GetFlashSize(ctx)
  139. }
  140. FADT := ctx.InfoSource.GetACPI()["FACP"]
  141. sp0dtle_data := (inteltool.IOBP[0xea002750] >> 24) & 0xf
  142. sp0dtle_edge := (inteltool.IOBP[0xea002754] >> 16) & 0xf
  143. sp1dtle_data := (inteltool.IOBP[0xea002550] >> 24) & 0xf
  144. sp1dtle_edge := (inteltool.IOBP[0xea002554] >> 16) & 0xf
  145. if sp0dtle_data != sp0dtle_edge {
  146. fmt.Printf("Different SATA Gen3 port0 DTLE data and edge values are used.\n")
  147. }
  148. if sp1dtle_data != sp1dtle_edge {
  149. fmt.Printf("Different SATA Gen3 port1 DTLE data and edge values are used.\n")
  150. }
  151. cur := DevTreeNode{
  152. Chip: "southbridge/intel/lynxpoint",
  153. Comment: "Intel Series 8 Lynx Point PCH",
  154. /* alt_gp_smi_en is not generated because coreboot doesn't use SMI like OEM firmware */
  155. Registers: map[string]string{
  156. "gen1_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x84:0x88]),
  157. "gen2_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x88:0x8c]),
  158. "gen3_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x8c:0x90]),
  159. "gen4_dec": FormatHexLE32(PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 0}].ConfigDump[0x90:0x94]),
  160. "sata_port_map": fmt.Sprintf("0x%x", PCIMap[PCIAddr{Bus: 0, Dev: 0x1f, Func: 2}].ConfigDump[0x92]&0x3f),
  161. "docking_supported": (FormatBool((FADT[113] & (1 << 1)) != 0)),
  162. "sata_port0_gen3_dtle": fmt.Sprintf("0x%x", sp0dtle_data),
  163. "sata_port1_gen3_dtle": fmt.Sprintf("0x%x", sp1dtle_data),
  164. },
  165. PCISlots: []PCISlot{
  166. PCISlot{PCIAddr: PCIAddr{Dev: 0x13, Func: 0}, writeEmpty: isULT, additionalComment: "Smart Sound Audio DSP"},
  167. PCISlot{PCIAddr: PCIAddr{Dev: 0x14, Func: 0}, writeEmpty: true, additionalComment: "xHCI Controller"},
  168. PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 0}, writeEmpty: isULT, additionalComment: "Serial I/O DMA"},
  169. PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 1}, writeEmpty: isULT, additionalComment: "I2C0"},
  170. PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 2}, writeEmpty: isULT, additionalComment: "I2C1"},
  171. PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 3}, writeEmpty: isULT, additionalComment: "GSPI0"},
  172. PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 4}, writeEmpty: isULT, additionalComment: "GSPI1"},
  173. PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 5}, writeEmpty: isULT, additionalComment: "UART0"},
  174. PCISlot{PCIAddr: PCIAddr{Dev: 0x15, Func: 6}, writeEmpty: isULT, additionalComment: "UART1"},
  175. PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 0}, writeEmpty: true, additionalComment: "Management Engine Interface 1"},
  176. PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 1}, writeEmpty: true, additionalComment: "Management Engine Interface 2"},
  177. PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 2}, writeEmpty: true, additionalComment: "Management Engine IDE-R"},
  178. PCISlot{PCIAddr: PCIAddr{Dev: 0x16, Func: 3}, writeEmpty: true, additionalComment: "Management Engine KT"},
  179. PCISlot{PCIAddr: PCIAddr{Dev: 0x17, Func: 0}, writeEmpty: isULT, additionalComment: "SDIO"},
  180. PCISlot{PCIAddr: PCIAddr{Dev: 0x19, Func: 0}, writeEmpty: true, additionalComment: "Intel Gigabit Ethernet"},
  181. PCISlot{PCIAddr: PCIAddr{Dev: 0x1a, Func: 0}, writeEmpty: !isULT, additionalComment: "USB2 EHCI #2"},
  182. PCISlot{PCIAddr: PCIAddr{Dev: 0x1b, Func: 0}, writeEmpty: true, additionalComment: "High Definition Audio"},
  183. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 0}, writeEmpty: true, additionalComment: "PCIe Port #1"},
  184. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 1}, writeEmpty: true, additionalComment: "PCIe Port #2"},
  185. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 2}, writeEmpty: true, additionalComment: "PCIe Port #3"},
  186. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 3}, writeEmpty: true, additionalComment: "PCIe Port #4"},
  187. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 4}, writeEmpty: true, additionalComment: "PCIe Port #5"},
  188. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 5}, writeEmpty: true, additionalComment: "PCIe Port #6"},
  189. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 6}, writeEmpty: !isULT, additionalComment: "PCIe Port #7"},
  190. PCISlot{PCIAddr: PCIAddr{Dev: 0x1c, Func: 7}, writeEmpty: !isULT, additionalComment: "PCIe Port #8"},
  191. PCISlot{PCIAddr: PCIAddr{Dev: 0x1d, Func: 0}, writeEmpty: true, additionalComment: "USB2 EHCI #1"},
  192. PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 0}, writeEmpty: true, additionalComment: "LPC bridge"},
  193. PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 2}, writeEmpty: true, additionalComment: "SATA Controller (AHCI)"},
  194. PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 3}, writeEmpty: true, additionalComment: "SMBus"},
  195. PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 5}, writeEmpty: !isULT, additionalComment: "SATA Controller (Legacy)"},
  196. PCISlot{PCIAddr: PCIAddr{Dev: 0x1f, Func: 6}, writeEmpty: true, additionalComment: "Thermal"},
  197. },
  198. }
  199. if isULT {
  200. cur.Registers["gpe0_en_1"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x90])
  201. cur.Registers["gpe0_en_2"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x94])
  202. cur.Registers["gpe0_en_3"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x98])
  203. cur.Registers["gpe0_en_4"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x9c])
  204. } else {
  205. cur.Registers["gpe0_en_1"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x28])
  206. cur.Registers["gpe0_en_2"] = fmt.Sprintf("0x%x", inteltool.PMBASE[0x2c])
  207. }
  208. b.node = &cur
  209. PutPCIChip(addr, cur)
  210. PutPCIDevParent(addr, "", "lpc")
  211. DSDTIncludes = append(DSDTIncludes, DSDTInclude{
  212. File: "southbridge/intel/common/acpi/platform.asl",
  213. })
  214. DSDTIncludes = append(DSDTIncludes, DSDTInclude{
  215. File: "southbridge/intel/lynxpoint/acpi/globalnvs.asl",
  216. Comment: "global NVS and variables",
  217. })
  218. DSDTIncludes = append(DSDTIncludes, DSDTInclude{
  219. File: "southbridge/intel/common/acpi/sleepstates.asl",
  220. })
  221. DSDTPCI0Includes = append(DSDTPCI0Includes, DSDTInclude{
  222. File: "southbridge/intel/lynxpoint/acpi/pch.asl",
  223. })
  224. AddBootBlockFile("bootblock.c", "")
  225. bb := Create(ctx, "bootblock.c")
  226. defer bb.Close()
  227. Add_gpl(bb)
  228. bb.WriteString(`#include <southbridge/intel/lynxpoint/pch.h>
  229. /* FIXME: remove this if not needed */
  230. void mainboard_config_superio(void)
  231. {
  232. }
  233. `)
  234. sb := Create(ctx, "romstage.c")
  235. defer sb.Close()
  236. Add_gpl(sb)
  237. sb.WriteString(`#include <stdint.h>
  238. #include <northbridge/intel/haswell/haswell.h>
  239. #include <northbridge/intel/haswell/raminit.h>
  240. #include <southbridge/intel/lynxpoint/pch.h>
  241. void mainboard_config_rcba(void)
  242. {
  243. }
  244. /* FIXME: called after romstage_common, remove it if not used */
  245. void mb_late_romstage_setup(void)
  246. {
  247. }
  248. void mb_get_spd_map(struct spd_info *spdi)
  249. {
  250. /* FIXME: check this */
  251. spdi->addresses[0] = 0x50;
  252. spdi->addresses[1] = 0x51;
  253. spdi->addresses[2] = 0x52;
  254. spdi->addresses[3] = 0x53;
  255. }
  256. const struct usb2_port_config mainboard_usb2_ports[MAX_USB2_PORTS] = {
  257. /* FIXME: Length and Location are computed from IOBP values, may be inaccurate */
  258. /* Length, Enable, OCn#, Location */
  259. `)
  260. pdo1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x64]
  261. ocmap1 := PCIMap[PCIAddr{Bus: 0, Dev: 0x1d, Func: 0}].ConfigDump[0x74:0x78]
  262. var pdo2 uint8
  263. var ocmap2 []uint8
  264. var nPorts uint
  265. if isULT {
  266. nPorts = 8
  267. } else {
  268. pdo2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x64]
  269. ocmap2 = PCIMap[PCIAddr{Bus: 0, Dev: 0x1a, Func: 0}].ConfigDump[0x74:0x78]
  270. nPorts = 14
  271. }
  272. xusb2pr := GetLE16(PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xd0:0xd4])
  273. for port := uint(0); port < nPorts; port++ {
  274. var port_oc int = -1
  275. var port_pos string
  276. var port_disable uint8
  277. if port < 8 {
  278. port_disable = ((pdo1 >> port) & (uint8(xusb2pr>>port) ^ 1)) & 1
  279. for oc := 0; oc < 4; oc++ {
  280. if (ocmap1[oc] & (1 << port)) != 0 {
  281. port_oc = oc
  282. break
  283. }
  284. }
  285. } else {
  286. port_disable = ((pdo2 >> (port - 8)) & (uint8(xusb2pr>>port) ^ 1)) & 1
  287. for oc := 0; oc < 4; oc++ {
  288. if (ocmap2[oc] & (1 << (port - 8))) != 0 {
  289. port_oc = oc + 4
  290. break
  291. }
  292. }
  293. }
  294. /* get USB2 port length and location from IOBP */
  295. port_iobp := inteltool.IOBP[0xe5004100+uint32(port)*0x100]
  296. loc_param := (port_iobp >> 8) & 7
  297. txamp := (port_iobp >> 11) & 7
  298. var port_length int
  299. if isULT {
  300. port_pos, port_length = GetLptLPEHCISetting(loc_param, txamp)
  301. } else if b.variant == LYNX_POINT_MOBILE {
  302. port_pos, port_length = GetLptMobileEHCISetting(loc_param, txamp)
  303. } else { /* desktop or server */
  304. port_pos, port_length = GetLptDesktopEHCISetting(loc_param, txamp)
  305. }
  306. if port_disable == 1 {
  307. port_pos = "USB_PORT_SKIP"
  308. }
  309. if port_oc == -1 {
  310. fmt.Fprintf(sb, "\t{ 0x%04x, %d, USB_OC_PIN_SKIP, %s },\n",
  311. port_length, (port_disable ^ 1), port_pos)
  312. } else {
  313. fmt.Fprintf(sb, "\t{ 0x%04x, %d, %d, %s },\n",
  314. port_length, (port_disable ^ 1), port_oc, port_pos)
  315. }
  316. }
  317. sb.WriteString(`};
  318. const struct usb3_port_config mainboard_usb3_ports[MAX_USB3_PORTS] = {
  319. `)
  320. xpdo := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xe8]
  321. u3ocm := PCIMap[PCIAddr{Bus: 0, Dev: 0x14, Func: 0}].ConfigDump[0xc8:0xd0]
  322. if !isULT {
  323. nPorts = 6
  324. } else {
  325. nPorts = 4
  326. }
  327. for port := uint(0); port < nPorts; port++ {
  328. var port_oc int = -1
  329. port_disable := (xpdo >> port) & 1
  330. for oc := 0; oc < 8; oc++ {
  331. if (u3ocm[oc] & (1 << port)) != 0 {
  332. port_oc = oc
  333. break
  334. }
  335. }
  336. if port_oc == -1 {
  337. fmt.Fprintf(sb, "\t{ %d, USB_OC_PIN_SKIP },\n",
  338. (port_disable ^ 1))
  339. } else {
  340. fmt.Fprintf(sb, "\t{ %d, %d },\n",
  341. (port_disable ^ 1), port_oc)
  342. }
  343. }
  344. sb.WriteString(`};
  345. `)
  346. }
  347. func init() {
  348. for _, id := range []uint16{
  349. 0x8c41, 0x8c49, 0x8c4b, 0x8c4f,
  350. } {
  351. RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_MOBILE})
  352. }
  353. for _, id := range []uint16{
  354. 0x8c42, 0x8c44, 0x8c46, 0x8c4a,
  355. 0x8c4c, 0x8c4e, 0x8c50, 0x8c5c,
  356. } {
  357. RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_DESKTOP})
  358. }
  359. for _, id := range []uint16{
  360. 0x8c52, 0x8c54, 0x8c56,
  361. } {
  362. RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_SERVER})
  363. }
  364. for _, id := range []uint16{
  365. 0x9c41, 0x9c43, 0x9c45,
  366. } {
  367. RegisterPCI(0x8086, uint16(id), lynxpoint{variant: LYNX_POINT_ULT})
  368. }
  369. /* PCIe bridge */
  370. for _, id := range []uint16{
  371. 0x8c10, 0x8c12, 0x8c14, 0x8c16, 0x8c18, 0x8c1a, 0x8c1c, 0x8c1e,
  372. 0x9c10, 0x9c12, 0x9c14, 0x9c16, 0x9c18, 0x9c1a,
  373. } {
  374. RegisterPCI(0x8086, id, GenericPCI{})
  375. }
  376. /* SMBus controller */
  377. RegisterPCI(0x8086, 0x8c22, GenericPCI{MissingParent: "smbus"})
  378. RegisterPCI(0x8086, 0x9c22, GenericPCI{MissingParent: "smbus"})
  379. /* SATA */
  380. for _, id := range []uint16{
  381. 0x8c00, 0x8c02, 0x8c04, 0x8c06, 0x8c08, 0x8c0e,
  382. 0x8c01, 0x8c03, 0x8c05, 0x8c07, 0x8c09, 0x8c0f,
  383. 0x9c03, 0x9c05, 0x9c07, 0x9c0f,
  384. } {
  385. RegisterPCI(0x8086, id, GenericPCI{})
  386. }
  387. /* EHCI */
  388. for _, id := range []uint16{
  389. 0x9c26, 0x8c26, 0x8c2d,
  390. } {
  391. RegisterPCI(0x8086, id, GenericPCI{})
  392. }
  393. /* XHCI */
  394. RegisterPCI(0x8086, 0x8c31, GenericPCI{})
  395. RegisterPCI(0x8086, 0x9c31, GenericPCI{})
  396. /* ME and children */
  397. for _, id := range []uint16{
  398. 0x8c3a, 0x8c3b, 0x8c3c, 0x8c3d,
  399. 0x9c3a, 0x9c3b, 0x9c3c, 0x9c3d,
  400. } {
  401. RegisterPCI(0x8086, id, GenericPCI{})
  402. }
  403. /* Ethernet */
  404. RegisterPCI(0x8086, 0x8c33, GenericPCI{})
  405. /* Thermal */
  406. RegisterPCI(0x8086, 0x8c24, GenericPCI{})
  407. RegisterPCI(0x8086, 0x9c24, GenericPCI{})
  408. /* LAN Controller on LP PCH (if EEPROM has 0x0000/0xffff in DID) */
  409. RegisterPCI(0x8086, 0x155a, GenericPCI{})
  410. /* SDIO */
  411. RegisterPCI(0x8086, 0x9c35, GenericPCI{})
  412. /* Smart Sound Technology Controller */
  413. RegisterPCI(0x8086, 0x9c36, GenericPCI{})
  414. /* Serial I/O */
  415. for id := uint16(0x9c60); id <= 0x9c66; id++ {
  416. RegisterPCI(0x8086, id, GenericPCI{})
  417. }
  418. }