bios_pci.S 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /*
  2. * (C) Copyright 2002
  3. * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. /*
  24. * x86 realmode assembly implementation of a PCI BIOS
  25. * for platforms that use one PCI hose and configuration
  26. * access type 1. (The common case for low-end PC's)
  27. */
  28. #include "bios.h"
  29. #define PCI_BIOS_DEBUG
  30. .section .bios, "ax"
  31. .code16
  32. .globl realmode_pci_bios_call_entry
  33. .hidden realmode_pci_bios_call_entry
  34. .type realmode_pci_bios_call_entry, @function
  35. realmode_pci_bios_call_entry:
  36. MAKE_BIOS_STACK
  37. call realmode_pci_bios
  38. RESTORE_CALLERS_STACK
  39. ret
  40. .globl realmode_pci_bios
  41. realmode_pci_bios:
  42. gs movw OFFS_AX(%bp), %ax
  43. cmpb $1, %al
  44. je pci_bios_present
  45. cmpb $2, %al
  46. je pci_bios_find_device
  47. cmpb $3, %al
  48. je pci_bios_find_class
  49. cmpb $6, %al
  50. je pci_bios_generate_special_cycle
  51. cmpb $8, %al
  52. je pci_bios_read_cfg_byte
  53. cmpb $9, %al
  54. je pci_bios_read_cfg_word
  55. cmpb $10, %al
  56. je pci_bios_read_cfg_dword
  57. cmpb $11, %al
  58. je pci_bios_write_cfg_byte
  59. cmpb $12, %al
  60. je pci_bios_write_cfg_word
  61. cmpb $13, %al
  62. je pci_bios_write_cfg_dword
  63. cmpb $14, %al
  64. je pci_bios_get_irq_routing
  65. cmpb $15, %al
  66. je pci_bios_set_irq
  67. jmp unknown_function
  68. /*****************************************************************************/
  69. pci_bios_present:
  70. #ifdef PCI_BIOS_DEBUG
  71. cs incl num_pci_bios_present
  72. #endif
  73. movl $0x20494350, %eax
  74. gs movl %eax, OFFS_EDX(%bp)
  75. /* We support cfg type 1 version 2.10 */
  76. movb $0x01, %al
  77. gs movb %al, OFFS_AL(%bp)
  78. movw $0x0210, %ax
  79. gs movw %ax, OFFS_BX(%bp)
  80. /* last bus number */
  81. cs movb pci_last_bus, %al
  82. gs movb %al, OFFS_CL(%bp)
  83. jmp clear_carry
  84. /*****************************************************************************/
  85. /* device 0-31, function 0-7 */
  86. pci_bios_find_device:
  87. #ifdef PCI_BIOS_DEBUG
  88. cs incl num_pci_bios_find_device
  89. #endif
  90. gs movw OFFS_CX(%bp), %di
  91. shll $16, %edi
  92. gs movw OFFS_DX(%bp), %di
  93. /* edi now holds device in upper 16 bits and vendor in lower 16 bits */
  94. gs movw OFFS_SI(%bp), %si
  95. /* start at bus 0 dev 0 function 0 */
  96. xorw %bx, %bx
  97. pfd_loop:
  98. /* dword 0 is vendor/device */
  99. xorw %ax, %ax
  100. call __pci_bios_select_register
  101. movw $0xcfc, %dx
  102. inl %dx, %eax
  103. /* our device ? */
  104. cmpl %edi, %eax
  105. je pfd_found_one
  106. pfd_next_dev:
  107. /* check for multi function devices */
  108. movw %bx, %ax
  109. andw $3, %ax
  110. jnz pfd_function_not_zero
  111. movw $0x000c, %ax
  112. call __pci_bios_select_register
  113. movw $0xcfe, %dx
  114. inb %dx, %al
  115. andb $0x80, %al
  116. jz pfd_not_multi_function
  117. pfd_function_not_zero:
  118. /* next function, overflows in to device number, then bus number */
  119. incw %bx
  120. jmp pfd_check_bus
  121. pfd_not_multi_function:
  122. /* remove function bits */
  123. andw $0xfff8, %bx
  124. /* next device, overflows in to bus number */
  125. addw $0x0008, %bx
  126. pfd_check_bus:
  127. cs movb pci_last_bus, %ah
  128. cmpb %ah, %bh
  129. ja pfd_not_found
  130. jmp pfd_loop
  131. pfd_found_one:
  132. decw %si
  133. js pfd_done
  134. jmp pfd_next_dev
  135. pfd_done:
  136. gs movw %bx, OFFS_BX(%bp)
  137. jmp clear_carry
  138. pfd_not_found:
  139. /* device not found */
  140. movb $0x86, %ah
  141. jmp set_carry
  142. /*****************************************************************************/
  143. pci_bios_find_class:
  144. #ifdef PCI_BIOS_DEBUG
  145. cs incl num_pci_bios_find_class
  146. #endif
  147. gs movl OFFS_ECX(%bp), %edi
  148. /* edi now holds class-code in lower 24 bits */
  149. andl $0x00ffffff, %edi
  150. gs movw OFFS_SI(%bp), %si
  151. /* start at bus 0 dev 0 function 0 */
  152. xorw %bx, %bx
  153. pfc_loop:
  154. /* dword 8 is class-code high 24bits */
  155. movw $8, %ax
  156. call __pci_bios_select_register
  157. movw $0xcfc, %dx
  158. inl %dx, %eax
  159. shrl $8, %eax
  160. andl $0x00ffffff, %eax
  161. /* our device ? */
  162. cmpl %edi, %eax
  163. je pfc_found_one
  164. pfc_next_dev:
  165. /* check for multi function devices */
  166. andw $3, %bx
  167. jnz pfc_function_not_zero
  168. movw $0x000c, %ax
  169. call __pci_bios_select_register
  170. movw $0xcfe, %dx
  171. inb %dx, %al
  172. andb $0x80, %al
  173. jz pfc_not_multi_function
  174. pfc_function_not_zero:
  175. /* next function, overflows in to device number, then bus number */
  176. incw %bx
  177. jmp pfc_check_bus
  178. pfc_not_multi_function:
  179. /* remove function bits */
  180. andw $0xfff8, %bx
  181. /* next device, overflows in to bus number */
  182. addw $0x0008, %bx
  183. pfc_check_bus:
  184. cs movb pci_last_bus, %ah
  185. cmpb %ah, %bh
  186. ja pfc_not_found
  187. jmp pfc_loop
  188. pfc_found_one:
  189. decw %si
  190. js pfc_done
  191. jmp pfc_next_dev
  192. pfc_done:
  193. gs movw %bx, OFFS_BX(%bp)
  194. jmp clear_carry
  195. pfc_not_found:
  196. /* device not found */
  197. movb $0x86, %ah
  198. jmp set_carry
  199. /*****************************************************************************/
  200. pci_bios_generate_special_cycle:
  201. #ifdef PCI_BIOS_DEBUG
  202. cs incl num_pci_bios_generate_special_cycle
  203. #endif
  204. /* function not supported */
  205. movb $0x81, %ah
  206. jmp set_carry
  207. /*****************************************************************************/
  208. pci_bios_read_cfg_byte:
  209. #ifdef PCI_BIOS_DEBUG
  210. cs incl num_pci_bios_read_cfg_byte
  211. #endif
  212. call pci_bios_select_register
  213. gs movw OFFS_DI(%bp), %dx
  214. andw $3, %dx
  215. addw $0xcfc, %dx
  216. inb %dx, %al
  217. gs movb %al, OFFS_CL(%bp)
  218. jmp clear_carry
  219. /*****************************************************************************/
  220. pci_bios_read_cfg_word:
  221. #ifdef PCI_BIOS_DEBUG
  222. cs incl num_pci_bios_read_cfg_word
  223. #endif
  224. call pci_bios_select_register
  225. gs movw OFFS_DI(%bp), %dx
  226. andw $2, %dx
  227. addw $0xcfc, %dx
  228. inw %dx, %ax
  229. gs movw %ax, OFFS_CX(%bp)
  230. jmp clear_carry
  231. /*****************************************************************************/
  232. pci_bios_read_cfg_dword:
  233. #ifdef PCI_BIOS_DEBUG
  234. cs incl num_pci_bios_read_cfg_dword
  235. #endif
  236. call pci_bios_select_register
  237. movw $0xcfc, %dx
  238. inl %dx, %eax
  239. gs movl %eax, OFFS_ECX(%bp)
  240. jmp clear_carry
  241. /*****************************************************************************/
  242. pci_bios_write_cfg_byte:
  243. #ifdef PCI_BIOS_DEBUG
  244. cs incl num_pci_bios_write_cfg_byte
  245. #endif
  246. call pci_bios_select_register
  247. gs movw OFFS_DI(%bp), %dx
  248. gs movb OFFS_CL(%bp), %al
  249. andw $3, %dx
  250. addw $0xcfc, %dx
  251. outb %al, %dx
  252. jmp clear_carry
  253. /*****************************************************************************/
  254. pci_bios_write_cfg_word:
  255. #ifdef PCI_BIOS_DEBUG
  256. cs incl num_pci_bios_write_cfg_word
  257. #endif
  258. call pci_bios_select_register
  259. gs movw OFFS_DI(%bp), %dx
  260. gs movw OFFS_CX(%bp), %ax
  261. andw $2, %dx
  262. addw $0xcfc, %dx
  263. outw %ax, %dx
  264. jmp clear_carry
  265. /*****************************************************************************/
  266. pci_bios_write_cfg_dword:
  267. #ifdef PCI_BIOS_DEBUG
  268. cs incl num_pci_bios_write_cfg_dword
  269. #endif
  270. call pci_bios_select_register
  271. gs movl OFFS_ECX(%bp), %eax
  272. movw $0xcfc, %dx
  273. outl %eax, %dx
  274. jmp clear_carry
  275. /*****************************************************************************/
  276. pci_bios_get_irq_routing:
  277. #ifdef PCI_BIOS_DEBUG
  278. cs incl num_pci_bios_get_irq_routing
  279. #endif
  280. /* function not supported */
  281. movb $0x81, %ah
  282. jmp set_carry
  283. /*****************************************************************************/
  284. pci_bios_set_irq:
  285. #ifdef PCI_BIOS_DEBUG
  286. cs incl num_pci_bios_set_irq
  287. #endif
  288. /* function not supported */
  289. movb $0x81, %ah
  290. jmp set_carry
  291. /*****************************************************************************/
  292. unknown_function:
  293. #ifdef PCI_BIOS_DEBUG
  294. cs incl num_pci_bios_unknown_function
  295. #endif
  296. /* function not supported */
  297. movb $0x81, %ah
  298. jmp set_carry
  299. /*****************************************************************************/
  300. pci_bios_select_register:
  301. gs movw OFFS_BX(%bp), %bx
  302. gs movw OFFS_DI(%bp), %ax
  303. /* destroys eax, dx */
  304. __pci_bios_select_register:
  305. /* BX holds device id, AX holds register index */
  306. pushl %ebx
  307. andl $0xfc, %eax
  308. andl $0xffff, %ebx
  309. shll $8, %ebx
  310. orl %ebx, %eax
  311. orl $0x80000000, %eax
  312. movw $0xcf8, %dx
  313. outl %eax, %dx
  314. popl %ebx
  315. ret
  316. clear_carry:
  317. gs movw OFFS_FLAGS(%bp), %ax
  318. /* clear carry -- function succeeded */
  319. andw $0xfffe, %ax
  320. gs movw %ax, OFFS_FLAGS(%bp)
  321. xorw %ax, %ax
  322. gs movb %ah, OFFS_AH(%bp)
  323. ret
  324. set_carry:
  325. gs movb %ah, OFFS_AH(%bp)
  326. gs movw OFFS_FLAGS(%bp), %ax
  327. /* return carry -- function not supported */
  328. orw $1, %ax
  329. gs movw %ax, OFFS_FLAGS(%bp)
  330. movw $-1, %ax
  331. ret
  332. /*****************************************************************************/
  333. .globl pci_last_bus
  334. pci_last_bus:
  335. .byte 0
  336. #ifdef PCI_BIOS_DEBUG
  337. .globl num_pci_bios_present
  338. num_pci_bios_present:
  339. .long 0
  340. .globl num_pci_bios_find_device
  341. num_pci_bios_find_device:
  342. .long 0
  343. .globl num_pci_bios_find_class
  344. num_pci_bios_find_class:
  345. .long 0
  346. .globl num_pci_bios_generate_special_cycle
  347. num_pci_bios_generate_special_cycle:
  348. .long 0
  349. .globl num_pci_bios_read_cfg_byte
  350. num_pci_bios_read_cfg_byte:
  351. .long 0
  352. .globl num_pci_bios_read_cfg_word
  353. num_pci_bios_read_cfg_word:
  354. .long 0
  355. .globl num_pci_bios_read_cfg_dword
  356. num_pci_bios_read_cfg_dword:
  357. .long 0
  358. .globl num_pci_bios_write_cfg_byte
  359. num_pci_bios_write_cfg_byte:
  360. .long 0
  361. .globl num_pci_bios_write_cfg_word
  362. num_pci_bios_write_cfg_word:
  363. .long 0
  364. .globl num_pci_bios_write_cfg_dword
  365. num_pci_bios_write_cfg_dword:
  366. .long 0
  367. .globl num_pci_bios_get_irq_routing
  368. num_pci_bios_get_irq_routing:
  369. .long 0
  370. .globl num_pci_bios_set_irq
  371. num_pci_bios_set_irq:
  372. .long 0
  373. .globl num_pci_bios_unknown_function
  374. num_pci_bios_unknown_function:
  375. .long 0
  376. #endif