blob: 2c63f438e33f1f58c9485e74bf0ca7cdd75abe28 [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 {
Mark Marshalld08e69d2009-11-05 09:03:04 +000037 PCIBIOS_CHECK = 0xb101,
38 PCIBIOS_FINDDEV = 0xb102,
39 PCIBIOS_READCONFBYTE = 0xb108,
40 PCIBIOS_READCONFWORD = 0xb109,
41 PCIBIOS_READCONFDWORD = 0xb10a,
42 PCIBIOS_WRITECONFBYTE = 0xb10b,
43 PCIBIOS_WRITECONFWORD = 0xb10c,
44 PCIBIOS_WRITECONFDWORD = 0xb10d
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000045};
46
47// errors go in AH. Just set these up so that word assigns
48// will work. KISS.
49enum {
Mark Marshalld08e69d2009-11-05 09:03:04 +000050 PCIBIOS_SUCCESSFUL = 0x0000,
51 PCIBIOS_UNSUPPORTED = 0x8100,
52 PCIBIOS_BADVENDOR = 0x8300,
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000053 PCIBIOS_NODEV = 0x8600,
54 PCIBIOS_BADREG = 0x8700
55};
56
Maciej Pijankaea921852009-10-27 14:29:29 +000057int int12_handler(struct eregs *regs);
58int int1a_handler(struct eregs *regs);
59int int15_handler(struct eregs *regs);
60
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000061int int12_handler(struct eregs *regs)
62{
63 regs->eax = 64 * 1024;
64 return 0;
65}
66
67int int1a_handler(struct eregs *regs)
68{
Mark Marshalld08e69d2009-11-05 09:03:04 +000069 unsigned short func = (unsigned short)regs->eax;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000070 int retval = 0;
71 unsigned short devid, vendorid, devfn;
72 /* Use short to get rid of gabage in upper half of 32-bit register */
73 short devindex;
74 unsigned char bus;
75 struct device *dev;
76
Mark Marshalld08e69d2009-11-05 09:03:04 +000077 switch (func) {
78 case PCIBIOS_CHECK:
79 regs->edx = 0x20494350; /* ' ICP' */
80 regs->edi = 0x00000000; /* protected mode entry */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000081 retval = 0;
82 break;
Mark Marshalld08e69d2009-11-05 09:03:04 +000083 case PCIBIOS_FINDDEV:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000084 devid = regs->ecx;
85 vendorid = regs->edx;
86 devindex = regs->esi;
87 dev = 0;
88#ifdef CONFIG_COREBOOT_V2
89 while ((dev = dev_find_device(vendorid, devid, dev))) {
90#else
91 while ((dev = dev_find_pci_device(vendorid, devid, dev))) {
92#endif
93 if (devindex <= 0)
94 break;
95 devindex--;
96 }
97 if (dev) {
98 unsigned short busdevfn;
99 regs->eax = 0;
100 // busnum is an unsigned char;
101 // devfn is an int, so we mask it off.
102 busdevfn = (dev->bus->secondary << 8)
Mark Marshalld08e69d2009-11-05 09:03:04 +0000103 | (dev->path.pci.devfn & 0xff);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000104 printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
105 regs->ebx = busdevfn;
106 retval = 0;
107 } else {
108 regs->eax = PCIBIOS_NODEV;
109 retval = -1;
110 }
Mark Marshalld08e69d2009-11-05 09:03:04 +0000111 break;
112 case PCIBIOS_READCONFDWORD:
113 case PCIBIOS_READCONFWORD:
114 case PCIBIOS_READCONFBYTE:
115 case PCIBIOS_WRITECONFDWORD:
116 case PCIBIOS_WRITECONFWORD:
117 case PCIBIOS_WRITECONFBYTE:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000118 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);
Mark Marshalld08e69d2009-11-05 09:03:04 +0000127 if (!dev) {
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000128 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;
Mark Marshalld08e69d2009-11-05 09:03:04 +0000132 return retval;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000133 }
Mark Marshalld08e69d2009-11-05 09:03:04 +0000134 switch (func) {
135 case PCIBIOS_READCONFBYTE:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000136 byte = pci_read_config8(dev, reg);
137 regs->ecx = byte;
138 break;
Mark Marshalld08e69d2009-11-05 09:03:04 +0000139 case PCIBIOS_READCONFWORD:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000140 word = pci_read_config16(dev, reg);
141 regs->ecx = word;
142 break;
Mark Marshalld08e69d2009-11-05 09:03:04 +0000143 case PCIBIOS_READCONFDWORD:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000144 dword = pci_read_config32(dev, reg);
145 regs->ecx = dword;
146 break;
Mark Marshalld08e69d2009-11-05 09:03:04 +0000147 case PCIBIOS_WRITECONFBYTE:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000148 byte = regs->ecx;
149 pci_write_config8(dev, reg, byte);
150 break;
Mark Marshalld08e69d2009-11-05 09:03:04 +0000151 case PCIBIOS_WRITECONFWORD:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000152 word = regs->ecx;
153 pci_write_config16(dev, reg, word);
154 break;
Mark Marshalld08e69d2009-11-05 09:03:04 +0000155 case PCIBIOS_WRITECONFDWORD:
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000156 dword = regs->ecx;
157 pci_write_config32(dev, reg, dword);
158 break;
159 }
160
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000161 printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
162 func, bus, devfn, reg, regs->ecx);
163 regs->eax = 0;
164 retval = 0;
Mark Marshalld08e69d2009-11-05 09:03:04 +0000165 break;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000166 default:
Mark Marshalld08e69d2009-11-05 09:03:04 +0000167 printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
168 retval = -1;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000169 break;
170 }
171
172 return retval;
173}
174
175int int15_handler(struct eregs *regs)
176{
177 int res = -1;
178
179 /* This int15 handler is VIA Tech. specific. Other chipsets need other
180 * handlers. The right way to do this is to move this handler code into
181 * the mainboard or northbridge code.
182 */
183 switch (regs->eax & 0xffff) {
184 case 0x5f19:
185 break;
186 case 0x5f18:
187 regs->eax = 0x5f;
188 // MCLK = 133, 32M frame buffer, 256 M main memory
189 regs->ebx = 0x545;
190 regs->ecx = 0x060;
191 res = 0;
192 break;
193 case 0x5f00:
194 regs->eax = 0x8600;
195 break;
196 case 0x5f01:
197 regs->eax = 0x5f;
198 regs->ecx = (regs->ecx & 0xffffff00 ) | 2; // panel type = 2 = 1024 * 768
199 res = 0;
200 break;
201 case 0x5f02:
202 regs->eax = 0x5f;
203 regs->ebx = (regs->ebx & 0xffff0000) | 2;
204 regs->ecx = (regs->ecx & 0xffff0000) | 0x401; // PAL + crt only
205 regs->edx = (regs->edx & 0xffff0000) | 0; // TV Layout - default
206 res = 0;
207 break;
208 case 0x5f0f:
209 regs->eax = 0x860f;
210 break;
211 /* And now Intel IGD code */
Stefan Reinauer074356e2009-10-25 19:50:47 +0000212#define BOOT_DISPLAY_DEFAULT 0
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000213#define BOOT_DISPLAY_CRT (1 << 0)
214#define BOOT_DISPLAY_TV (1 << 1)
215#define BOOT_DISPLAY_EFP (1 << 2)
216#define BOOT_DISPLAY_LCD (1 << 3)
217#define BOOT_DISPLAY_CRT2 (1 << 4)
218#define BOOT_DISPLAY_TV2 (1 << 5)
219#define BOOT_DISPLAY_EFP2 (1 << 6)
220#define BOOT_DISPLAY_LCD2 (1 << 7)
221
222 case 0x5f35:
223 regs->eax = 0x5f;
Stefan Reinauer074356e2009-10-25 19:50:47 +0000224 regs->ecx = BOOT_DISPLAY_DEFAULT;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000225 res = 0;
226 break;
227 case 0x5f40:
228 regs->eax = 0x5f;
229 regs->ecx = 3; // This is mainboard specific
230 printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx);
231 res = 0;
232 break;
233 default:
234 printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n",
235 regs->eax & 0xffff);
236 }
237
238 return res;
239}
240