bios_pci.S 9.6 KB

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