This patch is from 2009-10-20
[coreboot.git] / util / x86emu / x86_interrupts.c
1 /*
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
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21
22 #include <device/pci.h>
23 #include <device/pci_ids.h>
24 #include <device/pci_ops.h>
25 #include <string.h>
26 #include <console/console.h>
27 #include <arch/io.h>
28 #include <arch/registers.h>
29
30 enum {
31         PCIBIOS_CHECK = 0xb101,
32         PCIBIOS_FINDDEV = 0xb102,
33         PCIBIOS_READCONFBYTE = 0xb108,
34         PCIBIOS_READCONFWORD = 0xb109,
35         PCIBIOS_READCONFDWORD = 0xb10a,
36         PCIBIOS_WRITECONFBYTE = 0xb10b,
37         PCIBIOS_WRITECONFWORD = 0xb10c,
38         PCIBIOS_WRITECONFDWORD = 0xb10d
39 };
40
41 // errors go in AH. Just set these up so that word assigns
42 // will work. KISS.
43 enum {
44         PCIBIOS_SUCCESSFUL = 0x0000,
45         PCIBIOS_UNSUPPORTED = 0x8100,
46         PCIBIOS_BADVENDOR = 0x8300,
47         PCIBIOS_NODEV = 0x8600,
48         PCIBIOS_BADREG = 0x8700
49 };
50
51 int int12_handler(struct eregs *regs);
52 int int1a_handler(struct eregs *regs);
53 int int15_handler(struct eregs *regs);
54
55 int int12_handler(struct eregs *regs)
56 {
57         regs->eax = 64 * 1024;
58         return 0;
59 }
60
61 int int1a_handler(struct eregs *regs)
62 {
63         unsigned short func = (unsigned short)regs->eax;
64         int retval = 0;
65         unsigned short devid, vendorid, devfn;
66         /* Use short to get rid of gabage in upper half of 32-bit register */
67         short devindex;
68         unsigned char bus;
69         struct device *dev;
70         u32 dword;
71         u16 word;
72         u8 byte, reg;
73
74         switch (func) {
75         case PCIBIOS_CHECK:
76                 regs->edx = 0x20494350; /* ' ICP' */
77                 regs->edi = 0x00000000; /* protected mode entry */
78                 retval = 0;
79                 break;
80         case PCIBIOS_FINDDEV:
81                 devid = regs->ecx;
82                 vendorid = regs->edx;
83                 devindex = regs->esi;
84                 dev = 0;
85                 while ((dev = dev_find_device(vendorid, devid, dev))) {
86                         if (devindex <= 0)
87                                 break;
88                         devindex--;
89                 }
90                 if (dev) {
91                         unsigned short busdevfn;
92                         regs->eax = 0;
93                         // busnum is an unsigned char;
94                         // devfn is an int, so we mask it off.
95                         busdevfn = (dev->bus->secondary << 8)
96                             | (dev->path.pci.devfn & 0xff);
97                         printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, busdevfn);
98                         regs->ebx = busdevfn;
99                         retval = 0;
100                 } else {
101                         regs->eax = PCIBIOS_NODEV;
102                         retval = -1;
103                 }
104                 break;
105         case PCIBIOS_READCONFDWORD:
106         case PCIBIOS_READCONFWORD:
107         case PCIBIOS_READCONFBYTE:
108         case PCIBIOS_WRITECONFDWORD:
109         case PCIBIOS_WRITECONFWORD:
110         case PCIBIOS_WRITECONFBYTE:
111                 devfn = regs->ebx & 0xff;
112                 bus = regs->ebx >> 8;
113                 reg = regs->edi;
114                 dev = dev_find_slot(bus, devfn);
115                 if (!dev) {
116                         printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
117                         // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
118                         regs->eax = PCIBIOS_BADREG;
119                         retval = -1;
120                         return retval;
121                 }
122                 switch (func) {
123                 case PCIBIOS_READCONFBYTE:
124                         byte = pci_read_config8(dev, reg);
125                         regs->ecx = byte;
126                         break;
127                 case PCIBIOS_READCONFWORD:
128                         word = pci_read_config16(dev, reg);
129                         regs->ecx = word;
130                         break;
131                 case PCIBIOS_READCONFDWORD:
132                         dword = pci_read_config32(dev, reg);
133                         regs->ecx = dword;
134                         break;
135                 case PCIBIOS_WRITECONFBYTE:
136                         byte = regs->ecx;
137                         pci_write_config8(dev, reg, byte);
138                         break;
139                 case PCIBIOS_WRITECONFWORD:
140                         word = regs->ecx;
141                         pci_write_config16(dev, reg, word);
142                         break;
143                 case PCIBIOS_WRITECONFDWORD:
144                         dword = regs->ecx;
145                         pci_write_config32(dev, reg, dword);
146                         break;
147                 }
148
149                 printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n",
150                              func, bus, devfn, reg, regs->ecx);
151                 regs->eax = 0;
152                 retval = 0;
153                 break;
154         default:
155                 printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
156                 retval = -1;
157                 break;
158         }
159
160         return retval;
161 }
162
163 int int15_handler(struct eregs *regs)
164 {
165         int res = -1;
166
167         /* This int15 handler is VIA Tech. specific. Other chipsets need other
168          * handlers. The right way to do this is to move this handler code into
169          * the mainboard or northbridge code.
170          */
171         switch (regs->eax & 0xffff) {
172         case 0x5f19:
173                 break;
174         case 0x5f18:
175                 regs->eax = 0x5f;
176                 // MCLK = 133, 32M frame buffer, 256 M main memory
177                 regs->ebx = 0x545;
178                 regs->ecx = 0x060;
179                 res = 0;
180                 break;
181         case 0x5f00:
182                 regs->eax = 0x8600;
183                 break;
184         case 0x5f01:
185                 regs->eax = 0x5f;
186                 regs->ecx = (regs->ecx & 0xffffff00 ) | 2; // panel type =  2 = 1024 * 768
187                 res = 0;
188                 break;
189         case 0x5f02:
190                 regs->eax = 0x5f;
191                 regs->ebx = (regs->ebx & 0xffff0000) | 2;
192                 regs->ecx = (regs->ecx & 0xffff0000) | 0x401;  // PAL + crt only
193                 regs->edx = (regs->edx & 0xffff0000) | 0;  // TV Layout - default
194                 res = 0;
195                 break;
196         case 0x5f0f:
197                 regs->eax = 0x860f;
198                 break;
199         /* And now Intel IGD code */
200 #define BOOT_DISPLAY_DEFAULT    0
201 #define BOOT_DISPLAY_CRT        (1 << 0)
202 #define BOOT_DISPLAY_TV         (1 << 1)
203 #define BOOT_DISPLAY_EFP        (1 << 2)
204 #define BOOT_DISPLAY_LCD        (1 << 3)
205 #define BOOT_DISPLAY_CRT2       (1 << 4)
206 #define BOOT_DISPLAY_TV2        (1 << 5)
207 #define BOOT_DISPLAY_EFP2       (1 << 6)
208 #define BOOT_DISPLAY_LCD2       (1 << 7)
209
210         case 0x5f35:
211                 regs->eax = 0x5f;
212                 regs->ecx = BOOT_DISPLAY_DEFAULT;
213                 res = 0;
214                 break;
215         case 0x5f40:
216                 regs->eax = 0x5f;
217                 regs->ecx = 3; // This is mainboard specific
218                 printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx);
219                 res = 0;
220                 break;
221         default:
222                 printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", 
223                                 regs->eax & 0xffff);
224         }
225
226         return res;
227 }
228