diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sparc/kernel/pcic.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/sparc/kernel/pcic.c')
-rw-r--r-- | arch/sparc/kernel/pcic.c | 1041 |
1 files changed, 1041 insertions, 0 deletions
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c new file mode 100644 index 000000000000..597d3ff6ad68 --- /dev/null +++ b/arch/sparc/kernel/pcic.c | |||
@@ -0,0 +1,1041 @@ | |||
1 | /* | ||
2 | * pcic.c: MicroSPARC-IIep PCI controller support | ||
3 | * | ||
4 | * Copyright (C) 1998 V. Roganov and G. Raiko | ||
5 | * | ||
6 | * Code is derived from Ultra/PCI PSYCHO controller support, see that | ||
7 | * for author info. | ||
8 | * | ||
9 | * Support for diverse IIep based platforms by Pete Zaitcev. | ||
10 | * CP-1200 by Eric Brower. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | |||
21 | #include <asm/ebus.h> | ||
22 | #include <asm/sbus.h> /* for sanity check... */ | ||
23 | #include <asm/swift.h> /* for cache flushing. */ | ||
24 | #include <asm/io.h> | ||
25 | |||
26 | #include <linux/ctype.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/time.h> | ||
29 | #include <linux/timex.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | |||
32 | #include <asm/irq.h> | ||
33 | #include <asm/oplib.h> | ||
34 | #include <asm/pcic.h> | ||
35 | #include <asm/timer.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | |||
38 | |||
39 | unsigned int pcic_pin_to_irq(unsigned int pin, char *name); | ||
40 | |||
41 | /* | ||
42 | * I studied different documents and many live PROMs both from 2.30 | ||
43 | * family and 3.xx versions. I came to the amazing conclusion: there is | ||
44 | * absolutely no way to route interrupts in IIep systems relying on | ||
45 | * information which PROM presents. We must hardcode interrupt routing | ||
46 | * schematics. And this actually sucks. -- zaitcev 1999/05/12 | ||
47 | * | ||
48 | * To find irq for a device we determine which routing map | ||
49 | * is in effect or, in other words, on which machine we are running. | ||
50 | * We use PROM name for this although other techniques may be used | ||
51 | * in special cases (Gleb reports a PROMless IIep based system). | ||
52 | * Once we know the map we take device configuration address and | ||
53 | * find PCIC pin number where INT line goes. Then we may either program | ||
54 | * preferred irq into the PCIC or supply the preexisting irq to the device. | ||
55 | */ | ||
56 | struct pcic_ca2irq { | ||
57 | unsigned char busno; /* PCI bus number */ | ||
58 | unsigned char devfn; /* Configuration address */ | ||
59 | unsigned char pin; /* PCIC external interrupt pin */ | ||
60 | unsigned char irq; /* Preferred IRQ (mappable in PCIC) */ | ||
61 | unsigned int force; /* Enforce preferred IRQ */ | ||
62 | }; | ||
63 | |||
64 | struct pcic_sn2list { | ||
65 | char *sysname; | ||
66 | struct pcic_ca2irq *intmap; | ||
67 | int mapdim; | ||
68 | }; | ||
69 | |||
70 | /* | ||
71 | * JavaEngine-1 apparently has different versions. | ||
72 | * | ||
73 | * According to communications with Sun folks, for P2 build 501-4628-03: | ||
74 | * pin 0 - parallel, audio; | ||
75 | * pin 1 - Ethernet; | ||
76 | * pin 2 - su; | ||
77 | * pin 3 - PS/2 kbd and mouse. | ||
78 | * | ||
79 | * OEM manual (805-1486): | ||
80 | * pin 0: Ethernet | ||
81 | * pin 1: All EBus | ||
82 | * pin 2: IGA (unused) | ||
83 | * pin 3: Not connected | ||
84 | * OEM manual says that 501-4628 & 501-4811 are the same thing, | ||
85 | * only the latter has NAND flash in place. | ||
86 | * | ||
87 | * So far unofficial Sun wins over the OEM manual. Poor OEMs... | ||
88 | */ | ||
89 | static struct pcic_ca2irq pcic_i_je1a[] = { /* 501-4811-03 */ | ||
90 | { 0, 0x00, 2, 12, 0 }, /* EBus: hogs all */ | ||
91 | { 0, 0x01, 1, 6, 1 }, /* Happy Meal */ | ||
92 | { 0, 0x80, 0, 7, 0 }, /* IGA (unused) */ | ||
93 | }; | ||
94 | |||
95 | /* XXX JS-E entry is incomplete - PCI Slot 2 address (pin 7)? */ | ||
96 | static struct pcic_ca2irq pcic_i_jse[] = { | ||
97 | { 0, 0x00, 0, 13, 0 }, /* Ebus - serial and keyboard */ | ||
98 | { 0, 0x01, 1, 6, 0 }, /* hme */ | ||
99 | { 0, 0x08, 2, 9, 0 }, /* VGA - we hope not used :) */ | ||
100 | { 0, 0x10, 6, 8, 0 }, /* PCI INTA# in Slot 1 */ | ||
101 | { 0, 0x18, 7, 12, 0 }, /* PCI INTA# in Slot 2, shared w. RTC */ | ||
102 | { 0, 0x38, 4, 9, 0 }, /* All ISA devices. Read 8259. */ | ||
103 | { 0, 0x80, 5, 11, 0 }, /* EIDE */ | ||
104 | /* {0,0x88, 0,0,0} - unknown device... PMU? Probably no interrupt. */ | ||
105 | { 0, 0xA0, 4, 9, 0 }, /* USB */ | ||
106 | /* | ||
107 | * Some pins belong to non-PCI devices, we hardcode them in drivers. | ||
108 | * sun4m timers - irq 10, 14 | ||
109 | * PC style RTC - pin 7, irq 4 ? | ||
110 | * Smart card, Parallel - pin 4 shared with USB, ISA | ||
111 | * audio - pin 3, irq 5 ? | ||
112 | */ | ||
113 | }; | ||
114 | |||
115 | /* SPARCengine-6 was the original release name of CP1200. | ||
116 | * The documentation differs between the two versions | ||
117 | */ | ||
118 | static struct pcic_ca2irq pcic_i_se6[] = { | ||
119 | { 0, 0x08, 0, 2, 0 }, /* SCSI */ | ||
120 | { 0, 0x01, 1, 6, 0 }, /* HME */ | ||
121 | { 0, 0x00, 3, 13, 0 }, /* EBus */ | ||
122 | }; | ||
123 | |||
124 | /* | ||
125 | * Krups (courtesy of Varol Kaptan) | ||
126 | * No documentation available, but it was easy to guess | ||
127 | * because it was very similar to Espresso. | ||
128 | * | ||
129 | * pin 0 - kbd, mouse, serial; | ||
130 | * pin 1 - Ethernet; | ||
131 | * pin 2 - igs (we do not use it); | ||
132 | * pin 3 - audio; | ||
133 | * pin 4,5,6 - unused; | ||
134 | * pin 7 - RTC (from P2 onwards as David B. says). | ||
135 | */ | ||
136 | static struct pcic_ca2irq pcic_i_jk[] = { | ||
137 | { 0, 0x00, 0, 13, 0 }, /* Ebus - serial and keyboard */ | ||
138 | { 0, 0x01, 1, 6, 0 }, /* hme */ | ||
139 | }; | ||
140 | |||
141 | /* | ||
142 | * Several entries in this list may point to the same routing map | ||
143 | * as several PROMs may be installed on the same physical board. | ||
144 | */ | ||
145 | #define SN2L_INIT(name, map) \ | ||
146 | { name, map, sizeof(map)/sizeof(struct pcic_ca2irq) } | ||
147 | |||
148 | static struct pcic_sn2list pcic_known_sysnames[] = { | ||
149 | SN2L_INIT("SUNW,JavaEngine1", pcic_i_je1a), /* JE1, PROM 2.32 */ | ||
150 | SN2L_INIT("SUNW,JS-E", pcic_i_jse), /* PROLL JavaStation-E */ | ||
151 | SN2L_INIT("SUNW,SPARCengine-6", pcic_i_se6), /* SPARCengine-6/CP-1200 */ | ||
152 | SN2L_INIT("SUNW,JS-NC", pcic_i_jk), /* PROLL JavaStation-NC */ | ||
153 | SN2L_INIT("SUNW,JSIIep", pcic_i_jk), /* OBP JavaStation-NC */ | ||
154 | { NULL, NULL, 0 } | ||
155 | }; | ||
156 | |||
157 | /* | ||
158 | * Only one PCIC per IIep, | ||
159 | * and since we have no SMP IIep, only one per system. | ||
160 | */ | ||
161 | static int pcic0_up; | ||
162 | static struct linux_pcic pcic0; | ||
163 | |||
164 | void * __iomem pcic_regs; | ||
165 | volatile int pcic_speculative; | ||
166 | volatile int pcic_trapped; | ||
167 | |||
168 | static void pci_do_gettimeofday(struct timeval *tv); | ||
169 | static int pci_do_settimeofday(struct timespec *tv); | ||
170 | |||
171 | #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) | ||
172 | |||
173 | static int pcic_read_config_dword(unsigned int busno, unsigned int devfn, | ||
174 | int where, u32 *value) | ||
175 | { | ||
176 | struct linux_pcic *pcic; | ||
177 | unsigned long flags; | ||
178 | |||
179 | pcic = &pcic0; | ||
180 | |||
181 | local_irq_save(flags); | ||
182 | #if 0 /* does not fail here */ | ||
183 | pcic_speculative = 1; | ||
184 | pcic_trapped = 0; | ||
185 | #endif | ||
186 | writel(CONFIG_CMD(busno, devfn, where), pcic->pcic_config_space_addr); | ||
187 | #if 0 /* does not fail here */ | ||
188 | nop(); | ||
189 | if (pcic_trapped) { | ||
190 | local_irq_restore(flags); | ||
191 | *value = ~0; | ||
192 | return 0; | ||
193 | } | ||
194 | #endif | ||
195 | pcic_speculative = 2; | ||
196 | pcic_trapped = 0; | ||
197 | *value = readl(pcic->pcic_config_space_data + (where&4)); | ||
198 | nop(); | ||
199 | if (pcic_trapped) { | ||
200 | pcic_speculative = 0; | ||
201 | local_irq_restore(flags); | ||
202 | *value = ~0; | ||
203 | return 0; | ||
204 | } | ||
205 | pcic_speculative = 0; | ||
206 | local_irq_restore(flags); | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int pcic_read_config(struct pci_bus *bus, unsigned int devfn, | ||
211 | int where, int size, u32 *val) | ||
212 | { | ||
213 | unsigned int v; | ||
214 | |||
215 | if (bus->number != 0) return -EINVAL; | ||
216 | switch (size) { | ||
217 | case 1: | ||
218 | pcic_read_config_dword(bus->number, devfn, where&~3, &v); | ||
219 | *val = 0xff & (v >> (8*(where & 3))); | ||
220 | return 0; | ||
221 | case 2: | ||
222 | if (where&1) return -EINVAL; | ||
223 | pcic_read_config_dword(bus->number, devfn, where&~3, &v); | ||
224 | *val = 0xffff & (v >> (8*(where & 3))); | ||
225 | return 0; | ||
226 | case 4: | ||
227 | if (where&3) return -EINVAL; | ||
228 | pcic_read_config_dword(bus->number, devfn, where&~3, val); | ||
229 | return 0; | ||
230 | } | ||
231 | return -EINVAL; | ||
232 | } | ||
233 | |||
234 | static int pcic_write_config_dword(unsigned int busno, unsigned int devfn, | ||
235 | int where, u32 value) | ||
236 | { | ||
237 | struct linux_pcic *pcic; | ||
238 | unsigned long flags; | ||
239 | |||
240 | pcic = &pcic0; | ||
241 | |||
242 | local_irq_save(flags); | ||
243 | writel(CONFIG_CMD(busno, devfn, where), pcic->pcic_config_space_addr); | ||
244 | writel(value, pcic->pcic_config_space_data + (where&4)); | ||
245 | local_irq_restore(flags); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int pcic_write_config(struct pci_bus *bus, unsigned int devfn, | ||
250 | int where, int size, u32 val) | ||
251 | { | ||
252 | unsigned int v; | ||
253 | |||
254 | if (bus->number != 0) return -EINVAL; | ||
255 | switch (size) { | ||
256 | case 1: | ||
257 | pcic_read_config_dword(bus->number, devfn, where&~3, &v); | ||
258 | v = (v & ~(0xff << (8*(where&3)))) | | ||
259 | ((0xff&val) << (8*(where&3))); | ||
260 | return pcic_write_config_dword(bus->number, devfn, where&~3, v); | ||
261 | case 2: | ||
262 | if (where&1) return -EINVAL; | ||
263 | pcic_read_config_dword(bus->number, devfn, where&~3, &v); | ||
264 | v = (v & ~(0xffff << (8*(where&3)))) | | ||
265 | ((0xffff&val) << (8*(where&3))); | ||
266 | return pcic_write_config_dword(bus->number, devfn, where&~3, v); | ||
267 | case 4: | ||
268 | if (where&3) return -EINVAL; | ||
269 | return pcic_write_config_dword(bus->number, devfn, where, val); | ||
270 | } | ||
271 | return -EINVAL; | ||
272 | } | ||
273 | |||
274 | static struct pci_ops pcic_ops = { | ||
275 | .read = pcic_read_config, | ||
276 | .write = pcic_write_config, | ||
277 | }; | ||
278 | |||
279 | /* | ||
280 | * On sparc64 pcibios_init() calls pci_controller_probe(). | ||
281 | * We want PCIC probed little ahead so that interrupt controller | ||
282 | * would be operational. | ||
283 | */ | ||
284 | int __init pcic_probe(void) | ||
285 | { | ||
286 | struct linux_pcic *pcic; | ||
287 | struct linux_prom_registers regs[PROMREG_MAX]; | ||
288 | struct linux_pbm_info* pbm; | ||
289 | char namebuf[64]; | ||
290 | int node; | ||
291 | int err; | ||
292 | |||
293 | if (pcic0_up) { | ||
294 | prom_printf("PCIC: called twice!\n"); | ||
295 | prom_halt(); | ||
296 | } | ||
297 | pcic = &pcic0; | ||
298 | |||
299 | node = prom_getchild (prom_root_node); | ||
300 | node = prom_searchsiblings (node, "pci"); | ||
301 | if (node == 0) | ||
302 | return -ENODEV; | ||
303 | /* | ||
304 | * Map in PCIC register set, config space, and IO base | ||
305 | */ | ||
306 | err = prom_getproperty(node, "reg", (char*)regs, sizeof(regs)); | ||
307 | if (err == 0 || err == -1) { | ||
308 | prom_printf("PCIC: Error, cannot get PCIC registers " | ||
309 | "from PROM.\n"); | ||
310 | prom_halt(); | ||
311 | } | ||
312 | |||
313 | pcic0_up = 1; | ||
314 | |||
315 | pcic->pcic_res_regs.name = "pcic_registers"; | ||
316 | pcic->pcic_regs = ioremap(regs[0].phys_addr, regs[0].reg_size); | ||
317 | if (!pcic->pcic_regs) { | ||
318 | prom_printf("PCIC: Error, cannot map PCIC registers.\n"); | ||
319 | prom_halt(); | ||
320 | } | ||
321 | |||
322 | pcic->pcic_res_io.name = "pcic_io"; | ||
323 | if ((pcic->pcic_io = (unsigned long) | ||
324 | ioremap(regs[1].phys_addr, 0x10000)) == 0) { | ||
325 | prom_printf("PCIC: Error, cannot map PCIC IO Base.\n"); | ||
326 | prom_halt(); | ||
327 | } | ||
328 | |||
329 | pcic->pcic_res_cfg_addr.name = "pcic_cfg_addr"; | ||
330 | if ((pcic->pcic_config_space_addr = | ||
331 | ioremap(regs[2].phys_addr, regs[2].reg_size * 2)) == 0) { | ||
332 | prom_printf("PCIC: Error, cannot map" | ||
333 | "PCI Configuration Space Address.\n"); | ||
334 | prom_halt(); | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Docs say three least significant bits in address and data | ||
339 | * must be the same. Thus, we need adjust size of data. | ||
340 | */ | ||
341 | pcic->pcic_res_cfg_data.name = "pcic_cfg_data"; | ||
342 | if ((pcic->pcic_config_space_data = | ||
343 | ioremap(regs[3].phys_addr, regs[3].reg_size * 2)) == 0) { | ||
344 | prom_printf("PCIC: Error, cannot map" | ||
345 | "PCI Configuration Space Data.\n"); | ||
346 | prom_halt(); | ||
347 | } | ||
348 | |||
349 | pbm = &pcic->pbm; | ||
350 | pbm->prom_node = node; | ||
351 | prom_getstring(node, "name", namebuf, 63); namebuf[63] = 0; | ||
352 | strcpy(pbm->prom_name, namebuf); | ||
353 | |||
354 | { | ||
355 | extern volatile int t_nmi[1]; | ||
356 | extern int pcic_nmi_trap_patch[1]; | ||
357 | |||
358 | t_nmi[0] = pcic_nmi_trap_patch[0]; | ||
359 | t_nmi[1] = pcic_nmi_trap_patch[1]; | ||
360 | t_nmi[2] = pcic_nmi_trap_patch[2]; | ||
361 | t_nmi[3] = pcic_nmi_trap_patch[3]; | ||
362 | swift_flush_dcache(); | ||
363 | pcic_regs = pcic->pcic_regs; | ||
364 | } | ||
365 | |||
366 | prom_getstring(prom_root_node, "name", namebuf, 63); namebuf[63] = 0; | ||
367 | { | ||
368 | struct pcic_sn2list *p; | ||
369 | |||
370 | for (p = pcic_known_sysnames; p->sysname != NULL; p++) { | ||
371 | if (strcmp(namebuf, p->sysname) == 0) | ||
372 | break; | ||
373 | } | ||
374 | pcic->pcic_imap = p->intmap; | ||
375 | pcic->pcic_imdim = p->mapdim; | ||
376 | } | ||
377 | if (pcic->pcic_imap == NULL) { | ||
378 | /* | ||
379 | * We do not panic here for the sake of embedded systems. | ||
380 | */ | ||
381 | printk("PCIC: System %s is unknown, cannot route interrupts\n", | ||
382 | namebuf); | ||
383 | } | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic) | ||
389 | { | ||
390 | struct linux_pbm_info *pbm = &pcic->pbm; | ||
391 | |||
392 | pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm); | ||
393 | #if 0 /* deadwood transplanted from sparc64 */ | ||
394 | pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node); | ||
395 | pci_record_assignments(pbm, pbm->pci_bus); | ||
396 | pci_assign_unassigned(pbm, pbm->pci_bus); | ||
397 | pci_fixup_irq(pbm, pbm->pci_bus); | ||
398 | #endif | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Main entry point from the PCI subsystem. | ||
403 | */ | ||
404 | static int __init pcic_init(void) | ||
405 | { | ||
406 | struct linux_pcic *pcic; | ||
407 | |||
408 | /* | ||
409 | * PCIC should be initialized at start of the timer. | ||
410 | * So, here we report the presence of PCIC and do some magic passes. | ||
411 | */ | ||
412 | if(!pcic0_up) | ||
413 | return 0; | ||
414 | pcic = &pcic0; | ||
415 | |||
416 | /* | ||
417 | * Switch off IOTLB translation. | ||
418 | */ | ||
419 | writeb(PCI_DVMA_CONTROL_IOTLB_DISABLE, | ||
420 | pcic->pcic_regs+PCI_DVMA_CONTROL); | ||
421 | |||
422 | /* | ||
423 | * Increase mapped size for PCI memory space (DMA access). | ||
424 | * Should be done in that order (size first, address second). | ||
425 | * Why we couldn't set up 4GB and forget about it? XXX | ||
426 | */ | ||
427 | writel(0xF0000000UL, pcic->pcic_regs+PCI_SIZE_0); | ||
428 | writel(0+PCI_BASE_ADDRESS_SPACE_MEMORY, | ||
429 | pcic->pcic_regs+PCI_BASE_ADDRESS_0); | ||
430 | |||
431 | pcic_pbm_scan_bus(pcic); | ||
432 | |||
433 | ebus_init(); | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | int pcic_present(void) | ||
438 | { | ||
439 | return pcic0_up; | ||
440 | } | ||
441 | |||
442 | static int __init pdev_to_pnode(struct linux_pbm_info *pbm, | ||
443 | struct pci_dev *pdev) | ||
444 | { | ||
445 | struct linux_prom_pci_registers regs[PROMREG_MAX]; | ||
446 | int err; | ||
447 | int node = prom_getchild(pbm->prom_node); | ||
448 | |||
449 | while(node) { | ||
450 | err = prom_getproperty(node, "reg", | ||
451 | (char *)®s[0], sizeof(regs)); | ||
452 | if(err != 0 && err != -1) { | ||
453 | unsigned long devfn = (regs[0].which_io >> 8) & 0xff; | ||
454 | if(devfn == pdev->devfn) | ||
455 | return node; | ||
456 | } | ||
457 | node = prom_getsibling(node); | ||
458 | } | ||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static inline struct pcidev_cookie *pci_devcookie_alloc(void) | ||
463 | { | ||
464 | return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC); | ||
465 | } | ||
466 | |||
467 | static void pcic_map_pci_device(struct linux_pcic *pcic, | ||
468 | struct pci_dev *dev, int node) | ||
469 | { | ||
470 | char namebuf[64]; | ||
471 | unsigned long address; | ||
472 | unsigned long flags; | ||
473 | int j; | ||
474 | |||
475 | if (node == 0 || node == -1) { | ||
476 | strcpy(namebuf, "???"); | ||
477 | } else { | ||
478 | prom_getstring(node, "name", namebuf, 63); namebuf[63] = 0; | ||
479 | } | ||
480 | |||
481 | for (j = 0; j < 6; j++) { | ||
482 | address = dev->resource[j].start; | ||
483 | if (address == 0) break; /* are sequential */ | ||
484 | flags = dev->resource[j].flags; | ||
485 | if ((flags & IORESOURCE_IO) != 0) { | ||
486 | if (address < 0x10000) { | ||
487 | /* | ||
488 | * A device responds to I/O cycles on PCI. | ||
489 | * We generate these cycles with memory | ||
490 | * access into the fixed map (phys 0x30000000). | ||
491 | * | ||
492 | * Since a device driver does not want to | ||
493 | * do ioremap() before accessing PC-style I/O, | ||
494 | * we supply virtual, ready to access address. | ||
495 | * | ||
496 | * Ebus devices do not come here even if | ||
497 | * CheerIO makes a similar conversion. | ||
498 | * See ebus.c for details. | ||
499 | * | ||
500 | * Note that check_region()/request_region() | ||
501 | * work for these devices. | ||
502 | * | ||
503 | * XXX Neat trick, but it's a *bad* idea | ||
504 | * to shit into regions like that. | ||
505 | * What if we want to allocate one more | ||
506 | * PCI base address... | ||
507 | */ | ||
508 | dev->resource[j].start = | ||
509 | pcic->pcic_io + address; | ||
510 | dev->resource[j].end = 1; /* XXX */ | ||
511 | dev->resource[j].flags = | ||
512 | (flags & ~IORESOURCE_IO) | IORESOURCE_MEM; | ||
513 | } else { | ||
514 | /* | ||
515 | * OOPS... PCI Spec allows this. Sun does | ||
516 | * not have any devices getting above 64K | ||
517 | * so it must be user with a weird I/O | ||
518 | * board in a PCI slot. We must remap it | ||
519 | * under 64K but it is not done yet. XXX | ||
520 | */ | ||
521 | printk("PCIC: Skipping I/O space at 0x%lx," | ||
522 | "this will Oops if a driver attaches;" | ||
523 | "device '%s' at %02x:%02x)\n", address, | ||
524 | namebuf, dev->bus->number, dev->devfn); | ||
525 | } | ||
526 | } | ||
527 | } | ||
528 | } | ||
529 | |||
530 | static void | ||
531 | pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) | ||
532 | { | ||
533 | struct pcic_ca2irq *p; | ||
534 | int i, ivec; | ||
535 | char namebuf[64]; | ||
536 | |||
537 | if (node == 0 || node == -1) { | ||
538 | strcpy(namebuf, "???"); | ||
539 | } else { | ||
540 | prom_getstring(node, "name", namebuf, sizeof(namebuf)); | ||
541 | } | ||
542 | |||
543 | if ((p = pcic->pcic_imap) == 0) { | ||
544 | dev->irq = 0; | ||
545 | return; | ||
546 | } | ||
547 | for (i = 0; i < pcic->pcic_imdim; i++) { | ||
548 | if (p->busno == dev->bus->number && p->devfn == dev->devfn) | ||
549 | break; | ||
550 | p++; | ||
551 | } | ||
552 | if (i >= pcic->pcic_imdim) { | ||
553 | printk("PCIC: device %s devfn %02x:%02x not found in %d\n", | ||
554 | namebuf, dev->bus->number, dev->devfn, pcic->pcic_imdim); | ||
555 | dev->irq = 0; | ||
556 | return; | ||
557 | } | ||
558 | |||
559 | i = p->pin; | ||
560 | if (i >= 0 && i < 4) { | ||
561 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); | ||
562 | dev->irq = ivec >> (i << 2) & 0xF; | ||
563 | } else if (i >= 4 && i < 8) { | ||
564 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); | ||
565 | dev->irq = ivec >> ((i-4) << 2) & 0xF; | ||
566 | } else { /* Corrupted map */ | ||
567 | printk("PCIC: BAD PIN %d\n", i); for (;;) {} | ||
568 | } | ||
569 | /* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */ | ||
570 | |||
571 | /* | ||
572 | * dev->irq=0 means PROM did not bother to program the upper | ||
573 | * half of PCIC. This happens on JS-E with PROM 3.11, for instance. | ||
574 | */ | ||
575 | if (dev->irq == 0 || p->force) { | ||
576 | if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */ | ||
577 | printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {} | ||
578 | } | ||
579 | printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n", | ||
580 | p->irq, p->pin, dev->bus->number, dev->devfn); | ||
581 | dev->irq = p->irq; | ||
582 | |||
583 | i = p->pin; | ||
584 | if (i >= 4) { | ||
585 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); | ||
586 | ivec &= ~(0xF << ((i - 4) << 2)); | ||
587 | ivec |= p->irq << ((i - 4) << 2); | ||
588 | writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_HI); | ||
589 | } else { | ||
590 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); | ||
591 | ivec &= ~(0xF << (i << 2)); | ||
592 | ivec |= p->irq << (i << 2); | ||
593 | writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | return; | ||
598 | } | ||
599 | |||
600 | /* | ||
601 | * Normally called from {do_}pci_scan_bus... | ||
602 | */ | ||
603 | void __init pcibios_fixup_bus(struct pci_bus *bus) | ||
604 | { | ||
605 | struct pci_dev *dev; | ||
606 | int i, has_io, has_mem; | ||
607 | unsigned int cmd; | ||
608 | struct linux_pcic *pcic; | ||
609 | /* struct linux_pbm_info* pbm = &pcic->pbm; */ | ||
610 | int node; | ||
611 | struct pcidev_cookie *pcp; | ||
612 | |||
613 | if (!pcic0_up) { | ||
614 | printk("pcibios_fixup_bus: no PCIC\n"); | ||
615 | return; | ||
616 | } | ||
617 | pcic = &pcic0; | ||
618 | |||
619 | /* | ||
620 | * Next crud is an equivalent of pbm = pcic_bus_to_pbm(bus); | ||
621 | */ | ||
622 | if (bus->number != 0) { | ||
623 | printk("pcibios_fixup_bus: nonzero bus 0x%x\n", bus->number); | ||
624 | return; | ||
625 | } | ||
626 | |||
627 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
628 | |||
629 | /* | ||
630 | * Comment from i386 branch: | ||
631 | * There are buggy BIOSes that forget to enable I/O and memory | ||
632 | * access to PCI devices. We try to fix this, but we need to | ||
633 | * be sure that the BIOS didn't forget to assign an address | ||
634 | * to the device. [mj] | ||
635 | * OBP is a case of such BIOS :-) | ||
636 | */ | ||
637 | has_io = has_mem = 0; | ||
638 | for(i=0; i<6; i++) { | ||
639 | unsigned long f = dev->resource[i].flags; | ||
640 | if (f & IORESOURCE_IO) { | ||
641 | has_io = 1; | ||
642 | } else if (f & IORESOURCE_MEM) | ||
643 | has_mem = 1; | ||
644 | } | ||
645 | pcic_read_config(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd); | ||
646 | if (has_io && !(cmd & PCI_COMMAND_IO)) { | ||
647 | printk("PCIC: Enabling I/O for device %02x:%02x\n", | ||
648 | dev->bus->number, dev->devfn); | ||
649 | cmd |= PCI_COMMAND_IO; | ||
650 | pcic_write_config(dev->bus, dev->devfn, | ||
651 | PCI_COMMAND, 2, cmd); | ||
652 | } | ||
653 | if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) { | ||
654 | printk("PCIC: Enabling memory for device %02x:%02x\n", | ||
655 | dev->bus->number, dev->devfn); | ||
656 | cmd |= PCI_COMMAND_MEMORY; | ||
657 | pcic_write_config(dev->bus, dev->devfn, | ||
658 | PCI_COMMAND, 2, cmd); | ||
659 | } | ||
660 | |||
661 | node = pdev_to_pnode(&pcic->pbm, dev); | ||
662 | if(node == 0) | ||
663 | node = -1; | ||
664 | |||
665 | /* cookies */ | ||
666 | pcp = pci_devcookie_alloc(); | ||
667 | pcp->pbm = &pcic->pbm; | ||
668 | pcp->prom_node = node; | ||
669 | dev->sysdata = pcp; | ||
670 | |||
671 | /* fixing I/O to look like memory */ | ||
672 | if ((dev->class>>16) != PCI_BASE_CLASS_BRIDGE) | ||
673 | pcic_map_pci_device(pcic, dev, node); | ||
674 | |||
675 | pcic_fill_irq(pcic, dev, node); | ||
676 | } | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * pcic_pin_to_irq() is exported to ebus.c. | ||
681 | */ | ||
682 | unsigned int | ||
683 | pcic_pin_to_irq(unsigned int pin, char *name) | ||
684 | { | ||
685 | struct linux_pcic *pcic = &pcic0; | ||
686 | unsigned int irq; | ||
687 | unsigned int ivec; | ||
688 | |||
689 | if (pin < 4) { | ||
690 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); | ||
691 | irq = ivec >> (pin << 2) & 0xF; | ||
692 | } else if (pin < 8) { | ||
693 | ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); | ||
694 | irq = ivec >> ((pin-4) << 2) & 0xF; | ||
695 | } else { /* Corrupted map */ | ||
696 | printk("PCIC: BAD PIN %d FOR %s\n", pin, name); | ||
697 | for (;;) {} /* XXX Cannot panic properly in case of PROLL */ | ||
698 | } | ||
699 | /* P3 */ /* printk("PCIC: dev %s pin %d ivec 0x%x irq %x\n", name, pin, ivec, irq); */ | ||
700 | return irq; | ||
701 | } | ||
702 | |||
703 | /* Makes compiler happy */ | ||
704 | static volatile int pcic_timer_dummy; | ||
705 | |||
706 | static void pcic_clear_clock_irq(void) | ||
707 | { | ||
708 | pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT); | ||
709 | } | ||
710 | |||
711 | static irqreturn_t pcic_timer_handler (int irq, void *h, struct pt_regs *regs) | ||
712 | { | ||
713 | write_seqlock(&xtime_lock); /* Dummy, to show that we remember */ | ||
714 | pcic_clear_clock_irq(); | ||
715 | do_timer(regs); | ||
716 | #ifndef CONFIG_SMP | ||
717 | update_process_times(user_mode(regs)); | ||
718 | #endif | ||
719 | write_sequnlock(&xtime_lock); | ||
720 | return IRQ_HANDLED; | ||
721 | } | ||
722 | |||
723 | #define USECS_PER_JIFFY 10000 /* We have 100HZ "standard" timer for sparc */ | ||
724 | #define TICK_TIMER_LIMIT ((100*1000000/4)/100) | ||
725 | |||
726 | void __init pci_time_init(void) | ||
727 | { | ||
728 | struct linux_pcic *pcic = &pcic0; | ||
729 | unsigned long v; | ||
730 | int timer_irq, irq; | ||
731 | |||
732 | /* A hack until do_gettimeofday prototype is moved to arch specific headers | ||
733 | and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */ | ||
734 | ((unsigned int *)do_gettimeofday)[0] = | ||
735 | 0x10800000 | ((((unsigned long)pci_do_gettimeofday - | ||
736 | (unsigned long)do_gettimeofday) >> 2) & 0x003fffff); | ||
737 | ((unsigned int *)do_gettimeofday)[1] = 0x01000000; | ||
738 | BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM); | ||
739 | btfixup(); | ||
740 | |||
741 | writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT); | ||
742 | /* PROM should set appropriate irq */ | ||
743 | v = readb(pcic->pcic_regs+PCI_COUNTER_IRQ); | ||
744 | timer_irq = PCI_COUNTER_IRQ_SYS(v); | ||
745 | writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), | ||
746 | pcic->pcic_regs+PCI_COUNTER_IRQ); | ||
747 | irq = request_irq(timer_irq, pcic_timer_handler, | ||
748 | (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL); | ||
749 | if (irq) { | ||
750 | prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); | ||
751 | prom_halt(); | ||
752 | } | ||
753 | local_irq_enable(); | ||
754 | } | ||
755 | |||
756 | static __inline__ unsigned long do_gettimeoffset(void) | ||
757 | { | ||
758 | /* | ||
759 | * We devide all to 100 | ||
760 | * to have microsecond resolution and to avoid overflow | ||
761 | */ | ||
762 | unsigned long count = | ||
763 | readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; | ||
764 | count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100); | ||
765 | return count; | ||
766 | } | ||
767 | |||
768 | extern unsigned long wall_jiffies; | ||
769 | |||
770 | static void pci_do_gettimeofday(struct timeval *tv) | ||
771 | { | ||
772 | unsigned long flags; | ||
773 | unsigned long seq; | ||
774 | unsigned long usec, sec; | ||
775 | unsigned long max_ntp_tick = tick_usec - tickadj; | ||
776 | |||
777 | do { | ||
778 | unsigned long lost; | ||
779 | |||
780 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | ||
781 | usec = do_gettimeoffset(); | ||
782 | lost = jiffies - wall_jiffies; | ||
783 | |||
784 | /* | ||
785 | * If time_adjust is negative then NTP is slowing the clock | ||
786 | * so make sure not to go into next possible interval. | ||
787 | * Better to lose some accuracy than have time go backwards.. | ||
788 | */ | ||
789 | if (unlikely(time_adjust < 0)) { | ||
790 | usec = min(usec, max_ntp_tick); | ||
791 | |||
792 | if (lost) | ||
793 | usec += lost * max_ntp_tick; | ||
794 | } | ||
795 | else if (unlikely(lost)) | ||
796 | usec += lost * tick_usec; | ||
797 | |||
798 | sec = xtime.tv_sec; | ||
799 | usec += (xtime.tv_nsec / 1000); | ||
800 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
801 | |||
802 | while (usec >= 1000000) { | ||
803 | usec -= 1000000; | ||
804 | sec++; | ||
805 | } | ||
806 | |||
807 | tv->tv_sec = sec; | ||
808 | tv->tv_usec = usec; | ||
809 | } | ||
810 | |||
811 | static int pci_do_settimeofday(struct timespec *tv) | ||
812 | { | ||
813 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | ||
814 | return -EINVAL; | ||
815 | |||
816 | /* | ||
817 | * This is revolting. We need to set "xtime" correctly. However, the | ||
818 | * value in this location is the value at the most recent update of | ||
819 | * wall time. Discover what correction gettimeofday() would have | ||
820 | * made, and then undo it! | ||
821 | */ | ||
822 | tv->tv_nsec -= 1000 * (do_gettimeoffset() + | ||
823 | (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ)); | ||
824 | while (tv->tv_nsec < 0) { | ||
825 | tv->tv_nsec += NSEC_PER_SEC; | ||
826 | tv->tv_sec--; | ||
827 | } | ||
828 | |||
829 | wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec; | ||
830 | wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec; | ||
831 | |||
832 | if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) { | ||
833 | wall_to_monotonic.tv_nsec -= NSEC_PER_SEC; | ||
834 | wall_to_monotonic.tv_sec++; | ||
835 | } | ||
836 | if (wall_to_monotonic.tv_nsec < 0) { | ||
837 | wall_to_monotonic.tv_nsec += NSEC_PER_SEC; | ||
838 | wall_to_monotonic.tv_sec--; | ||
839 | } | ||
840 | |||
841 | xtime.tv_sec = tv->tv_sec; | ||
842 | xtime.tv_nsec = tv->tv_nsec; | ||
843 | time_adjust = 0; /* stop active adjtime() */ | ||
844 | time_status |= STA_UNSYNC; | ||
845 | time_maxerror = NTP_PHASE_LIMIT; | ||
846 | time_esterror = NTP_PHASE_LIMIT; | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | #if 0 | ||
851 | static void watchdog_reset() { | ||
852 | writeb(0, pcic->pcic_regs+PCI_SYS_STATUS); | ||
853 | } | ||
854 | #endif | ||
855 | |||
856 | /* | ||
857 | * Other archs parse arguments here. | ||
858 | */ | ||
859 | char * __init pcibios_setup(char *str) | ||
860 | { | ||
861 | return str; | ||
862 | } | ||
863 | |||
864 | void pcibios_align_resource(void *data, struct resource *res, | ||
865 | unsigned long size, unsigned long align) | ||
866 | { | ||
867 | } | ||
868 | |||
869 | int pcibios_enable_device(struct pci_dev *pdev, int mask) | ||
870 | { | ||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | /* | ||
875 | * NMI | ||
876 | */ | ||
877 | void pcic_nmi(unsigned int pend, struct pt_regs *regs) | ||
878 | { | ||
879 | |||
880 | pend = flip_dword(pend); | ||
881 | |||
882 | if (!pcic_speculative || (pend & PCI_SYS_INT_PENDING_PIO) == 0) { | ||
883 | /* | ||
884 | * XXX On CP-1200 PCI #SERR may happen, we do not know | ||
885 | * what to do about it yet. | ||
886 | */ | ||
887 | printk("Aiee, NMI pend 0x%x pc 0x%x spec %d, hanging\n", | ||
888 | pend, (int)regs->pc, pcic_speculative); | ||
889 | for (;;) { } | ||
890 | } | ||
891 | pcic_speculative = 0; | ||
892 | pcic_trapped = 1; | ||
893 | regs->pc = regs->npc; | ||
894 | regs->npc += 4; | ||
895 | } | ||
896 | |||
897 | static inline unsigned long get_irqmask(int irq_nr) | ||
898 | { | ||
899 | return 1 << irq_nr; | ||
900 | } | ||
901 | |||
902 | static inline char *pcic_irq_itoa(unsigned int irq) | ||
903 | { | ||
904 | static char buff[16]; | ||
905 | sprintf(buff, "%d", irq); | ||
906 | return buff; | ||
907 | } | ||
908 | |||
909 | static void pcic_disable_irq(unsigned int irq_nr) | ||
910 | { | ||
911 | unsigned long mask, flags; | ||
912 | |||
913 | mask = get_irqmask(irq_nr); | ||
914 | local_irq_save(flags); | ||
915 | writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); | ||
916 | local_irq_restore(flags); | ||
917 | } | ||
918 | |||
919 | static void pcic_enable_irq(unsigned int irq_nr) | ||
920 | { | ||
921 | unsigned long mask, flags; | ||
922 | |||
923 | mask = get_irqmask(irq_nr); | ||
924 | local_irq_save(flags); | ||
925 | writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); | ||
926 | local_irq_restore(flags); | ||
927 | } | ||
928 | |||
929 | static void pcic_clear_profile_irq(int cpu) | ||
930 | { | ||
931 | printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); | ||
932 | } | ||
933 | |||
934 | static void pcic_load_profile_irq(int cpu, unsigned int limit) | ||
935 | { | ||
936 | printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); | ||
937 | } | ||
938 | |||
939 | /* We assume the caller has disabled local interrupts when these are called, | ||
940 | * or else very bizarre behavior will result. | ||
941 | */ | ||
942 | static void pcic_disable_pil_irq(unsigned int pil) | ||
943 | { | ||
944 | writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); | ||
945 | } | ||
946 | |||
947 | static void pcic_enable_pil_irq(unsigned int pil) | ||
948 | { | ||
949 | writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); | ||
950 | } | ||
951 | |||
952 | void __init sun4m_pci_init_IRQ(void) | ||
953 | { | ||
954 | BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM); | ||
955 | BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM); | ||
956 | BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM); | ||
957 | BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM); | ||
958 | BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); | ||
959 | BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM); | ||
960 | BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); | ||
961 | BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM); | ||
962 | } | ||
963 | |||
964 | int pcibios_assign_resource(struct pci_dev *pdev, int resource) | ||
965 | { | ||
966 | return -ENXIO; | ||
967 | } | ||
968 | |||
969 | /* | ||
970 | * This probably belongs here rather than ioport.c because | ||
971 | * we do not want this crud linked into SBus kernels. | ||
972 | * Also, think for a moment about likes of floppy.c that | ||
973 | * include architecture specific parts. They may want to redefine ins/outs. | ||
974 | * | ||
975 | * We do not use horroble macroses here because we want to | ||
976 | * advance pointer by sizeof(size). | ||
977 | */ | ||
978 | void outsb(unsigned long addr, const void *src, unsigned long count) | ||
979 | { | ||
980 | while (count) { | ||
981 | count -= 1; | ||
982 | outb(*(const char *)src, addr); | ||
983 | src += 1; | ||
984 | /* addr += 1; */ | ||
985 | } | ||
986 | } | ||
987 | |||
988 | void outsw(unsigned long addr, const void *src, unsigned long count) | ||
989 | { | ||
990 | while (count) { | ||
991 | count -= 2; | ||
992 | outw(*(const short *)src, addr); | ||
993 | src += 2; | ||
994 | /* addr += 2; */ | ||
995 | } | ||
996 | } | ||
997 | |||
998 | void outsl(unsigned long addr, const void *src, unsigned long count) | ||
999 | { | ||
1000 | while (count) { | ||
1001 | count -= 4; | ||
1002 | outl(*(const long *)src, addr); | ||
1003 | src += 4; | ||
1004 | /* addr += 4; */ | ||
1005 | } | ||
1006 | } | ||
1007 | |||
1008 | void insb(unsigned long addr, void *dst, unsigned long count) | ||
1009 | { | ||
1010 | while (count) { | ||
1011 | count -= 1; | ||
1012 | *(unsigned char *)dst = inb(addr); | ||
1013 | dst += 1; | ||
1014 | /* addr += 1; */ | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | void insw(unsigned long addr, void *dst, unsigned long count) | ||
1019 | { | ||
1020 | while (count) { | ||
1021 | count -= 2; | ||
1022 | *(unsigned short *)dst = inw(addr); | ||
1023 | dst += 2; | ||
1024 | /* addr += 2; */ | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | void insl(unsigned long addr, void *dst, unsigned long count) | ||
1029 | { | ||
1030 | while (count) { | ||
1031 | count -= 4; | ||
1032 | /* | ||
1033 | * XXX I am sure we are in for an unaligned trap here. | ||
1034 | */ | ||
1035 | *(unsigned long *)dst = inl(addr); | ||
1036 | dst += 4; | ||
1037 | /* addr += 4; */ | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | subsys_initcall(pcic_init); | ||