/[gxemul]/upstream/0.3.1/devices/bus_pci.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.1/devices/bus_pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Mon Oct 8 16:17:52 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 6367 byte(s)
0.3.1
1 /*
2 * Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: bus_pci.c,v 1.10 2005/03/18 23:20:52 debug Exp $
29 *
30 * This is a generic PCI bus device, used by even lower level devices.
31 * For example, the "gt" device used in Cobalt machines contains a PCI
32 * device.
33 *
34 * TODO: This more or less just a dummy bus device, so far.
35 */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "memory.h"
42 #include "misc.h"
43
44 #include "bus_pci.h"
45
46
47 /*
48 * bus_pci_access():
49 *
50 * relative_addr should be either BUS_PCI_ADDR or BUS_PCI_DATA. The uint64_t
51 * pointed to by data should contain the word to be written to the pci bus,
52 * or a placeholder for information read from the bus.
53 *
54 * Returns 1 if ok, 0 on error.
55 */
56 int bus_pci_access(struct cpu *cpu, struct memory *mem, uint64_t relative_addr,
57 uint64_t *data, int writeflag, struct pci_data *pci_data)
58 {
59 struct pci_device *dev, *found;
60 int bus, device, function, registernr;
61
62 if (writeflag == MEM_READ)
63 *data = 0;
64
65 switch (relative_addr) {
66 case BUS_PCI_ADDR:
67 if (writeflag == MEM_WRITE) {
68 debug("[ bus_pci: write to PCI ADDR: data = 0x%016llx"
69 " ]\n", (long long)*data);
70 pci_data->pci_addr = *data;
71 } else {
72 debug("[ bus_pci: read from PCI ADDR (data = "
73 "0x%016llx) ]\n", (long long)pci_data->pci_addr);
74 *data = pci_data->pci_addr;
75 }
76 break;
77 case BUS_PCI_DATA:
78 if (writeflag == MEM_WRITE) {
79 debug("[ bus_pci: write to PCI DATA: data = "
80 "0x%016llx ]\n", (long long)*data);
81 if (*data == 0xffffffffULL)
82 pci_data->last_was_write_ffffffff = 1;
83 } else {
84 /* Get the bus, device, and function numbers from
85 the address: */
86 bus = (pci_data->pci_addr >> 16) & 0xff;
87 device = (pci_data->pci_addr >> 11) & 0x1f;
88 function = (pci_data->pci_addr >> 8) & 0x7;
89 registernr = (pci_data->pci_addr) & 0xff;
90
91 /* Scan through the list of pci_device entries. */
92 dev = pci_data->first_device;
93 found = NULL;
94
95 while (dev != NULL && found == NULL) {
96 if (dev->bus == bus &&
97 dev->function == function &&
98 dev->device == device)
99 found = dev;
100 dev = dev->next;
101 }
102
103 if (found == NULL) {
104 if ((pci_data->pci_addr & 0xff) == 0)
105 *data = 0xffffffff;
106 else
107 *data = 0;
108 return 1;
109 }
110
111 *data = 0;
112
113 if (pci_data->last_was_write_ffffffff &&
114 registernr >= 0x10 && registernr <= 0x24) {
115 /* TODO: real length!!! */
116 *data = 0x00400000 - 1;
117 } else if (found->read_register != NULL)
118 *data = found->read_register(registernr);
119
120 pci_data->last_was_write_ffffffff = 0;
121
122 debug("[ bus_pci: read from PCI DATA, addr = 0x%08lx "
123 "(bus %i, device %i, function %i, register "
124 "0x%02x): 0x%08lx ]\n", (long)pci_data->pci_addr,
125 bus, device, function, registernr, (long)*data);
126 }
127
128 break;
129 default:
130 if (writeflag==MEM_READ) {
131 debug("[ bus_pci: read from unimplemented addr "
132 "0x%x ]\n", (int)relative_addr);
133 *data = 0;
134 } else {
135 debug("[ bus_pci: write to unimplemented addr "
136 "0x%x:", (int)relative_addr);
137 }
138 }
139
140 return 1;
141 }
142
143
144 /*
145 * bus_pci_add():
146 *
147 * Add a PCI device to a bus_pci device.
148 */
149 void bus_pci_add(struct machine *machine, struct pci_data *pci_data,
150 struct memory *mem, int bus, int device, int function,
151 void (*init)(struct machine *, struct memory *),
152 uint32_t (*read_register)(int reg))
153 {
154 struct pci_device *new_device;
155
156 /* Make sure this bus/device/function number isn't already in use: */
157 new_device = pci_data->first_device;
158 while (new_device != NULL) {
159 if (new_device->bus == bus &&
160 new_device->device == device &&
161 new_device->function == function) {
162 fatal("bus_pci_add(): (bus %i, device %i, function"
163 " %i) already in use\n", bus, device, function);
164 return;
165 }
166 new_device = new_device->next;
167 }
168
169 new_device = malloc(sizeof(struct pci_device));
170 if (new_device == NULL) {
171 fprintf(stderr, "out of memory\n");
172 exit(1);
173 }
174
175 memset(new_device, 0, sizeof(struct pci_device));
176 new_device->bus = bus;
177 new_device->device = device;
178 new_device->function = function;
179 new_device->init = init;
180 new_device->read_register = read_register;
181
182 /* Add the new device first in the PCI bus' chain: */
183 new_device->next = pci_data->first_device;
184 pci_data->first_device = new_device;
185
186 /* Call the PCI device' init function: */
187 if (init != NULL)
188 init(machine, mem);
189 }
190
191
192 /*
193 * bus_pci_init():
194 *
195 * This doesn't register a device, but instead returns a pointer to a struct
196 * which should be passed to bus_pci_access() when accessing the PCI bus.
197 */
198 struct pci_data *bus_pci_init(int irq_nr)
199 {
200 struct pci_data *d;
201
202 d = malloc(sizeof(struct pci_data));
203 if (d == NULL) {
204 fprintf(stderr, "out of memory\n");
205 exit(1);
206 }
207 memset(d, 0, sizeof(struct pci_data));
208 d->irq_nr = irq_nr;
209
210 return d;
211 }
212

  ViewVC Help
Powered by ViewVC 1.1.26