blob: 556e81043aac4944fb026499b3617e7ea61527d9 [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
54int int12_handler(struct eregs *regs)
55{
56 regs->eax = 64 * 1024;
57 return 0;
58}
59
60int int1a_handler(struct eregs *regs)
61{
62 unsigned short func = (unsigned short) regs->eax;
63 int retval = 0;
64 unsigned short devid, vendorid, devfn;
65 /* Use short to get rid of gabage in upper half of 32-bit register */
66 short devindex;
67 unsigned char bus;
68 struct device *dev;
69
70 switch(func) {
71 case CHECK:
72 regs->edx = 0x4350;
73 regs->ecx = 0x2049;
74 retval = 0;
75 break;
76 case FINDDEV:
77 {
78 devid = regs->ecx;
79 vendorid = regs->edx;
80 devindex = regs->esi;
81 dev = 0;
82#ifdef CONFIG_COREBOOT_V2
83 while ((dev = dev_find_device(vendorid, devid, dev))) {
84#else
85 while ((dev = dev_find_pci_device(vendorid, devid, dev))) {
86#endif
87 if (devindex <= 0)
88 break;
89 devindex--;
90 }
91 if (dev) {
92 unsigned short busdevfn;
93 regs->eax = 0;
94 // busnum is an unsigned char;
95 // devfn is an int, so we mask it off.
96 busdevfn = (dev->bus->secondary << 8)
97 | (dev->path.pci.devfn & 0xff);
98 printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
99 regs->ebx = busdevfn;
100 retval = 0;
101 } else {
102 regs->eax = PCIBIOS_NODEV;
103 retval = -1;
104 }
105 }
106 break;
107 case READCONFDWORD:
108 case READCONFWORD:
109 case READCONFBYTE:
110 case WRITECONFDWORD:
111 case WRITECONFWORD:
112 case WRITECONFBYTE:
113 {
114 unsigned long dword;
115 unsigned short word;
116 unsigned char byte;
117 unsigned char reg;
118
119 devfn = regs->ebx & 0xff;
120 bus = regs->ebx >> 8;
121 reg = regs->edi;
122 dev = dev_find_slot(bus, devfn);
123 if (! dev) {
124 printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
125 // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
126 regs->eax = PCIBIOS_BADREG;
127 retval = -1;
128 }
129 switch(func) {
130 case READCONFBYTE:
131 byte = pci_read_config8(dev, reg);
132 regs->ecx = byte;
133 break;
134 case READCONFWORD:
135 word = pci_read_config16(dev, reg);
136 regs->ecx = word;
137 break;
138 case READCONFDWORD:
139 dword = pci_read_config32(dev, reg);
140 regs->ecx = dword;
141 break;
142 case WRITECONFBYTE:
143 byte = regs->ecx;
144 pci_write_config8(dev, reg, byte);
145 break;
146 case WRITECONFWORD:
147 word = regs->ecx;
148 pci_write_config16(dev, reg, word);
149 break;
150 case WRITECONFDWORD:
151 dword = regs->ecx;
152 pci_write_config32(dev, reg, dword);
153 break;
154 }
155
156 if (retval)
157 retval = PCIBIOS_BADREG;
158 printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
159 func, bus, devfn, reg, regs->ecx);
160 regs->eax = 0;
161 retval = 0;
162 }
163 break;
164 default:
165 printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
166 break;
167 }
168
169 return retval;
170}
171
172int int15_handler(struct eregs *regs)
173{
174 int res = -1;
175
176 /* This int15 handler is VIA Tech. specific. Other chipsets need other
177 * handlers. The right way to do this is to move this handler code into
178 * the mainboard or northbridge code.
179 */
180 switch (regs->eax & 0xffff) {
181 case 0x5f19:
182 break;
183 case 0x5f18:
184 regs->eax = 0x5f;
185 // MCLK = 133, 32M frame buffer, 256 M main memory
186 regs->ebx = 0x545;
187 regs->ecx = 0x060;
188 res = 0;
189 break;
190 case 0x5f00:
191 regs->eax = 0x8600;
192 break;
193 case 0x5f01:
194 regs->eax = 0x5f;
195 regs->ecx = (regs->ecx & 0xffffff00 ) | 2; // panel type = 2 = 1024 * 768
196 res = 0;
197 break;
198 case 0x5f02:
199 regs->eax = 0x5f;
200 regs->ebx = (regs->ebx & 0xffff0000) | 2;
201 regs->ecx = (regs->ecx & 0xffff0000) | 0x401; // PAL + crt only
202 regs->edx = (regs->edx & 0xffff0000) | 0; // TV Layout - default
203 res = 0;
204 break;
205 case 0x5f0f:
206 regs->eax = 0x860f;
207 break;
208 /* And now Intel IGD code */
Stefan Reinauer074356e2009-10-25 19:50:47 +0000209#define BOOT_DISPLAY_DEFAULT 0
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000210#define BOOT_DISPLAY_CRT (1 << 0)
211#define BOOT_DISPLAY_TV (1 << 1)
212#define BOOT_DISPLAY_EFP (1 << 2)
213#define BOOT_DISPLAY_LCD (1 << 3)
214#define BOOT_DISPLAY_CRT2 (1 << 4)
215#define BOOT_DISPLAY_TV2 (1 << 5)
216#define BOOT_DISPLAY_EFP2 (1 << 6)
217#define BOOT_DISPLAY_LCD2 (1 << 7)
218
219 case 0x5f35:
220 regs->eax = 0x5f;
Stefan Reinauer074356e2009-10-25 19:50:47 +0000221 regs->ecx = BOOT_DISPLAY_DEFAULT;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000222 res = 0;
223 break;
224 case 0x5f40:
225 regs->eax = 0x5f;
226 regs->ecx = 3; // This is mainboard specific
227 printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx);
228 res = 0;
229 break;
230 default:
231 printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n",
232 regs->eax & 0xffff);
233 }
234
235 return res;
236}
237