blob: 73bfe51099c220c592d4dd32ec2cba8ebbd4ab84 [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2001 Ronald G. Minnich
5 * Copyright (C) 2005 Nick.Barker9@btinternet.com
6 * Copyright (C) 2007-2009 coresystems GmbH
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
Stefan Reinauer6c641ee2009-09-23 21:52:45 +000019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000020 */
21
22#include <device/pci.h>
23#include <device/pci_ids.h>
24#include <device/pci_ops.h>
25#include <string.h>
26#ifdef CONFIG_COREBOOT_V2
27#include <console/console.h>
28#include <arch/io.h>
Stefan Reinauer42dc7212009-10-24 00:47:07 +000029#include <arch/registers.h>
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000030#define printk(x...) do_printk(x)
31#else
32#include <console.h>
33#include <io.h>
34#endif
35
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000036enum {
37 CHECK = 0xb001,
38 FINDDEV = 0xb102,
39 READCONFBYTE = 0xb108,
40 READCONFWORD = 0xb109,
41 READCONFDWORD = 0xb10a,
42 WRITECONFBYTE = 0xb10b,
43 WRITECONFWORD = 0xb10c,
44 WRITECONFDWORD = 0xb10d
45};
46
47// errors go in AH. Just set these up so that word assigns
48// will work. KISS.
49enum {
50 PCIBIOS_NODEV = 0x8600,
51 PCIBIOS_BADREG = 0x8700
52};
53
Maciej Pijankaea921852009-10-27 14:29:29 +000054int int12_handler(struct eregs *regs);
55int int1a_handler(struct eregs *regs);
56int int15_handler(struct eregs *regs);
57
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000058int int12_handler(struct eregs *regs)
59{
60 regs->eax = 64 * 1024;
61 return 0;
62}
63
64int int1a_handler(struct eregs *regs)
65{
66 unsigned short func = (unsigned short) regs->eax;
67 int retval = 0;
68 unsigned short devid, vendorid, devfn;
69 /* Use short to get rid of gabage in upper half of 32-bit register */
70 short devindex;
71 unsigned char bus;
72 struct device *dev;
73
74 switch(func) {
75 case CHECK:
76 regs->edx = 0x4350;
77 regs->ecx = 0x2049;
78 retval = 0;
79 break;
80 case FINDDEV:
81 {
82 devid = regs->ecx;
83 vendorid = regs->edx;
84 devindex = regs->esi;
85 dev = 0;
86#ifdef CONFIG_COREBOOT_V2
87 while ((dev = dev_find_device(vendorid, devid, dev))) {
88#else
89 while ((dev = dev_find_pci_device(vendorid, devid, dev))) {
90#endif
91 if (devindex <= 0)
92 break;
93 devindex--;
94 }
95 if (dev) {
96 unsigned short busdevfn;
97 regs->eax = 0;
98 // busnum is an unsigned char;
99 // devfn is an int, so we mask it off.
100 busdevfn = (dev->bus->secondary << 8)
101 | (dev->path.pci.devfn & 0xff);
102 printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
103 regs->ebx = busdevfn;
104 retval = 0;
105 } else {
106 regs->eax = PCIBIOS_NODEV;
107 retval = -1;
108 }
109 }
110 break;
111 case READCONFDWORD:
112 case READCONFWORD:
113 case READCONFBYTE:
114 case WRITECONFDWORD:
115 case WRITECONFWORD:
116 case WRITECONFBYTE:
117 {
118 unsigned long dword;
119 unsigned short word;
120 unsigned char byte;
121 unsigned char reg;
122
123 devfn = regs->ebx & 0xff;
124 bus = regs->ebx >> 8;
125 reg = regs->edi;
126 dev = dev_find_slot(bus, devfn);
127 if (! dev) {
128 printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
129 // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
130 regs->eax = PCIBIOS_BADREG;
131 retval = -1;
132 }
133 switch(func) {
134 case READCONFBYTE:
135 byte = pci_read_config8(dev, reg);
136 regs->ecx = byte;
137 break;
138 case READCONFWORD:
139 word = pci_read_config16(dev, reg);
140 regs->ecx = word;
141 break;
142 case READCONFDWORD:
143 dword = pci_read_config32(dev, reg);
144 regs->ecx = dword;
145 break;
146 case WRITECONFBYTE:
147 byte = regs->ecx;
148 pci_write_config8(dev, reg, byte);
149 break;
150 case WRITECONFWORD:
151 word = regs->ecx;
152 pci_write_config16(dev, reg, word);
153 break;
154 case WRITECONFDWORD:
155 dword = regs->ecx;
156 pci_write_config32(dev, reg, dword);
157 break;
158 }
159
160 if (retval)
161 retval = PCIBIOS_BADREG;
162 printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
163 func, bus, devfn, reg, regs->ecx);
164 regs->eax = 0;
165 retval = 0;
166 }
167 break;
168 default:
169 printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
170 break;
171 }
172
173 return retval;
174}
175
176int int15_handler(struct eregs *regs)
177{
178 int res = -1;
179
180 /* This int15 handler is VIA Tech. specific. Other chipsets need other
181 * handlers. The right way to do this is to move this handler code into
182 * the mainboard or northbridge code.
183 */
184 switch (regs->eax & 0xffff) {
185 case 0x5f19:
186 break;
187 case 0x5f18:
188 regs->eax = 0x5f;
189 // MCLK = 133, 32M frame buffer, 256 M main memory
190 regs->ebx = 0x545;
191 regs->ecx = 0x060;
192 res = 0;
193 break;
194 case 0x5f00:
195 regs->eax = 0x8600;
196 break;
197 case 0x5f01:
198 regs->eax = 0x5f;
199 regs->ecx = (regs->ecx & 0xffffff00 ) | 2; // panel type = 2 = 1024 * 768
200 res = 0;
201 break;
202 case 0x5f02:
203 regs->eax = 0x5f;
204 regs->ebx = (regs->ebx & 0xffff0000) | 2;
205 regs->ecx = (regs->ecx & 0xffff0000) | 0x401; // PAL + crt only
206 regs->edx = (regs->edx & 0xffff0000) | 0; // TV Layout - default
207 res = 0;
208 break;
209 case 0x5f0f:
210 regs->eax = 0x860f;
211 break;
212 /* And now Intel IGD code */
Stefan Reinauer074356e2009-10-25 19:50:47 +0000213#define BOOT_DISPLAY_DEFAULT 0
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000214#define BOOT_DISPLAY_CRT (1 << 0)
215#define BOOT_DISPLAY_TV (1 << 1)
216#define BOOT_DISPLAY_EFP (1 << 2)
217#define BOOT_DISPLAY_LCD (1 << 3)
218#define BOOT_DISPLAY_CRT2 (1 << 4)
219#define BOOT_DISPLAY_TV2 (1 << 5)
220#define BOOT_DISPLAY_EFP2 (1 << 6)
221#define BOOT_DISPLAY_LCD2 (1 << 7)
222
223 case 0x5f35:
224 regs->eax = 0x5f;
Stefan Reinauer074356e2009-10-25 19:50:47 +0000225 regs->ecx = BOOT_DISPLAY_DEFAULT;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000226 res = 0;
227 break;
228 case 0x5f40:
229 regs->eax = 0x5f;
230 regs->ecx = 3; // This is mainboard specific
231 printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx);
232 res = 0;
233 break;
234 default:
235 printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n",
236 regs->eax & 0xffff);
237 }
238
239 return res;
240}
241