diff options
Diffstat (limited to 'arch/mn10300/unit-asb2305/pci.c')
-rw-r--r-- | arch/mn10300/unit-asb2305/pci.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c new file mode 100644 index 000000000000..1a86425fec42 --- /dev/null +++ b/arch/mn10300/unit-asb2305/pci.c | |||
@@ -0,0 +1,545 @@ | |||
1 | /* ASB2305 PCI support | ||
2 | * | ||
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * Derived from arch/i386/kernel/pci-pc.c | ||
6 | * (c) 1999--2000 Martin Mares <mj@suse.cz> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public Licence | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the Licence, or (at your option) any later version. | ||
12 | */ | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <asm/io.h> | ||
21 | #include "pci-asb2305.h" | ||
22 | |||
23 | unsigned int pci_probe = 1; | ||
24 | |||
25 | int pcibios_last_bus = -1; | ||
26 | struct pci_bus *pci_root_bus; | ||
27 | struct pci_ops *pci_root_ops; | ||
28 | |||
29 | /* | ||
30 | * Functions for accessing PCI configuration space | ||
31 | */ | ||
32 | |||
33 | #define CONFIG_CMD(bus, devfn, where) \ | ||
34 | (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) | ||
35 | |||
36 | #define MEM_PAGING_REG (*(volatile __u32 *) 0xBFFFFFF4) | ||
37 | #define CONFIG_ADDRESS (*(volatile __u32 *) 0xBFFFFFF8) | ||
38 | #define CONFIG_DATAL(X) (*(volatile __u32 *) 0xBFFFFFFC) | ||
39 | #define CONFIG_DATAW(X) (*(volatile __u16 *) (0xBFFFFFFC + ((X) & 2))) | ||
40 | #define CONFIG_DATAB(X) (*(volatile __u8 *) (0xBFFFFFFC + ((X) & 3))) | ||
41 | |||
42 | #define BRIDGEREGB(X) (*(volatile __u8 *) (0xBE040000 + (X))) | ||
43 | #define BRIDGEREGW(X) (*(volatile __u16 *) (0xBE040000 + (X))) | ||
44 | #define BRIDGEREGL(X) (*(volatile __u32 *) (0xBE040000 + (X))) | ||
45 | |||
46 | static inline int __query(const struct pci_bus *bus, unsigned int devfn) | ||
47 | { | ||
48 | #if 0 | ||
49 | return bus->number == 0 && (devfn == PCI_DEVFN(0, 0)); | ||
50 | return bus->number == 1; | ||
51 | return bus->number == 0 && | ||
52 | (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0)); | ||
53 | #endif | ||
54 | return 1; | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * translate Linuxcentric addresses to PCI bus addresses | ||
59 | */ | ||
60 | void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, | ||
61 | struct resource *res) | ||
62 | { | ||
63 | if (res->flags & IORESOURCE_IO) { | ||
64 | region->start = (res->start & 0x00ffffff); | ||
65 | region->end = (res->end & 0x00ffffff); | ||
66 | } | ||
67 | |||
68 | if (res->flags & IORESOURCE_MEM) { | ||
69 | region->start = (res->start & 0x03ffffff) | MEM_PAGING_REG; | ||
70 | region->end = (res->end & 0x03ffffff) | MEM_PAGING_REG; | ||
71 | } | ||
72 | |||
73 | #if 0 | ||
74 | printk(KERN_DEBUG "RES->BUS: %lx-%lx => %lx-%lx\n", | ||
75 | res->start, res->end, region->start, region->end); | ||
76 | #endif | ||
77 | } | ||
78 | EXPORT_SYMBOL(pcibios_resource_to_bus); | ||
79 | |||
80 | /* | ||
81 | * translate PCI bus addresses to Linuxcentric addresses | ||
82 | */ | ||
83 | void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, | ||
84 | struct pci_bus_region *region) | ||
85 | { | ||
86 | if (res->flags & IORESOURCE_IO) { | ||
87 | res->start = (region->start & 0x00ffffff) | 0xbe000000; | ||
88 | res->end = (region->end & 0x00ffffff) | 0xbe000000; | ||
89 | } | ||
90 | |||
91 | if (res->flags & IORESOURCE_MEM) { | ||
92 | res->start = (region->start & 0x03ffffff) | 0xb8000000; | ||
93 | res->end = (region->end & 0x03ffffff) | 0xb8000000; | ||
94 | } | ||
95 | |||
96 | #if 0 | ||
97 | printk(KERN_INFO "BUS->RES: %lx-%lx => %lx-%lx\n", | ||
98 | region->start, region->end, res->start, res->end); | ||
99 | #endif | ||
100 | } | ||
101 | EXPORT_SYMBOL(pcibios_bus_to_resource); | ||
102 | |||
103 | /* | ||
104 | * | ||
105 | */ | ||
106 | static int pci_ampci_read_config_byte(struct pci_bus *bus, unsigned int devfn, | ||
107 | int where, u32 *_value) | ||
108 | { | ||
109 | u32 rawval, value; | ||
110 | |||
111 | if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) { | ||
112 | value = BRIDGEREGB(where); | ||
113 | __pcbdebug("=> %02hx", &BRIDGEREGL(where), value); | ||
114 | } else { | ||
115 | CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where); | ||
116 | rawval = CONFIG_ADDRESS; | ||
117 | value = CONFIG_DATAB(where); | ||
118 | if (__query(bus, devfn)) | ||
119 | __pcidebug("=> %02hx", bus, devfn, where, value); | ||
120 | } | ||
121 | |||
122 | *_value = value; | ||
123 | return PCIBIOS_SUCCESSFUL; | ||
124 | } | ||
125 | |||
126 | static int pci_ampci_read_config_word(struct pci_bus *bus, unsigned int devfn, | ||
127 | int where, u32 *_value) | ||
128 | { | ||
129 | u32 rawval, value; | ||
130 | |||
131 | if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) { | ||
132 | value = BRIDGEREGW(where); | ||
133 | __pcbdebug("=> %04hx", &BRIDGEREGL(where), value); | ||
134 | } else { | ||
135 | CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where); | ||
136 | rawval = CONFIG_ADDRESS; | ||
137 | value = CONFIG_DATAW(where); | ||
138 | if (__query(bus, devfn)) | ||
139 | __pcidebug("=> %04hx", bus, devfn, where, value); | ||
140 | } | ||
141 | |||
142 | *_value = value; | ||
143 | return PCIBIOS_SUCCESSFUL; | ||
144 | } | ||
145 | |||
146 | static int pci_ampci_read_config_dword(struct pci_bus *bus, unsigned int devfn, | ||
147 | int where, u32 *_value) | ||
148 | { | ||
149 | u32 rawval, value; | ||
150 | |||
151 | if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) { | ||
152 | value = BRIDGEREGL(where); | ||
153 | __pcbdebug("=> %08x", &BRIDGEREGL(where), value); | ||
154 | } else { | ||
155 | CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where); | ||
156 | rawval = CONFIG_ADDRESS; | ||
157 | value = CONFIG_DATAL(where); | ||
158 | if (__query(bus, devfn)) | ||
159 | __pcidebug("=> %08x", bus, devfn, where, value); | ||
160 | } | ||
161 | |||
162 | *_value = value; | ||
163 | return PCIBIOS_SUCCESSFUL; | ||
164 | } | ||
165 | |||
166 | static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn, | ||
167 | int where, u8 value) | ||
168 | { | ||
169 | u32 rawval; | ||
170 | |||
171 | if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) { | ||
172 | __pcbdebug("<= %02x", &BRIDGEREGB(where), value); | ||
173 | BRIDGEREGB(where) = value; | ||
174 | } else { | ||
175 | if (bus->number == 0 && | ||
176 | (devfn == PCI_DEVFN(2, 0) && devfn == PCI_DEVFN(3, 0)) | ||
177 | ) | ||
178 | __pcidebug("<= %02x", bus, devfn, where, value); | ||
179 | CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where); | ||
180 | rawval = CONFIG_ADDRESS; | ||
181 | CONFIG_DATAB(where) = value; | ||
182 | } | ||
183 | return PCIBIOS_SUCCESSFUL; | ||
184 | } | ||
185 | |||
186 | static int pci_ampci_write_config_word(struct pci_bus *bus, unsigned int devfn, | ||
187 | int where, u16 value) | ||
188 | { | ||
189 | u32 rawval; | ||
190 | |||
191 | if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) { | ||
192 | __pcbdebug("<= %04hx", &BRIDGEREGW(where), value); | ||
193 | BRIDGEREGW(where) = value; | ||
194 | } else { | ||
195 | if (__query(bus, devfn)) | ||
196 | __pcidebug("<= %04hx", bus, devfn, where, value); | ||
197 | CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where); | ||
198 | rawval = CONFIG_ADDRESS; | ||
199 | CONFIG_DATAW(where) = value; | ||
200 | } | ||
201 | return PCIBIOS_SUCCESSFUL; | ||
202 | } | ||
203 | |||
204 | static int pci_ampci_write_config_dword(struct pci_bus *bus, unsigned int devfn, | ||
205 | int where, u32 value) | ||
206 | { | ||
207 | u32 rawval; | ||
208 | |||
209 | if (bus->number == 0 && devfn == PCI_DEVFN(0, 0)) { | ||
210 | __pcbdebug("<= %08x", &BRIDGEREGL(where), value); | ||
211 | BRIDGEREGL(where) = value; | ||
212 | } else { | ||
213 | if (__query(bus, devfn)) | ||
214 | __pcidebug("<= %08x", bus, devfn, where, value); | ||
215 | CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where); | ||
216 | rawval = CONFIG_ADDRESS; | ||
217 | CONFIG_DATAL(where) = value; | ||
218 | } | ||
219 | return PCIBIOS_SUCCESSFUL; | ||
220 | } | ||
221 | |||
222 | static int pci_ampci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
223 | int where, int size, u32 *val) | ||
224 | { | ||
225 | switch (size) { | ||
226 | case 1: | ||
227 | return pci_ampci_read_config_byte(bus, devfn, where, val); | ||
228 | case 2: | ||
229 | return pci_ampci_read_config_word(bus, devfn, where, val); | ||
230 | case 4: | ||
231 | return pci_ampci_read_config_dword(bus, devfn, where, val); | ||
232 | default: | ||
233 | BUG(); | ||
234 | return -EOPNOTSUPP; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | static int pci_ampci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
239 | int where, int size, u32 val) | ||
240 | { | ||
241 | switch (size) { | ||
242 | case 1: | ||
243 | return pci_ampci_write_config_byte(bus, devfn, where, val); | ||
244 | case 2: | ||
245 | return pci_ampci_write_config_word(bus, devfn, where, val); | ||
246 | case 4: | ||
247 | return pci_ampci_write_config_dword(bus, devfn, where, val); | ||
248 | default: | ||
249 | BUG(); | ||
250 | return -EOPNOTSUPP; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | static struct pci_ops pci_direct_ampci = { | ||
255 | pci_ampci_read_config, | ||
256 | pci_ampci_write_config, | ||
257 | }; | ||
258 | |||
259 | /* | ||
260 | * Before we decide to use direct hardware access mechanisms, we try to do some | ||
261 | * trivial checks to ensure it at least _seems_ to be working -- we just test | ||
262 | * whether bus 00 contains a host bridge (this is similar to checking | ||
263 | * techniques used in XFree86, but ours should be more reliable since we | ||
264 | * attempt to make use of direct access hints provided by the PCI BIOS). | ||
265 | * | ||
266 | * This should be close to trivial, but it isn't, because there are buggy | ||
267 | * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID. | ||
268 | */ | ||
269 | static int __init pci_sanity_check(struct pci_ops *o) | ||
270 | { | ||
271 | struct pci_bus bus; /* Fake bus and device */ | ||
272 | u32 x; | ||
273 | |||
274 | bus.number = 0; | ||
275 | |||
276 | if ((!o->read(&bus, 0, PCI_CLASS_DEVICE, 2, &x) && | ||
277 | (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) || | ||
278 | (!o->read(&bus, 0, PCI_VENDOR_ID, 2, &x) && | ||
279 | (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) | ||
280 | return 1; | ||
281 | |||
282 | printk(KERN_ERROR "PCI: Sanity check failed\n"); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int __init pci_check_direct(void) | ||
287 | { | ||
288 | unsigned long flags; | ||
289 | |||
290 | local_irq_save(flags); | ||
291 | |||
292 | /* | ||
293 | * Check if access works. | ||
294 | */ | ||
295 | if (pci_sanity_check(&pci_direct_ampci)) { | ||
296 | local_irq_restore(flags); | ||
297 | printk(KERN_INFO "PCI: Using configuration ampci\n"); | ||
298 | request_mem_region(0xBE040000, 256, "AMPCI bridge"); | ||
299 | request_mem_region(0xBFFFFFF4, 12, "PCI ampci"); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | local_irq_restore(flags); | ||
304 | return -ENODEV; | ||
305 | } | ||
306 | |||
307 | static int __devinit is_valid_resource(struct pci_dev *dev, int idx) | ||
308 | { | ||
309 | unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; | ||
310 | struct resource *devr = &dev->resource[idx]; | ||
311 | |||
312 | if (dev->bus) { | ||
313 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | ||
314 | struct resource *busr = dev->bus->resource[i]; | ||
315 | |||
316 | if (!busr || (busr->flags ^ devr->flags) & type_mask) | ||
317 | continue; | ||
318 | |||
319 | if (devr->start && | ||
320 | devr->start >= busr->start && | ||
321 | devr->end <= busr->end) | ||
322 | return 1; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) | ||
330 | { | ||
331 | struct pci_bus_region region; | ||
332 | int i; | ||
333 | int limit; | ||
334 | |||
335 | if (dev->bus->number != 0) | ||
336 | return; | ||
337 | |||
338 | limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? | ||
339 | PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES; | ||
340 | |||
341 | for (i = 0; i < limit; i++) { | ||
342 | if (!dev->resource[i].flags) | ||
343 | continue; | ||
344 | |||
345 | region.start = dev->resource[i].start; | ||
346 | region.end = dev->resource[i].end; | ||
347 | pcibios_bus_to_resource(dev, &dev->resource[i], ®ion); | ||
348 | if (is_valid_resource(dev, i)) | ||
349 | pci_claim_resource(dev, i); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * Called after each bus is probed, but before its children | ||
355 | * are examined. | ||
356 | */ | ||
357 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | ||
358 | { | ||
359 | struct pci_dev *dev; | ||
360 | |||
361 | if (bus->self) { | ||
362 | pci_read_bridge_bases(bus); | ||
363 | pcibios_fixup_device_resources(bus->self); | ||
364 | } | ||
365 | |||
366 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
367 | pcibios_fixup_device_resources(dev); | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * Initialization. Try all known PCI access methods. Note that we support | ||
372 | * using both PCI BIOS and direct access: in such cases, we use I/O ports | ||
373 | * to access config space, but we still keep BIOS order of cards to be | ||
374 | * compatible with 2.0.X. This should go away some day. | ||
375 | */ | ||
376 | static int __init pcibios_init(void) | ||
377 | { | ||
378 | ioport_resource.start = 0xA0000000; | ||
379 | ioport_resource.end = 0xDFFFFFFF; | ||
380 | iomem_resource.start = 0xA0000000; | ||
381 | iomem_resource.end = 0xDFFFFFFF; | ||
382 | |||
383 | if (!pci_probe) | ||
384 | return 0; | ||
385 | |||
386 | if (pci_check_direct() < 0) { | ||
387 | printk(KERN_WARNING "PCI: No PCI bus detected\n"); | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n", | ||
392 | MEM_PAGING_REG); | ||
393 | |||
394 | { | ||
395 | #if 0 | ||
396 | static struct pci_bus am33_root_bus = { | ||
397 | .children = LIST_HEAD_INIT(am33_root_bus.children), | ||
398 | .devices = LIST_HEAD_INIT(am33_root_bus.devices), | ||
399 | .number = 0, | ||
400 | .secondary = 0, | ||
401 | .resource = { &ioport_resource, &iomem_resource }, | ||
402 | }; | ||
403 | |||
404 | am33_root_bus.ops = pci_root_ops; | ||
405 | list_add_tail(&am33_root_bus.node, &pci_root_buses); | ||
406 | |||
407 | am33_root_bus.subordinate = pci_do_scan_bus(0); | ||
408 | |||
409 | pci_root_bus = &am33_root_bus; | ||
410 | #else | ||
411 | pci_root_bus = pci_scan_bus(0, &pci_direct_ampci, NULL); | ||
412 | #endif | ||
413 | } | ||
414 | |||
415 | pcibios_irq_init(); | ||
416 | pcibios_fixup_irqs(); | ||
417 | #if 0 | ||
418 | pcibios_resource_survey(); | ||
419 | #endif | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | arch_initcall(pcibios_init); | ||
424 | |||
425 | char *__init pcibios_setup(char *str) | ||
426 | { | ||
427 | if (!strcmp(str, "off")) { | ||
428 | pci_probe = 0; | ||
429 | return NULL; | ||
430 | |||
431 | } else if (!strncmp(str, "lastbus=", 8)) { | ||
432 | pcibios_last_bus = simple_strtol(str+8, NULL, 0); | ||
433 | return NULL; | ||
434 | } | ||
435 | |||
436 | return str; | ||
437 | } | ||
438 | |||
439 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
440 | { | ||
441 | int err; | ||
442 | |||
443 | err = pcibios_enable_resources(dev, mask); | ||
444 | if (err == 0) | ||
445 | pcibios_enable_irq(dev); | ||
446 | return err; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * disable the ethernet chipset | ||
451 | */ | ||
452 | static void __init unit_disable_pcnet(struct pci_bus *bus, struct pci_ops *o) | ||
453 | { | ||
454 | u32 x; | ||
455 | |||
456 | bus->number = 0; | ||
457 | |||
458 | o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND, 2, &x); | ||
459 | x |= PCI_COMMAND_MASTER | | ||
460 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | ||
461 | PCI_COMMAND_SERR | PCI_COMMAND_PARITY; | ||
462 | o->write(bus, PCI_DEVFN(2, 0), PCI_COMMAND, 2, x); | ||
463 | o->read (bus, PCI_DEVFN(2, 0), PCI_COMMAND, 2, &x); | ||
464 | o->write(bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0, 4, 0x00030001); | ||
465 | o->read (bus, PCI_DEVFN(2, 0), PCI_BASE_ADDRESS_0, 4, &x); | ||
466 | |||
467 | #define RDP (*(volatile u32 *) 0xBE030010) | ||
468 | #define RAP (*(volatile u32 *) 0xBE030014) | ||
469 | #define __set_RAP(X) do { RAP = (X); x = RAP; } while (0) | ||
470 | #define __set_RDP(X) do { RDP = (X); x = RDP; } while (0) | ||
471 | #define __get_RDP() ({ RDP & 0xffff; }) | ||
472 | |||
473 | __set_RAP(0); | ||
474 | __set_RDP(0x0004); /* CSR0 = STOP */ | ||
475 | |||
476 | __set_RAP(88); /* check CSR88 indicates an Am79C973 */ | ||
477 | BUG_ON(__get_RDP() != 0x5003); | ||
478 | |||
479 | for (x = 0; x < 100; x++) | ||
480 | asm volatile("nop"); | ||
481 | |||
482 | __set_RDP(0x0004); /* CSR0 = STOP */ | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * initialise the unit hardware | ||
487 | */ | ||
488 | asmlinkage void __init unit_pci_init(void) | ||
489 | { | ||
490 | struct pci_bus bus; /* Fake bus and device */ | ||
491 | struct pci_ops *o = &pci_direct_ampci; | ||
492 | u32 x; | ||
493 | |||
494 | set_intr_level(XIRQ1, GxICR_LEVEL_3); | ||
495 | |||
496 | memset(&bus, 0, sizeof(bus)); | ||
497 | |||
498 | MEM_PAGING_REG = 0xE8000000; | ||
499 | |||
500 | /* we need to set up the bridge _now_ or we won't be able to access the | ||
501 | * PCI config registers | ||
502 | */ | ||
503 | BRIDGEREGW(PCI_COMMAND) |= | ||
504 | PCI_COMMAND_SERR | PCI_COMMAND_PARITY | | ||
505 | PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER; | ||
506 | BRIDGEREGW(PCI_STATUS) = 0xF800; | ||
507 | BRIDGEREGB(PCI_LATENCY_TIMER) = 0x10; | ||
508 | BRIDGEREGL(PCI_BASE_ADDRESS_0) = 0x80000000; | ||
509 | BRIDGEREGB(PCI_INTERRUPT_LINE) = 1; | ||
510 | BRIDGEREGL(0x48) = 0x98000000; /* AMPCI base addr */ | ||
511 | BRIDGEREGB(0x41) = 0x00; /* secondary bus | ||
512 | * number */ | ||
513 | BRIDGEREGB(0x42) = 0x01; /* subordinate bus | ||
514 | * number */ | ||
515 | BRIDGEREGB(0x44) = 0x01; | ||
516 | BRIDGEREGL(0x50) = 0x00000001; | ||
517 | BRIDGEREGL(0x58) = 0x00001002; | ||
518 | BRIDGEREGL(0x5C) = 0x00000011; | ||
519 | |||
520 | /* we also need to set up the PCI-PCI bridge */ | ||
521 | bus.number = 0; | ||
522 | |||
523 | /* IO: 0x00000000-0x00020000 */ | ||
524 | o->read (&bus, PCI_DEVFN(3, 0), PCI_COMMAND, 2, &x); | ||
525 | x |= PCI_COMMAND_MASTER | | ||
526 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | ||
527 | PCI_COMMAND_SERR | PCI_COMMAND_PARITY; | ||
528 | o->write(&bus, PCI_DEVFN(3, 0), PCI_COMMAND, 2, x); | ||
529 | |||
530 | o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE, 1, &x); | ||
531 | o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16, 4, &x); | ||
532 | o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE, 4, &x); | ||
533 | o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE, 4, &x); | ||
534 | |||
535 | o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE, 1, 0x01); | ||
536 | o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE, 1, &x); | ||
537 | o->write(&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16, 4, 0x00020000); | ||
538 | o->read (&bus, PCI_DEVFN(3, 0), PCI_IO_BASE_UPPER16, 4, &x); | ||
539 | o->write(&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE, 4, 0xEBB0EA00); | ||
540 | o->read (&bus, PCI_DEVFN(3, 0), PCI_MEMORY_BASE, 4, &x); | ||
541 | o->write(&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE, 4, 0xE9F0E800); | ||
542 | o->read (&bus, PCI_DEVFN(3, 0), PCI_PREF_MEMORY_BASE, 4, &x); | ||
543 | |||
544 | unit_disable_pcnet(&bus, o); | ||
545 | } | ||