blob: 67fd00b83433ae0bd4632908821491319fb1799f [file] [log] [blame]
wdenk7a8e9bed2003-05-31 18:35:21 +00001/*
2 * (C) Copyright 2002
3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
wdenk8bde7f72003-06-27 21:31:46 +00004 *
wdenk7a8e9bed2003-05-31 18:35:21 +00005 * 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/*
25 * x86 realmode assembly implementation of a PCI BIOS
wdenk8bde7f72003-06-27 21:31:46 +000026 * for platforms that use one PCI hose and configuration
wdenk7a8e9bed2003-05-31 18:35:21 +000027 * access type 1. (The common case for low-end PC's)
28 */
wdenk8bde7f72003-06-27 21:31:46 +000029
wdenk7a8e9bed2003-05-31 18:35:21 +000030#include "bios.h"
31
32#define PCI_BIOS_DEBUG
33
34.section .bios, "ax"
35.code16
36.globl realmode_pci_bios_call_entry
37realmode_pci_bios_call_entry:
38 MAKE_BIOS_STACK
39 call realmode_pci_bios
40 RESTORE_CALLERS_STACK
41 ret
wdenk8bde7f72003-06-27 21:31:46 +000042
43
wdenk7a8e9bed2003-05-31 18:35:21 +000044.globl realmode_pci_bios
45realmode_pci_bios:
46gs movw OFFS_AX(%bp), %ax
47 cmpb $1, %al
48 je pci_bios_present
49 cmpb $2, %al
50 je pci_bios_find_device
51 cmpb $3, %al
52 je pci_bios_find_class
53 cmpb $6, %al
54 je pci_bios_generate_special_cycle
55 cmpb $8, %al
56 je pci_bios_read_cfg_byte
57 cmpb $9, %al
58 je pci_bios_read_cfg_word
59 cmpb $10, %al
60 je pci_bios_read_cfg_dword
61 cmpb $11, %al
62 je pci_bios_write_cfg_byte
63 cmpb $12, %al
64 je pci_bios_write_cfg_word
65 cmpb $13, %al
66 je pci_bios_write_cfg_dword
67 cmpb $14, %al
68 je pci_bios_get_irq_routing
69 cmpb $15, %al
70 je pci_bios_set_irq
71 jmp unknown_function
wdenk8bde7f72003-06-27 21:31:46 +000072
wdenk7a8e9bed2003-05-31 18:35:21 +000073/*****************************************************************************/
74
75pci_bios_present:
76#ifdef PCI_BIOS_DEBUG
77cs incl num_pci_bios_present
78#endif
79 movl $0x20494350, %eax
wdenk8bde7f72003-06-27 21:31:46 +000080gs movl %eax, OFFS_EDX(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +000081 movb $0x01, %al
wdenk8bde7f72003-06-27 21:31:46 +000082gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */
83 movw $0x0210, %ax /* version 2.10 */
84gs movw %ax, OFFS_BX(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +000085cs movb pci_last_bus, %al /* last bus number */
wdenk8bde7f72003-06-27 21:31:46 +000086gs movb %al, OFFS_CL(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +020087 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +000088
89/*****************************************************************************/
90
91/* device 0-31, function 0-7 */
wdenk8bde7f72003-06-27 21:31:46 +000092pci_bios_find_device:
wdenk7a8e9bed2003-05-31 18:35:21 +000093#ifdef PCI_BIOS_DEBUG
Wolfgang Denk53677ef2008-05-20 16:00:29 +020094cs incl num_pci_bios_find_device
wdenk7a8e9bed2003-05-31 18:35:21 +000095#endif
wdenk8bde7f72003-06-27 21:31:46 +000096gs movw OFFS_CX(%bp), %di
wdenk7a8e9bed2003-05-31 18:35:21 +000097 shll $16, %edi
wdenk8bde7f72003-06-27 21:31:46 +000098gs movw OFFS_DX(%bp), %di /* edi now holds device in upper 16
99 * bits and vendor in lower 16 bits */
100gs movw OFFS_SI(%bp), %si
wdenk7a8e9bed2003-05-31 18:35:21 +0000101 xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
wdenk8bde7f72003-06-27 21:31:46 +0000102pfd_loop:
103 xorw %ax, %ax /* dword 0 is vendor/device */
104 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000105 movw $0xcfc, %dx
106 inl %dx, %eax
107 cmpl %edi, %eax /* our device ? */
108 je pfd_found_one
109pfd_next_dev:
110 /* check for multi function devices */
111 movw %bx, %ax
112 andw $3, %ax
113 jnz pfd_function_not_zero
wdenk8bde7f72003-06-27 21:31:46 +0000114 movw $0x000c, %ax
115 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000116 movw $0xcfe, %dx
117 inb %dx, %al
118 andb $0x80, %al
119 jz pfd_not_multi_function
120pfd_function_not_zero:
121 incw %bx /* next function, overflows in to
122 * device number, then bus number */
123 jmp pfd_check_bus
wdenk8bde7f72003-06-27 21:31:46 +0000124
wdenk7a8e9bed2003-05-31 18:35:21 +0000125pfd_not_multi_function:
126 andw $0xfff8, %bx /* remove function bits */
127 addw $0x0008, %bx /* next device, overflows in to bus number */
wdenk8bde7f72003-06-27 21:31:46 +0000128pfd_check_bus:
wdenk7a8e9bed2003-05-31 18:35:21 +0000129cs movb pci_last_bus, %ah
130 cmpb %ah, %bh
131 ja pfd_not_found
132 jmp pfd_loop
133pfd_found_one:
134 decw %si
135 js pfd_done
136 jmp pfd_next_dev
137
138pfd_done:
wdenk8bde7f72003-06-27 21:31:46 +0000139gs movw %bx, OFFS_BX(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000140 jmp clear_carry
141
142pfd_not_found:
143 movb $0x86, %ah /* device not found */
144 jmp set_carry
145
146/*****************************************************************************/
147
148pci_bios_find_class:
149#ifdef PCI_BIOS_DEBUG
150cs incl num_pci_bios_find_class
151#endif
wdenk8bde7f72003-06-27 21:31:46 +0000152gs movl OFFS_ECX(%bp), %edi
153 andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */
154gs movw OFFS_SI(%bp), %si
wdenk7a8e9bed2003-05-31 18:35:21 +0000155 xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
wdenk8bde7f72003-06-27 21:31:46 +0000156pfc_loop:
157 movw $8, %ax /* dword 8 is class-code high 24bits */
158 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000159 movw $0xcfc, %dx
160 inl %dx, %eax
161 shrl $8, %eax
162 andl $0x00ffffff, %eax
163 cmpl %edi, %eax /* our device ? */
164 je pfc_found_one
165pfc_next_dev:
166 /* check for multi function devices */
167 andw $3, %bx
168 jnz pfc_function_not_zero
wdenk8bde7f72003-06-27 21:31:46 +0000169 movw $0x000c, %ax
170 call __pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000171 movw $0xcfe, %dx
172 inb %dx, %al
173 andb $0x80, %al
174 jz pfc_not_multi_function
175pfc_function_not_zero:
176 incw %bx /* next function, overflows in to
177 * device number, then bus number */
178 jmp pfc_check_bus
wdenk8bde7f72003-06-27 21:31:46 +0000179
wdenk7a8e9bed2003-05-31 18:35:21 +0000180pfc_not_multi_function:
181 andw $0xfff8, %bx /* remove function bits */
182 addw $0x0008, %bx /* next device, overflows in to bus number */
wdenk8bde7f72003-06-27 21:31:46 +0000183pfc_check_bus:
wdenk7a8e9bed2003-05-31 18:35:21 +0000184cs movb pci_last_bus, %ah
185 cmpb %ah, %bh
186 ja pfc_not_found
187 jmp pfc_loop
188pfc_found_one:
189 decw %si
190 js pfc_done
191 jmp pfc_next_dev
192
193pfc_done:
wdenk8bde7f72003-06-27 21:31:46 +0000194gs movw %bx, OFFS_BX(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000195 jmp clear_carry
196
197pfc_not_found:
198 movb $0x86, %ah /* device not found */
199 jmp set_carry
200
201/*****************************************************************************/
202
203pci_bios_generate_special_cycle:
204#ifdef PCI_BIOS_DEBUG
205cs incl num_pci_bios_generate_special_cycle
206#endif
207 movb $0x81, %ah /* function not supported */
208 jmp set_carry
wdenk8bde7f72003-06-27 21:31:46 +0000209
wdenk7a8e9bed2003-05-31 18:35:21 +0000210/*****************************************************************************/
211
wdenk8bde7f72003-06-27 21:31:46 +0000212pci_bios_read_cfg_byte:
wdenk7a8e9bed2003-05-31 18:35:21 +0000213#ifdef PCI_BIOS_DEBUG
214cs incl num_pci_bios_read_cfg_byte
215#endif
wdenk8bde7f72003-06-27 21:31:46 +0000216 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200217gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000218 andw $3, %dx
219 addw $0xcfc, %dx
220 inb %dx, %al
wdenk8bde7f72003-06-27 21:31:46 +0000221gs movb %al, OFFS_CL(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200222 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000223
224/*****************************************************************************/
225
wdenk8bde7f72003-06-27 21:31:46 +0000226pci_bios_read_cfg_word:
wdenk7a8e9bed2003-05-31 18:35:21 +0000227#ifdef PCI_BIOS_DEBUG
228cs incl num_pci_bios_read_cfg_word
229#endif
230 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200231gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000232 andw $2, %dx
233 addw $0xcfc, %dx
234 inw %dx, %ax
wdenk8bde7f72003-06-27 21:31:46 +0000235gs movw %ax, OFFS_CX(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200236 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000237
238
239/*****************************************************************************/
240
wdenk8bde7f72003-06-27 21:31:46 +0000241pci_bios_read_cfg_dword:
wdenk7a8e9bed2003-05-31 18:35:21 +0000242#ifdef PCI_BIOS_DEBUG
243cs incl num_pci_bios_read_cfg_dword
244#endif
245 call pci_bios_select_register
246 movw $0xcfc, %dx
247 inl %dx, %eax
wdenk8bde7f72003-06-27 21:31:46 +0000248gs movl %eax, OFFS_ECX(%bp)
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200249 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000250
251/*****************************************************************************/
252
253pci_bios_write_cfg_byte:
254#ifdef PCI_BIOS_DEBUG
255cs incl num_pci_bios_write_cfg_byte
256#endif
wdenk8bde7f72003-06-27 21:31:46 +0000257 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200258gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000259gs movb OFFS_CL(%bp), %al
260 andw $3, %dx
261 addw $0xcfc, %dx
262 outb %al, %dx
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200263 jmp clear_carry
wdenk8bde7f72003-06-27 21:31:46 +0000264
wdenk7a8e9bed2003-05-31 18:35:21 +0000265/*****************************************************************************/
266
267pci_bios_write_cfg_word:
268#ifdef PCI_BIOS_DEBUG
269cs incl num_pci_bios_write_cfg_word
270#endif
wdenk8bde7f72003-06-27 21:31:46 +0000271 call pci_bios_select_register
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200272gs movw OFFS_DI(%bp), %dx
wdenk7a8e9bed2003-05-31 18:35:21 +0000273gs movw OFFS_CX(%bp), %ax
274 andw $2, %dx
275 addw $0xcfc, %dx
276 outw %ax, %dx
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200277 jmp clear_carry
wdenk8bde7f72003-06-27 21:31:46 +0000278
wdenk7a8e9bed2003-05-31 18:35:21 +0000279/*****************************************************************************/
280
281pci_bios_write_cfg_dword:
282#ifdef PCI_BIOS_DEBUG
283cs incl num_pci_bios_write_cfg_dword
284#endif
wdenk8bde7f72003-06-27 21:31:46 +0000285 call pci_bios_select_register
wdenk7a8e9bed2003-05-31 18:35:21 +0000286gs movl OFFS_ECX(%bp), %eax
287 movw $0xcfc, %dx
288 outl %eax, %dx
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200289 jmp clear_carry
wdenk7a8e9bed2003-05-31 18:35:21 +0000290
291/*****************************************************************************/
292
293pci_bios_get_irq_routing:
294#ifdef PCI_BIOS_DEBUG
295cs incl num_pci_bios_get_irq_routing
296#endif
297 movb $0x81, %ah /* function not supported */
298 jmp set_carry
wdenk8bde7f72003-06-27 21:31:46 +0000299
wdenk7a8e9bed2003-05-31 18:35:21 +0000300/*****************************************************************************/
301
302pci_bios_set_irq:
303#ifdef PCI_BIOS_DEBUG
304cs incl num_pci_bios_set_irq
305#endif
306 movb $0x81, %ah /* function not supported */
307 jmp set_carry
308
309/*****************************************************************************/
310
311unknown_function:
312#ifdef PCI_BIOS_DEBUG
313cs incl num_pci_bios_unknown_function
314#endif
315 movb $0x81, %ah /* function not supported */
316 jmp set_carry
317
318/*****************************************************************************/
wdenk8bde7f72003-06-27 21:31:46 +0000319
wdenk7a8e9bed2003-05-31 18:35:21 +0000320pci_bios_select_register:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200321gs movw OFFS_BX(%bp), %bx
322gs movw OFFS_DI(%bp), %ax
wdenk7a8e9bed2003-05-31 18:35:21 +0000323/* destroys eax, dx */
324__pci_bios_select_register: /* BX holds device id, AX holds register index */
325 pushl %ebx
326 andl $0xfc, %eax
327 andl $0xffff, %ebx
328 shll $8, %ebx
329 orl %ebx, %eax
330 orl $0x80000000, %eax
331 movw $0xcf8, %dx
332 outl %eax, %dx
333 popl %ebx
334 ret
335
336
337clear_carry:
338gs movw OFFS_FLAGS(%bp), %ax
339 andw $0xfffe, %ax /* clear carry -- function succeeded */
340gs movw %ax, OFFS_FLAGS(%bp)
341 xorw %ax, %ax
wdenk8bde7f72003-06-27 21:31:46 +0000342gs movb %ah, OFFS_AH(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000343 ret
344
345set_carry:
wdenk8bde7f72003-06-27 21:31:46 +0000346gs movb %ah, OFFS_AH(%bp)
wdenk7a8e9bed2003-05-31 18:35:21 +0000347gs movw OFFS_FLAGS(%bp), %ax
348 orw $1, %ax /* return carry -- function not supported */
349gs movw %ax, OFFS_FLAGS(%bp)
350 movw $-1, %ax
351 ret
352
353/*****************************************************************************/
354
355.globl pci_last_bus
356pci_last_bus:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200357 .byte 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000358
359#ifdef PCI_BIOS_DEBUG
360.globl num_pci_bios_present
361num_pci_bios_present:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200362 .long 0
wdenk8bde7f72003-06-27 21:31:46 +0000363
wdenk7a8e9bed2003-05-31 18:35:21 +0000364.globl num_pci_bios_find_device
365num_pci_bios_find_device:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200366 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000367
368.globl num_pci_bios_find_class
369num_pci_bios_find_class:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200370 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000371
372.globl num_pci_bios_generate_special_cycle
wdenk8bde7f72003-06-27 21:31:46 +0000373num_pci_bios_generate_special_cycle:
wdenk7a8e9bed2003-05-31 18:35:21 +0000374 .long 0
wdenk8bde7f72003-06-27 21:31:46 +0000375
wdenk7a8e9bed2003-05-31 18:35:21 +0000376.globl num_pci_bios_read_cfg_byte
377num_pci_bios_read_cfg_byte:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200378 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000379
380.globl num_pci_bios_read_cfg_word
381num_pci_bios_read_cfg_word:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200382 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000383
384.globl num_pci_bios_read_cfg_dword
385num_pci_bios_read_cfg_dword:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200386 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000387
388.globl num_pci_bios_write_cfg_byte
389num_pci_bios_write_cfg_byte:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200390 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000391
392.globl num_pci_bios_write_cfg_word
393num_pci_bios_write_cfg_word:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200394 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000395
396.globl num_pci_bios_write_cfg_dword
397num_pci_bios_write_cfg_dword:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200398 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000399
400.globl num_pci_bios_get_irq_routing
401num_pci_bios_get_irq_routing:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200402 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000403
404.globl num_pci_bios_set_irq
405num_pci_bios_set_irq:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200406 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000407
408.globl num_pci_bios_unknown_function
409num_pci_bios_unknown_function:
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200410 .long 0
wdenk7a8e9bed2003-05-31 18:35:21 +0000411#endif