bios_pci.S 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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. movb $0x01, %al
  76. gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */
  77. movw $0x0210, %ax /* version 2.10 */
  78. gs movw %ax, OFFS_BX(%bp)
  79. cs movb pci_last_bus, %al /* last bus number */
  80. gs movb %al, OFFS_CL(%bp)
  81. jmp clear_carry
  82. /*****************************************************************************/
  83. /* device 0-31, function 0-7 */
  84. pci_bios_find_device:
  85. #ifdef PCI_BIOS_DEBUG
  86. cs incl num_pci_bios_find_device
  87. #endif
  88. gs movw OFFS_CX(%bp), %di
  89. shll $16, %edi
  90. gs movw OFFS_DX(%bp), %di /* edi now holds device in upper 16
  91. * bits and vendor in lower 16 bits */
  92. gs movw OFFS_SI(%bp), %si
  93. xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
  94. pfd_loop:
  95. xorw %ax, %ax /* dword 0 is vendor/device */
  96. call __pci_bios_select_register
  97. movw $0xcfc, %dx
  98. inl %dx, %eax
  99. cmpl %edi, %eax /* our device ? */
  100. je pfd_found_one
  101. pfd_next_dev:
  102. /* check for multi function devices */
  103. movw %bx, %ax
  104. andw $3, %ax
  105. jnz pfd_function_not_zero
  106. movw $0x000c, %ax
  107. call __pci_bios_select_register
  108. movw $0xcfe, %dx
  109. inb %dx, %al
  110. andb $0x80, %al
  111. jz pfd_not_multi_function
  112. pfd_function_not_zero:
  113. incw %bx /* next function, overflows in to
  114. * device number, then bus number */
  115. jmp pfd_check_bus
  116. pfd_not_multi_function:
  117. andw $0xfff8, %bx /* remove function bits */
  118. addw $0x0008, %bx /* next device, overflows in to bus number */
  119. pfd_check_bus:
  120. cs movb pci_last_bus, %ah
  121. cmpb %ah, %bh
  122. ja pfd_not_found
  123. jmp pfd_loop
  124. pfd_found_one:
  125. decw %si
  126. js pfd_done
  127. jmp pfd_next_dev
  128. pfd_done:
  129. gs movw %bx, OFFS_BX(%bp)
  130. jmp clear_carry
  131. pfd_not_found:
  132. movb $0x86, %ah /* device not found */
  133. jmp set_carry
  134. /*****************************************************************************/
  135. pci_bios_find_class:
  136. #ifdef PCI_BIOS_DEBUG
  137. cs incl num_pci_bios_find_class
  138. #endif
  139. gs movl OFFS_ECX(%bp), %edi
  140. andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */
  141. gs movw OFFS_SI(%bp), %si
  142. xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
  143. pfc_loop:
  144. movw $8, %ax /* dword 8 is class-code high 24bits */
  145. call __pci_bios_select_register
  146. movw $0xcfc, %dx
  147. inl %dx, %eax
  148. shrl $8, %eax
  149. andl $0x00ffffff, %eax
  150. cmpl %edi, %eax /* our device ? */
  151. je pfc_found_one
  152. pfc_next_dev:
  153. /* check for multi function devices */
  154. andw $3, %bx
  155. jnz pfc_function_not_zero
  156. movw $0x000c, %ax
  157. call __pci_bios_select_register
  158. movw $0xcfe, %dx
  159. inb %dx, %al
  160. andb $0x80, %al
  161. jz pfc_not_multi_function
  162. pfc_function_not_zero:
  163. incw %bx /* next function, overflows in to
  164. * device number, then bus number */
  165. jmp pfc_check_bus
  166. pfc_not_multi_function:
  167. andw $0xfff8, %bx /* remove function bits */
  168. addw $0x0008, %bx /* next device, overflows in to bus number */
  169. pfc_check_bus:
  170. cs movb pci_last_bus, %ah
  171. cmpb %ah, %bh
  172. ja pfc_not_found
  173. jmp pfc_loop
  174. pfc_found_one:
  175. decw %si
  176. js pfc_done
  177. jmp pfc_next_dev
  178. pfc_done:
  179. gs movw %bx, OFFS_BX(%bp)
  180. jmp clear_carry
  181. pfc_not_found:
  182. movb $0x86, %ah /* device not found */
  183. jmp set_carry
  184. /*****************************************************************************/
  185. pci_bios_generate_special_cycle:
  186. #ifdef PCI_BIOS_DEBUG
  187. cs incl num_pci_bios_generate_special_cycle
  188. #endif
  189. movb $0x81, %ah /* function not supported */
  190. jmp set_carry
  191. /*****************************************************************************/
  192. pci_bios_read_cfg_byte:
  193. #ifdef PCI_BIOS_DEBUG
  194. cs incl num_pci_bios_read_cfg_byte
  195. #endif
  196. call pci_bios_select_register
  197. gs movw OFFS_DI(%bp), %dx
  198. andw $3, %dx
  199. addw $0xcfc, %dx
  200. inb %dx, %al
  201. gs movb %al, OFFS_CL(%bp)
  202. jmp clear_carry
  203. /*****************************************************************************/
  204. pci_bios_read_cfg_word:
  205. #ifdef PCI_BIOS_DEBUG
  206. cs incl num_pci_bios_read_cfg_word
  207. #endif
  208. call pci_bios_select_register
  209. gs movw OFFS_DI(%bp), %dx
  210. andw $2, %dx
  211. addw $0xcfc, %dx
  212. inw %dx, %ax
  213. gs movw %ax, OFFS_CX(%bp)
  214. jmp clear_carry
  215. /*****************************************************************************/
  216. pci_bios_read_cfg_dword:
  217. #ifdef PCI_BIOS_DEBUG
  218. cs incl num_pci_bios_read_cfg_dword
  219. #endif
  220. call pci_bios_select_register
  221. movw $0xcfc, %dx
  222. inl %dx, %eax
  223. gs movl %eax, OFFS_ECX(%bp)
  224. jmp clear_carry
  225. /*****************************************************************************/
  226. pci_bios_write_cfg_byte:
  227. #ifdef PCI_BIOS_DEBUG
  228. cs incl num_pci_bios_write_cfg_byte
  229. #endif
  230. call pci_bios_select_register
  231. gs movw OFFS_DI(%bp), %dx
  232. gs movb OFFS_CL(%bp), %al
  233. andw $3, %dx
  234. addw $0xcfc, %dx
  235. outb %al, %dx
  236. jmp clear_carry
  237. /*****************************************************************************/
  238. pci_bios_write_cfg_word:
  239. #ifdef PCI_BIOS_DEBUG
  240. cs incl num_pci_bios_write_cfg_word
  241. #endif
  242. call pci_bios_select_register
  243. gs movw OFFS_DI(%bp), %dx
  244. gs movw OFFS_CX(%bp), %ax
  245. andw $2, %dx
  246. addw $0xcfc, %dx
  247. outw %ax, %dx
  248. jmp clear_carry
  249. /*****************************************************************************/
  250. pci_bios_write_cfg_dword:
  251. #ifdef PCI_BIOS_DEBUG
  252. cs incl num_pci_bios_write_cfg_dword
  253. #endif
  254. call pci_bios_select_register
  255. gs movl OFFS_ECX(%bp), %eax
  256. movw $0xcfc, %dx
  257. outl %eax, %dx
  258. jmp clear_carry
  259. /*****************************************************************************/
  260. pci_bios_get_irq_routing:
  261. #ifdef PCI_BIOS_DEBUG
  262. cs incl num_pci_bios_get_irq_routing
  263. #endif
  264. movb $0x81, %ah /* function not supported */
  265. jmp set_carry
  266. /*****************************************************************************/
  267. pci_bios_set_irq:
  268. #ifdef PCI_BIOS_DEBUG
  269. cs incl num_pci_bios_set_irq
  270. #endif
  271. movb $0x81, %ah /* function not supported */
  272. jmp set_carry
  273. /*****************************************************************************/
  274. unknown_function:
  275. #ifdef PCI_BIOS_DEBUG
  276. cs incl num_pci_bios_unknown_function
  277. #endif
  278. movb $0x81, %ah /* function not supported */
  279. jmp set_carry
  280. /*****************************************************************************/
  281. pci_bios_select_register:
  282. gs movw OFFS_BX(%bp), %bx
  283. gs movw OFFS_DI(%bp), %ax
  284. /* destroys eax, dx */
  285. __pci_bios_select_register: /* BX holds device id, AX holds register index */
  286. pushl %ebx
  287. andl $0xfc, %eax
  288. andl $0xffff, %ebx
  289. shll $8, %ebx
  290. orl %ebx, %eax
  291. orl $0x80000000, %eax
  292. movw $0xcf8, %dx
  293. outl %eax, %dx
  294. popl %ebx
  295. ret
  296. clear_carry:
  297. gs movw OFFS_FLAGS(%bp), %ax
  298. andw $0xfffe, %ax /* clear carry -- function succeeded */
  299. gs movw %ax, OFFS_FLAGS(%bp)
  300. xorw %ax, %ax
  301. gs movb %ah, OFFS_AH(%bp)
  302. ret
  303. set_carry:
  304. gs movb %ah, OFFS_AH(%bp)
  305. gs movw OFFS_FLAGS(%bp), %ax
  306. orw $1, %ax /* return carry -- function not supported */
  307. gs movw %ax, OFFS_FLAGS(%bp)
  308. movw $-1, %ax
  309. ret
  310. /*****************************************************************************/
  311. .globl pci_last_bus
  312. pci_last_bus:
  313. .byte 0
  314. #ifdef PCI_BIOS_DEBUG
  315. .globl num_pci_bios_present
  316. num_pci_bios_present:
  317. .long 0
  318. .globl num_pci_bios_find_device
  319. num_pci_bios_find_device:
  320. .long 0
  321. .globl num_pci_bios_find_class
  322. num_pci_bios_find_class:
  323. .long 0
  324. .globl num_pci_bios_generate_special_cycle
  325. num_pci_bios_generate_special_cycle:
  326. .long 0
  327. .globl num_pci_bios_read_cfg_byte
  328. num_pci_bios_read_cfg_byte:
  329. .long 0
  330. .globl num_pci_bios_read_cfg_word
  331. num_pci_bios_read_cfg_word:
  332. .long 0
  333. .globl num_pci_bios_read_cfg_dword
  334. num_pci_bios_read_cfg_dword:
  335. .long 0
  336. .globl num_pci_bios_write_cfg_byte
  337. num_pci_bios_write_cfg_byte:
  338. .long 0
  339. .globl num_pci_bios_write_cfg_word
  340. num_pci_bios_write_cfg_word:
  341. .long 0
  342. .globl num_pci_bios_write_cfg_dword
  343. num_pci_bios_write_cfg_dword:
  344. .long 0
  345. .globl num_pci_bios_get_irq_routing
  346. num_pci_bios_get_irq_routing:
  347. .long 0
  348. .globl num_pci_bios_set_irq
  349. num_pci_bios_set_irq:
  350. .long 0
  351. .globl num_pci_bios_unknown_function
  352. num_pci_bios_unknown_function:
  353. .long 0
  354. #endif