1 /* tag: openbios pci plugin
3 * Copyright (C) 2003 Stefan Reinauer
5 * See the file "COPYING" for further information about
6 * the copyright and warranty status of this work.
11 #include "unix/plugins.h"
12 #include "unix/plugin_pci.h"
16 u32 pci_conf_addr = 0;
17 pci_dev_t *pci_devices = NULL;
19 static pci_dev_t *find_device(u32 conf_addr)
21 pci_dev_t *devs = pci_devices;
22 unsigned bus = (conf_addr >> 16) & 0xff;
23 unsigned dev = (conf_addr >> 11) & 0x1f;
24 unsigned fn = (conf_addr >> 8) & 0x7;
26 // printf("Looking for device %x\n",conf_addr);
29 if (devs->bus == bus && devs->dev == dev && devs->fn == fn)
37 * IO functions. These manage all the magic of providing a PCI
38 * compatible interface to OpenBIOS' unix version of the kernel.
41 static u8 pci_inb(u32 reg)
43 u32 basereg = (reg & 0xfffc);
44 u32 basepos = (reg & 0x03);
47 if (basereg == 0xcf8) {
48 return (pci_conf_addr >> (basepos << 3));
51 /* still here? so we're 0xCFC */
52 dev = find_device(pci_conf_addr);
53 if (!dev || !dev->config)
56 return dev->config[(pci_conf_addr + basepos) & 0xff];
59 static u16 pci_inw(u32 reg)
61 u32 basereg = (reg & 0xfffc);
62 u32 basepos = (reg & 0x02);
65 if (basereg == 0xcf8) {
66 return (pci_conf_addr >> (basepos << 3));
69 /* still here? so we're 0xCFC */
70 dev = find_device(pci_conf_addr);
71 if (!dev || !dev->config)
74 return *(u16 *) (dev->config + ((pci_conf_addr + basepos) & 0xff));
77 static u32 pci_inl(u32 reg)
79 u32 basereg = (reg & 0xfffc);
82 if (basereg == 0xcf8) {
86 /* still here? so we're 0xCFC */
87 dev = find_device(pci_conf_addr);
88 if (!dev || !dev->config)
91 return *(u32 *) (dev->config + (pci_conf_addr & 0xff));
94 static void pci_outb(u32 reg, u8 val)
96 u32 basereg = (reg & 0xfffc);
97 u32 basepos = (reg & 0x03);
100 if (basereg == 0xcf8) {
101 pci_conf_addr &= (~(0xff << (basepos << 3)));
102 pci_conf_addr |= (val << (basepos << 3));
106 /* still here? so we're 0xCFC */
107 dev = find_device(pci_conf_addr);
108 if (!dev || !dev->config)
111 dev->config[pci_conf_addr & 0xff] = val;
114 static void pci_outw(u32 reg, u16 val)
116 u32 basereg = (reg & 0xfffc);
117 u32 basepos = (reg & 0x02);
120 if (basereg == 0xcf8) {
121 pci_conf_addr &= (~(0xffff << (basepos << 3)));
122 pci_conf_addr |= (val << (basepos << 3));
126 /* still here? so we're 0xCFC */
127 dev = find_device(pci_conf_addr);
128 if (!dev || !dev->config)
131 *(u16 *) (dev->config + (pci_conf_addr & 0xff)) = val;
134 static void pci_outl(u32 reg, u32 val)
136 u32 basereg = (reg & 0xfffc);
139 if (basereg == 0xcf8) {
144 /* still here? so we're 0xCFC */
145 dev = find_device(pci_conf_addr);
146 if (!dev || !dev->config)
149 *(u32 *) (dev->config + (pci_conf_addr & 0xff)) = val;
152 static io_ops_t pci_io_ops = {
162 * Functions visible to modules depending on this module.
165 int pci_register_device(unsigned bus, unsigned dev, unsigned fn,
169 u32 caddr = (1 << 31) | (bus << 16) | (dev << 11) | (fn << 8);
171 if (find_device(caddr)) {
172 printf("Error: pci device %02x:%02x.%01x already exists\n",
177 newdev = malloc(sizeof(pci_dev_t));
180 printf("Out of memory\n");
187 newdev->config = config;
188 newdev->next = pci_devices;
190 pci_devices = newdev;
196 * Initialization is really simple. We just grab the
197 * PCI conf1 io range for our emulation functions.
199 extern int plugin_pci_init( void );
201 int plugin_pci_init(void)
204 printf("Plugin \"pci\" initializing... ");
206 register_iorange("pci", &pci_io_ops, 0xcf8, 0xcff);
213 /* plugin meta information available for the plugin loader */
214 PLUGIN_AUTHOR ("Stefan Reinauer <stepan@openbios.org>")
215 PLUGIN_DESCRIPTION ("Generic PCI Device Emulation")
216 PLUGIN_LICENSE ("GPL v2")
218 /* This plugin has no dependencies. Otherwise the following
219 * macro would be uncommented:
220 * PLUGIN_DEPENDENCIES ("this", "that")