fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/devices/pci.c *
7 * Created: 2004-06-05 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2009 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include <stdio.h>
24#include <stdlib.h>
25
26#include "memory.h"
27#include "pci.h"
28
29
30void pci_dev_init (pci_dev_t *dev)
31{
32 unsigned i;
33
34 dev->index = 0;
35
36 for (i = 0; i < PCI_REG_MAX; i++) {
37 dev->reg[i] = NULL;
38 }
39
40 for (i = 0; i < PCI_MEM_MAX; i++) {
41 dev->mem[i] = NULL;
42 }
43
44 for (i = 0; i < 256; i++) {
45 dev->config[i] = 0;
46 dev->wrmask[i] = 0;
47 }
48
49 dev->config[0] = 0xff;
50 dev->config[1] = 0xff;
51
52 dev->cfg_ext = NULL;
53 dev->get_cfg8 = NULL;
54 dev->get_cfg16 = NULL;
55 dev->get_cfg32 = NULL;
56 dev->set_cfg8 = NULL;
57 dev->get_cfg16 = NULL;
58 dev->set_cfg32 = NULL;
59
60 for (i = 0; i < 4; i++) {
61 dev->intr[i] = NULL;
62 dev->intr_ext[i] = NULL;
63 dev->intr_val[i] = 0;
64 }
65
66 dev->ext = NULL;
67}
68
69void pci_dev_free (pci_dev_t *dev)
70{
71}
72
73void pci_dev_set_intr_fct (pci_dev_t *dev, unsigned intr, void *ext, void *fct)
74{
75 if (intr < 4) {
76 dev->intr[intr] = fct;
77 dev->intr_ext[intr] = ext;
78 dev->intr_val[intr] = 0;
79 }
80}
81
82void pci_dev_set_intr (pci_dev_t *dev, unsigned intr, unsigned char val)
83{
84 if (intr >= 4) {
85 return;
86 }
87
88 val = (val != 0);
89
90 if (val != dev->intr_val[intr]) {
91 dev->intr_val[intr] = val;
92
93 if (dev->intr[intr] != NULL) {
94 dev->intr[intr] (dev->intr_ext[intr], val);
95 }
96
97 if (dev->pci != NULL) {
98 pci_set_intr (dev->pci, dev->index, intr, val);
99 }
100 }
101}
102
103void pci_dev_set_inta (pci_dev_t *dev, unsigned char val)
104{
105 pci_dev_set_intr (dev, 0, val);
106}
107
108void pci_dev_set_intb (pci_dev_t *dev, unsigned char val)
109{
110 pci_dev_set_intr (dev, 1, val);
111}
112
113void pci_dev_set_intc (pci_dev_t *dev, unsigned char val)
114{
115 pci_dev_set_intr (dev, 2, val);
116}
117
118void pci_dev_set_intd (pci_dev_t *dev, unsigned char val)
119{
120 pci_dev_set_intr (dev, 3, val);
121}
122
123void pci_dev_set_device_id (pci_dev_t *dev, unsigned vendor, unsigned id)
124{
125 buf_set_uint16_le (dev->config, 0x00, vendor);
126 buf_set_uint16_le (dev->config, 0x02, id);
127}
128
129void pci_dev_set_cfg_mask (pci_dev_t *dev, unsigned i, unsigned n, int val)
130{
131 unsigned k, m;
132
133 while (n > 0) {
134 k = i >> 3;
135 m = 1 << (i & 7);
136
137 if (k > 255) {
138 return;
139 }
140
141 if (val) {
142 dev->wrmask[k] |= m;
143 }
144 else {
145 dev->wrmask[k] &= ~m;
146 }
147
148 i += 1;
149 n -= 1;
150 }
151}
152
153unsigned char pci_dev_get_cfg8 (pci_dev_t *dev, unsigned long addr)
154{
155 if (addr <= 255) {
156 return (dev->config[addr]);
157 }
158
159 return (0);
160}
161
162unsigned short pci_dev_get_cfg16 (pci_dev_t *dev, unsigned long addr)
163{
164 unsigned short val;
165
166 val = pci_dev_get_cfg8 (dev, addr + 1);
167 val = (val << 8) | pci_dev_get_cfg8 (dev, addr);
168
169 return (val);
170}
171
172unsigned long pci_dev_get_cfg32 (pci_dev_t *dev, unsigned long addr)
173{
174 unsigned long val;
175
176 val = pci_dev_get_cfg8 (dev, addr + 3);
177 val = (val << 8) | pci_dev_get_cfg8 (dev, addr + 2);
178 val = (val << 8) | pci_dev_get_cfg8 (dev, addr + 1);
179 val = (val << 8) | pci_dev_get_cfg8 (dev, addr);
180
181 return (val);
182}
183
184void pci_dev_set_cfg8 (pci_dev_t *dev, unsigned long addr, unsigned char val)
185{
186 if (addr <= 255) {
187 val = (val & dev->wrmask[addr]) | (dev->config[addr] & ~dev->wrmask[addr]);
188 dev->config[addr] = val;
189 }
190}
191
192void pci_dev_set_cfg16 (pci_dev_t *dev, unsigned long addr, unsigned short val)
193{
194 pci_dev_set_cfg8 (dev, addr, val & 0xff);
195 pci_dev_set_cfg8 (dev, addr + 1, (val >> 8) & 0xff);
196}
197
198void pci_dev_set_cfg32 (pci_dev_t *dev, unsigned long addr, unsigned long val)
199{
200 pci_dev_set_cfg8 (dev, addr, val & 0xff);
201 pci_dev_set_cfg8 (dev, addr + 1, (val >> 8) & 0xff);
202 pci_dev_set_cfg8 (dev, addr + 2, (val >> 16) & 0xff);
203 pci_dev_set_cfg8 (dev, addr + 3, (val >> 24) & 0xff);
204}
205
206
207void pci_init (pci_bus_t *pci)
208{
209 unsigned i, j;
210
211 for (i = 0; i < 32; i++) {
212 pci->dev[i] = NULL;
213 }
214
215 pci->asio = NULL;
216 pci->asmem = NULL;
217
218 for (i = 0; i < 32; i++) {
219 for (j = 0; j < 4; j++) {
220 pci->irq[i][j] = NULL;
221 pci->irq_ext[i][j] = NULL;
222 pci->irq_val[i][j] = 0;
223 }
224 }
225
226 pci->cfgaddr = 0;
227 pci->cfgdata = 0;
228}
229
230void pci_free (pci_bus_t *pci)
231{
232}
233
234void pci_set_device (pci_bus_t *pci, pci_dev_t *dev, unsigned i)
235{
236 unsigned j;
237 pci_dev_t *old;
238
239 i &= 0x1f;
240
241 old = pci->dev[i];
242
243 if (old != NULL) {
244 if (pci->asio != NULL) {
245 for (j = 0; j < PCI_REG_MAX; j++) {
246 if (dev->reg[j] != NULL) {
247 mem_rmv_blk (pci->asio, dev->reg[j]);
248 }
249 }
250 }
251
252 if (pci->asmem != NULL) {
253 for (j = 0; j < PCI_MEM_MAX; j++) {
254 if (dev->mem[j] != NULL) {
255 mem_rmv_blk (pci->asmem, dev->mem[j]);
256 }
257 }
258 }
259 }
260
261 dev->index = i;
262 dev->pci = pci;
263
264 pci->dev[i] = dev;
265
266 if (dev != NULL) {
267 if (pci->asio != NULL) {
268 for (j = 0; j < PCI_REG_MAX; j++) {
269 if (dev->reg[j] != NULL) {
270 mem_add_blk (pci->asio, dev->reg[j], 0);
271 }
272 }
273 }
274
275 if (pci->asmem != NULL) {
276 for (j = 0; j < PCI_MEM_MAX; j++) {
277 if (dev->mem[j] != NULL) {
278 mem_add_blk (pci->asmem, dev->mem[j], 0);
279 }
280 }
281 }
282 }
283}
284
285void pci_set_asio (pci_bus_t *pci, memory_t *as)
286{
287 pci->asio = as;
288}
289
290void pci_set_asmem (pci_bus_t *pci, memory_t *as)
291{
292 pci->asmem = as;
293}
294
295void pci_set_irq_fct (pci_bus_t *pci, unsigned dev, unsigned intr, void *ext, void *fct)
296{
297 if ((dev < 32) && (intr < 4)) {
298 pci->irq[dev][intr] = fct;
299 pci->irq_ext[dev][intr] = ext;
300 pci->irq_val[dev][intr] = 0;
301 }
302}
303
304void pci_set_cfg8 (pci_bus_t *pci, unsigned dev, unsigned long addr, unsigned char val)
305{
306 pci_dev_t *pdev = pci->dev[dev & 0x1f];
307
308 if ((pdev != NULL) && (pdev->set_cfg8 != NULL)) {
309 pdev->set_cfg8 (pdev->cfg_ext, addr, val);
310 }
311}
312
313void pci_set_cfg16 (pci_bus_t *pci, unsigned dev, unsigned long addr, unsigned short val)
314{
315 pci_dev_t *pdev = pci->dev[dev & 0x1f];
316
317 if ((pdev != NULL) && (pdev->set_cfg16 != NULL)) {
318 pdev->set_cfg16 (pdev->cfg_ext, addr, val);
319 }
320}
321
322void pci_set_cfg32 (pci_bus_t *pci, unsigned dev, unsigned long addr, unsigned long val)
323{
324 pci_dev_t *pdev = pci->dev[dev & 0x1f];
325
326 if ((pdev != NULL) && (pdev->set_cfg32 != NULL)) {
327 pdev->set_cfg32 (pdev->cfg_ext, addr, val);
328 }
329}
330
331unsigned char pci_get_cfg8 (pci_bus_t *pci, unsigned dev, unsigned long addr)
332{
333 pci_dev_t *pdev = pci->dev[dev & 0x1f];
334
335 if ((pdev != NULL) && (pdev->get_cfg8 != NULL)) {
336 return (pdev->get_cfg8 (pdev->cfg_ext, addr));
337 }
338
339 return (0xff);
340}
341
342unsigned short pci_get_cfg16 (pci_bus_t *pci, unsigned dev, unsigned long addr)
343{
344 pci_dev_t *pdev = pci->dev[dev & 0x1f];
345
346 if ((pdev != NULL) && (pdev->get_cfg16 != NULL)) {
347 return (pdev->get_cfg16 (pdev->cfg_ext, addr));
348 }
349
350 return (0xffffU);
351}
352
353unsigned long pci_get_cfg32 (pci_bus_t *pci, unsigned dev, unsigned long addr)
354{
355 pci_dev_t *pdev = pci->dev[dev & 0x1f];
356
357 if ((pdev != NULL) && (pdev->get_cfg32 != NULL)) {
358 return (pdev->get_cfg32 (pdev->cfg_ext, addr));
359 }
360
361 return (0xffffffffUL);
362}
363
364static
365void pci_set_irq (pci_bus_t *pci, unsigned dev, unsigned intr, unsigned char val)
366{
367 val = (val != 0);
368
369 dev &= 0x1f;
370 intr &= 0x03;
371
372 if (val != pci->irq_val[dev][intr]) {
373 pci->irq_val[dev][intr] = val;
374
375 if (pci->irq[dev][intr] != NULL) {
376 pci->irq[dev][intr] (pci->irq_ext[dev][intr], val);
377 }
378 }
379}
380
381void pci_set_intr (pci_bus_t *pci, unsigned dev, unsigned intr, unsigned char val)
382{
383 pci_set_irq (pci, dev, intr, val);
384}
385
386void pci_set_inta (pci_bus_t *pci, unsigned dev, unsigned char val)
387{
388 pci_set_intr (pci, 0, dev, val);
389}
390
391void pci_set_intb (pci_bus_t *pci, unsigned dev, unsigned char val)
392{
393 pci_set_intr (pci, 1, dev, val);
394}
395
396void pci_set_intc (pci_bus_t *pci, unsigned dev, unsigned char val)
397{
398 pci_set_intr (pci, 2, dev, val);
399}
400
401void pci_set_intd (pci_bus_t *pci, unsigned dev, unsigned char val)
402{
403 pci_set_intr (pci, 3, dev, val);
404}
405
406
407unsigned long pci_get_config_addr (pci_bus_t *pci)
408{
409 return (pci->cfgaddr);
410}
411
412unsigned char pci_get_config_data8 (pci_bus_t *pci, unsigned addr)
413{
414 unsigned dev;
415 pci_dev_t *pdev;
416
417 addr &= 0x03;
418
419 dev = (pci->cfgaddr >> 11) & 0x1f;
420 pdev = pci->dev[dev];
421
422 if ((pdev != NULL) && (pdev->get_cfg8 != NULL)) {
423 return (pdev->get_cfg8 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr));
424 }
425
426 return (0);
427}
428
429unsigned short pci_get_config_data16 (pci_bus_t *pci, unsigned addr)
430{
431 unsigned dev;
432 pci_dev_t *pdev;
433
434 addr &= 0x03;
435
436 dev = (pci->cfgaddr >> 11) & 0x1f;
437 pdev = pci->dev[dev];
438
439 if ((pdev != NULL) && (pdev->get_cfg16 != NULL)) {
440 return (pdev->get_cfg16 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr));
441 }
442
443 return (0);
444}
445
446unsigned long pci_get_config_data32 (pci_bus_t *pci)
447{
448 unsigned dev;
449 pci_dev_t *pdev;
450
451 dev = (pci->cfgaddr >> 11) & 0x1f;
452 pdev = pci->dev[dev];
453
454 if ((pdev != NULL) && (pdev->get_cfg32 != NULL)) {
455 return (pdev->get_cfg32 (pdev->cfg_ext, pci->cfgaddr & 0x03fcU));
456 }
457
458 return (0);
459}
460
461void pci_set_config_addr (pci_bus_t *pci, unsigned long val)
462{
463 pci->cfgaddr = val;
464}
465
466void pci_set_config_data8 (pci_bus_t *pci, unsigned addr, unsigned char val)
467{
468 unsigned dev;
469 pci_dev_t *pdev;
470
471 addr &= 0x03;
472
473 dev = (pci->cfgaddr >> 11) & 0x1f;
474 pdev = pci->dev[dev];
475
476 if ((pdev != NULL) && (pdev->set_cfg8 != NULL)) {
477 pdev->set_cfg8 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr, val);
478 }
479}
480
481void pci_set_config_data16 (pci_bus_t *pci, unsigned addr, unsigned short val)
482{
483 unsigned dev;
484 pci_dev_t *pdev;
485
486 addr &= 0x03;
487
488 dev = (pci->cfgaddr >> 11) & 0x1f;
489 pdev = pci->dev[dev];
490
491 if ((pdev != NULL) && (pdev->set_cfg16 != NULL)) {
492 pdev->set_cfg16 (pdev->cfg_ext, (pci->cfgaddr & 0x03fcU) + addr, val);
493 }
494}
495
496void pci_set_config_data32 (pci_bus_t *pci, unsigned long val)
497{
498 unsigned dev;
499 pci_dev_t *pdev;
500
501 dev = (pci->cfgaddr >> 11) & 0x1f;
502 pdev = pci->dev[dev];
503
504 if ((pdev != NULL) && (pdev->set_cfg32 != NULL)) {
505 pdev->set_cfg32 (pdev->cfg_ext, pci->cfgaddr & 0x03fcU, val);
506 }
507}