diff options
Diffstat (limited to 'arch/m68knommu/kernel/comempci.c')
-rw-r--r-- | arch/m68knommu/kernel/comempci.c | 980 |
1 files changed, 0 insertions, 980 deletions
diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c deleted file mode 100644 index 0a68b5a85f86..000000000000 --- a/arch/m68knommu/kernel/comempci.c +++ /dev/null | |||
@@ -1,980 +0,0 @@ | |||
1 | /*****************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller. | ||
5 | * | ||
6 | * (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com). | ||
7 | * (C) Copyright 2000, Lineo (www.lineo.com) | ||
8 | */ | ||
9 | |||
10 | /*****************************************************************************/ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <linux/ptrace.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <asm/coldfire.h> | ||
20 | #include <asm/mcfsim.h> | ||
21 | #include <asm/irq.h> | ||
22 | #include <asm/anchor.h> | ||
23 | |||
24 | #ifdef CONFIG_eLIA | ||
25 | #include <asm/elia.h> | ||
26 | #endif | ||
27 | |||
28 | /*****************************************************************************/ | ||
29 | |||
30 | /* | ||
31 | * Debug configuration defines. DEBUGRES sets debugging output for | ||
32 | * the resource allocation phase. DEBUGPCI traces on pcibios_ function | ||
33 | * calls, and DEBUGIO traces all accesses to devices on the PCI bus. | ||
34 | */ | ||
35 | /*#define DEBUGRES 1*/ | ||
36 | /*#define DEBUGPCI 1*/ | ||
37 | /*#define DEBUGIO 1*/ | ||
38 | |||
39 | /*****************************************************************************/ | ||
40 | |||
41 | /* | ||
42 | * PCI markers for bus present and active slots. | ||
43 | */ | ||
44 | int pci_bus_is_present = 0; | ||
45 | unsigned long pci_slotmask = 0; | ||
46 | |||
47 | /* | ||
48 | * We may or may not need to swap the bytes of PCI bus tranfers. | ||
49 | * The endianess is re-roder automatically by the CO-MEM, but it | ||
50 | * will get the wrong byte order for a pure data stream. | ||
51 | */ | ||
52 | #define pci_byteswap 0 | ||
53 | |||
54 | |||
55 | /* | ||
56 | * Resource tracking. The CO-MEM part creates a virtual address | ||
57 | * space that all the PCI devices live in - it is not in any way | ||
58 | * directly mapped into the ColdFire address space. So we can | ||
59 | * really assign any resources we like to devices, as long as | ||
60 | * they do not clash with other PCI devices. | ||
61 | */ | ||
62 | unsigned int pci_iobase = PCIBIOS_MIN_IO; /* Arbitrary start address */ | ||
63 | unsigned int pci_membase = PCIBIOS_MIN_MEM; /* Arbitrary start address */ | ||
64 | |||
65 | #define PCI_MINIO 0x100 /* 256 byte minimum I/O */ | ||
66 | #define PCI_MINMEM 0x00010000 /* 64k minimum chunk */ | ||
67 | |||
68 | /* | ||
69 | * The CO-MEM's shared memory segment is visible inside the PCI | ||
70 | * memory address space. We need to keep track of the address that | ||
71 | * this is mapped at, to setup the bus masters pointers. | ||
72 | */ | ||
73 | unsigned int pci_shmemaddr; | ||
74 | |||
75 | /*****************************************************************************/ | ||
76 | |||
77 | void pci_interrupt(int irq, void *id, struct pt_regs *fp); | ||
78 | |||
79 | /*****************************************************************************/ | ||
80 | |||
81 | /* | ||
82 | * Some platforms have custom ways of reseting the PCI bus. | ||
83 | */ | ||
84 | |||
85 | void pci_resetbus(void) | ||
86 | { | ||
87 | #ifdef CONFIG_eLIA | ||
88 | int i; | ||
89 | |||
90 | #ifdef DEBUGPCI | ||
91 | printk(KERN_DEBUG "pci_resetbus()\n"); | ||
92 | #endif | ||
93 | |||
94 | *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADDR)) |= eLIA_PCIRESET; | ||
95 | for (i = 0; (i < 1000); i++) { | ||
96 | *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = | ||
97 | (ppdata | eLIA_PCIRESET); | ||
98 | } | ||
99 | |||
100 | |||
101 | *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = ppdata; | ||
102 | #endif | ||
103 | } | ||
104 | |||
105 | /*****************************************************************************/ | ||
106 | |||
107 | int pcibios_assign_resource_slot(int slot) | ||
108 | { | ||
109 | volatile unsigned long *rp; | ||
110 | volatile unsigned char *ip; | ||
111 | unsigned int idsel, addr, val, align, i; | ||
112 | int bar; | ||
113 | |||
114 | #ifdef DEBUGPCI | ||
115 | printk(KERN_INFO "pcibios_assign_resource_slot(slot=%x)\n", slot); | ||
116 | #endif | ||
117 | |||
118 | rp = (volatile unsigned long *) COMEM_BASE; | ||
119 | idsel = COMEM_DA_ADDR(0x1 << (slot + 16)); | ||
120 | |||
121 | /* Try to assign resource to each BAR */ | ||
122 | for (bar = 0; (bar < 6); bar++) { | ||
123 | addr = COMEM_PCIBUS + PCI_BASE_ADDRESS_0 + (bar * 4); | ||
124 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; | ||
125 | val = rp[LREG(addr)]; | ||
126 | #ifdef DEBUGRES | ||
127 | printk(KERN_DEBUG "-----------------------------------" | ||
128 | "-------------------------------------\n"); | ||
129 | printk(KERN_DEBUG "BAR[%d]: read=%08x ", bar, val); | ||
130 | #endif | ||
131 | |||
132 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; | ||
133 | rp[LREG(addr)] = 0xffffffff; | ||
134 | |||
135 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; | ||
136 | val = rp[LREG(addr)]; | ||
137 | #ifdef DEBUGRES | ||
138 | printk(KERN_DEBUG "write=%08x ", val); | ||
139 | #endif | ||
140 | if (val == 0) { | ||
141 | #ifdef DEBUGRES | ||
142 | printk(KERN_DEBUG "\n"); | ||
143 | #endif | ||
144 | continue; | ||
145 | } | ||
146 | |||
147 | /* Determine space required by BAR */ | ||
148 | /* FIXME: this should go backwords from 0x80000000... */ | ||
149 | for (i = 0; (i < 32); i++) { | ||
150 | if ((0x1 << i) & (val & 0xfffffffc)) | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | #ifdef DEBUGRES | ||
155 | printk(KERN_DEBUG "size=%08x(%d)\n", (0x1 << i), i); | ||
156 | #endif | ||
157 | i = 0x1 << i; | ||
158 | |||
159 | /* Assign a resource */ | ||
160 | if (val & PCI_BASE_ADDRESS_SPACE_IO) { | ||
161 | if (i < PCI_MINIO) | ||
162 | i = PCI_MINIO; | ||
163 | #ifdef DEBUGRES | ||
164 | printk(KERN_DEBUG "BAR[%d]: IO size=%08x iobase=%08x\n", | ||
165 | bar, i, pci_iobase); | ||
166 | #endif | ||
167 | if (i > 0xffff) { | ||
168 | /* Invalid size?? */ | ||
169 | val = 0 | PCI_BASE_ADDRESS_SPACE_IO; | ||
170 | #ifdef DEBUGRES | ||
171 | printk(KERN_DEBUG "BAR[%d]: too big for IO??\n", bar); | ||
172 | #endif | ||
173 | } else { | ||
174 | /* Check for un-alignment */ | ||
175 | if ((align = pci_iobase % i)) | ||
176 | pci_iobase += (i - align); | ||
177 | val = pci_iobase | PCI_BASE_ADDRESS_SPACE_IO; | ||
178 | pci_iobase += i; | ||
179 | } | ||
180 | } else { | ||
181 | if (i < PCI_MINMEM) | ||
182 | i = PCI_MINMEM; | ||
183 | #ifdef DEBUGRES | ||
184 | printk(KERN_DEBUG "BAR[%d]: MEMORY size=%08x membase=%08x\n", | ||
185 | bar, i, pci_membase); | ||
186 | #endif | ||
187 | /* Check for un-alignment */ | ||
188 | if ((align = pci_membase % i)) | ||
189 | pci_membase += (i - align); | ||
190 | val = pci_membase | PCI_BASE_ADDRESS_SPACE_MEMORY; | ||
191 | pci_membase += i; | ||
192 | } | ||
193 | |||
194 | /* Write resource back into BAR register */ | ||
195 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; | ||
196 | rp[LREG(addr)] = val; | ||
197 | #ifdef DEBUGRES | ||
198 | printk(KERN_DEBUG "BAR[%d]: assigned bar=%08x\n", bar, val); | ||
199 | #endif | ||
200 | } | ||
201 | |||
202 | #ifdef DEBUGRES | ||
203 | printk(KERN_DEBUG "-----------------------------------" | ||
204 | "-------------------------------------\n"); | ||
205 | #endif | ||
206 | |||
207 | /* Assign IRQ if one is wanted... */ | ||
208 | ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS); | ||
209 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; | ||
210 | |||
211 | addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03); | ||
212 | if (ip[addr]) { | ||
213 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; | ||
214 | addr = (PCI_INTERRUPT_LINE & 0xfc)+(~PCI_INTERRUPT_LINE & 0x03); | ||
215 | ip[addr] = 25; | ||
216 | #ifdef DEBUGRES | ||
217 | printk(KERN_DEBUG "IRQ LINE=25\n"); | ||
218 | #endif | ||
219 | } | ||
220 | |||
221 | return(0); | ||
222 | } | ||
223 | |||
224 | /*****************************************************************************/ | ||
225 | |||
226 | int pcibios_enable_slot(int slot) | ||
227 | { | ||
228 | volatile unsigned long *rp; | ||
229 | volatile unsigned short *wp; | ||
230 | unsigned int idsel, addr; | ||
231 | unsigned short cmd; | ||
232 | |||
233 | #ifdef DEBUGPCI | ||
234 | printk(KERN_DEBUG "pcibios_enbale_slot(slot=%x)\n", slot); | ||
235 | #endif | ||
236 | |||
237 | rp = (volatile unsigned long *) COMEM_BASE; | ||
238 | wp = (volatile unsigned short *) COMEM_BASE; | ||
239 | idsel = COMEM_DA_ADDR(0x1 << (slot + 16)); | ||
240 | |||
241 | /* Get current command settings */ | ||
242 | addr = COMEM_PCIBUS + PCI_COMMAND; | ||
243 | addr = (addr & ~0x3) + (~addr & 0x02); | ||
244 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; | ||
245 | cmd = wp[WREG(addr)]; | ||
246 | /*val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);*/ | ||
247 | |||
248 | /* Enable I/O and memory accesses to this device */ | ||
249 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; | ||
250 | cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | ||
251 | wp[WREG(addr)] = cmd; | ||
252 | |||
253 | return(0); | ||
254 | } | ||
255 | |||
256 | /*****************************************************************************/ | ||
257 | |||
258 | void pcibios_assign_resources(void) | ||
259 | { | ||
260 | volatile unsigned long *rp; | ||
261 | unsigned long sel, id; | ||
262 | int slot; | ||
263 | |||
264 | rp = (volatile unsigned long *) COMEM_BASE; | ||
265 | |||
266 | /* | ||
267 | * Do a quick scan of the PCI bus and see what is here. | ||
268 | */ | ||
269 | for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) { | ||
270 | sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16)); | ||
271 | rp[LREG(COMEM_DAHBASE)] = sel; | ||
272 | rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */ | ||
273 | id = rp[LREG(COMEM_PCIBUS)]; | ||
274 | if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) { | ||
275 | printk(KERN_INFO "PCI: slot=%d id=%08x\n", slot, (int) id); | ||
276 | pci_slotmask |= 0x1 << slot; | ||
277 | pcibios_assign_resource_slot(slot); | ||
278 | pcibios_enable_slot(slot); | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /*****************************************************************************/ | ||
284 | |||
285 | int pcibios_init(void) | ||
286 | { | ||
287 | volatile unsigned long *rp; | ||
288 | unsigned long sel, id; | ||
289 | int slot; | ||
290 | |||
291 | #ifdef DEBUGPCI | ||
292 | printk(KERN_DEBUG "pcibios_init()\n"); | ||
293 | #endif | ||
294 | |||
295 | pci_resetbus(); | ||
296 | |||
297 | /* | ||
298 | * Do some sort of basic check to see if the CO-MEM part | ||
299 | * is present... This works ok, but I think we really need | ||
300 | * something better... | ||
301 | */ | ||
302 | rp = (volatile unsigned long *) COMEM_BASE; | ||
303 | if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) { | ||
304 | printk(KERN_INFO "PCI: no PCI bus present\n"); | ||
305 | return(0); | ||
306 | } | ||
307 | |||
308 | #ifdef COMEM_BRIDGEDEV | ||
309 | /* | ||
310 | * Setup the PCI bridge device first. It needs resources too, | ||
311 | * so that bus masters can get to its shared memory. | ||
312 | */ | ||
313 | slot = COMEM_BRIDGEDEV; | ||
314 | sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16)); | ||
315 | rp[LREG(COMEM_DAHBASE)] = sel; | ||
316 | rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */ | ||
317 | id = rp[LREG(COMEM_PCIBUS)]; | ||
318 | if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) { | ||
319 | printk(KERN_INFO "PCI: no PCI bus bridge present\n"); | ||
320 | return(0); | ||
321 | } | ||
322 | |||
323 | printk(KERN_INFO "PCI: bridge device at slot=%d id=%08x\n", slot, (int) id); | ||
324 | pci_slotmask |= 0x1 << slot; | ||
325 | pci_shmemaddr = pci_membase; | ||
326 | pcibios_assign_resource_slot(slot); | ||
327 | pcibios_enable_slot(slot); | ||
328 | #endif | ||
329 | |||
330 | pci_bus_is_present = 1; | ||
331 | |||
332 | /* Get PCI irq for local vectoring */ | ||
333 | if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) { | ||
334 | printk(KERN_WARNING "PCI: failed to acquire interrupt %d\n", COMEM_IRQ); | ||
335 | } else { | ||
336 | mcf_autovector(COMEM_IRQ); | ||
337 | } | ||
338 | |||
339 | pcibios_assign_resources(); | ||
340 | |||
341 | return(0); | ||
342 | } | ||
343 | |||
344 | /*****************************************************************************/ | ||
345 | |||
346 | char *pcibios_setup(char *option) | ||
347 | { | ||
348 | /* Nothing for us to handle. */ | ||
349 | return(option); | ||
350 | } | ||
351 | /*****************************************************************************/ | ||
352 | |||
353 | void pcibios_fixup_bus(struct pci_bus *b) | ||
354 | { | ||
355 | } | ||
356 | |||
357 | /*****************************************************************************/ | ||
358 | |||
359 | void pcibios_align_resource(void *data, struct resource *res, | ||
360 | resource_size_t size, resource_size_t align) | ||
361 | { | ||
362 | } | ||
363 | |||
364 | /*****************************************************************************/ | ||
365 | |||
366 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
367 | { | ||
368 | int slot; | ||
369 | |||
370 | slot = PCI_SLOT(dev->devfn); | ||
371 | if ((dev->bus == 0) && (pci_slotmask & (1 << slot))) | ||
372 | pcibios_enable_slot(slot); | ||
373 | return(0); | ||
374 | } | ||
375 | |||
376 | /*****************************************************************************/ | ||
377 | |||
378 | /* | ||
379 | * Local routines to interrcept the standard I/O and vector handling | ||
380 | * code. Don't include this 'till now - initialization code above needs | ||
381 | * access to the real code too. | ||
382 | */ | ||
383 | #include <asm/mcfpci.h> | ||
384 | |||
385 | /*****************************************************************************/ | ||
386 | |||
387 | void pci_outb(unsigned char val, unsigned int addr) | ||
388 | { | ||
389 | volatile unsigned long *rp; | ||
390 | volatile unsigned char *bp; | ||
391 | |||
392 | #ifdef DEBUGIO | ||
393 | printk(KERN_DEBUG "pci_outb(val=%02x,addr=%x)\n", val, addr); | ||
394 | #endif | ||
395 | |||
396 | rp = (volatile unsigned long *) COMEM_BASE; | ||
397 | bp = (volatile unsigned char *) COMEM_BASE; | ||
398 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr); | ||
399 | addr = (addr & ~0x3) + (~addr & 0x03); | ||
400 | bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val; | ||
401 | } | ||
402 | |||
403 | /*****************************************************************************/ | ||
404 | |||
405 | void pci_outw(unsigned short val, unsigned int addr) | ||
406 | { | ||
407 | volatile unsigned long *rp; | ||
408 | volatile unsigned short *sp; | ||
409 | |||
410 | #ifdef DEBUGIO | ||
411 | printk(KERN_DEBUG "pci_outw(val=%04x,addr=%x)\n", val, addr); | ||
412 | #endif | ||
413 | |||
414 | rp = (volatile unsigned long *) COMEM_BASE; | ||
415 | sp = (volatile unsigned short *) COMEM_BASE; | ||
416 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr); | ||
417 | addr = (addr & ~0x3) + (~addr & 0x02); | ||
418 | if (pci_byteswap) | ||
419 | val = ((val & 0xff) << 8) | ((val >> 8) & 0xff); | ||
420 | sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val; | ||
421 | } | ||
422 | |||
423 | /*****************************************************************************/ | ||
424 | |||
425 | void pci_outl(unsigned int val, unsigned int addr) | ||
426 | { | ||
427 | volatile unsigned long *rp; | ||
428 | volatile unsigned int *lp; | ||
429 | |||
430 | #ifdef DEBUGIO | ||
431 | printk(KERN_DEBUG "pci_outl(val=%08x,addr=%x)\n", val, addr); | ||
432 | #endif | ||
433 | |||
434 | rp = (volatile unsigned long *) COMEM_BASE; | ||
435 | lp = (volatile unsigned int *) COMEM_BASE; | ||
436 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr); | ||
437 | |||
438 | if (pci_byteswap) | ||
439 | val = (val << 24) | ((val & 0x0000ff00) << 8) | | ||
440 | ((val & 0x00ff0000) >> 8) | (val >> 24); | ||
441 | |||
442 | lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val; | ||
443 | } | ||
444 | |||
445 | /*****************************************************************************/ | ||
446 | |||
447 | unsigned long pci_blmask[] = { | ||
448 | 0x000000e0, | ||
449 | 0x000000d0, | ||
450 | 0x000000b0, | ||
451 | 0x00000070 | ||
452 | }; | ||
453 | |||
454 | unsigned char pci_inb(unsigned int addr) | ||
455 | { | ||
456 | volatile unsigned long *rp; | ||
457 | volatile unsigned char *bp; | ||
458 | unsigned long r; | ||
459 | unsigned char val; | ||
460 | |||
461 | #ifdef DEBUGIO | ||
462 | printk(KERN_DEBUG "pci_inb(addr=%x)\n", addr); | ||
463 | #endif | ||
464 | |||
465 | rp = (volatile unsigned long *) COMEM_BASE; | ||
466 | bp = (volatile unsigned char *) COMEM_BASE; | ||
467 | |||
468 | r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_blmask[(addr & 0x3)]; | ||
469 | rp[LREG(COMEM_DAHBASE)] = r; | ||
470 | |||
471 | addr = (addr & ~0x3) + (~addr & 0x3); | ||
472 | val = bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))]; | ||
473 | return(val); | ||
474 | } | ||
475 | |||
476 | /*****************************************************************************/ | ||
477 | |||
478 | unsigned long pci_bwmask[] = { | ||
479 | 0x000000c0, | ||
480 | 0x000000c0, | ||
481 | 0x00000030, | ||
482 | 0x00000030 | ||
483 | }; | ||
484 | |||
485 | unsigned short pci_inw(unsigned int addr) | ||
486 | { | ||
487 | volatile unsigned long *rp; | ||
488 | volatile unsigned short *sp; | ||
489 | unsigned long r; | ||
490 | unsigned short val; | ||
491 | |||
492 | #ifdef DEBUGIO | ||
493 | printk(KERN_DEBUG "pci_inw(addr=%x)", addr); | ||
494 | #endif | ||
495 | |||
496 | rp = (volatile unsigned long *) COMEM_BASE; | ||
497 | r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_bwmask[(addr & 0x3)]; | ||
498 | rp[LREG(COMEM_DAHBASE)] = r; | ||
499 | |||
500 | sp = (volatile unsigned short *) COMEM_BASE; | ||
501 | addr = (addr & ~0x3) + (~addr & 0x02); | ||
502 | val = sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))]; | ||
503 | if (pci_byteswap) | ||
504 | val = ((val & 0xff) << 8) | ((val >> 8) & 0xff); | ||
505 | #ifdef DEBUGIO | ||
506 | printk(KERN_DEBUG "=%04x\n", val); | ||
507 | #endif | ||
508 | return(val); | ||
509 | } | ||
510 | |||
511 | /*****************************************************************************/ | ||
512 | |||
513 | unsigned int pci_inl(unsigned int addr) | ||
514 | { | ||
515 | volatile unsigned long *rp; | ||
516 | volatile unsigned int *lp; | ||
517 | unsigned int val; | ||
518 | |||
519 | #ifdef DEBUGIO | ||
520 | printk(KERN_DEBUG "pci_inl(addr=%x)", addr); | ||
521 | #endif | ||
522 | |||
523 | rp = (volatile unsigned long *) COMEM_BASE; | ||
524 | lp = (volatile unsigned int *) COMEM_BASE; | ||
525 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr); | ||
526 | val = lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))]; | ||
527 | |||
528 | if (pci_byteswap) | ||
529 | val = (val << 24) | ((val & 0x0000ff00) << 8) | | ||
530 | ((val & 0x00ff0000) >> 8) | (val >> 24); | ||
531 | |||
532 | #ifdef DEBUGIO | ||
533 | printk(KERN_DEBUG "=%08x\n", val); | ||
534 | #endif | ||
535 | return(val); | ||
536 | } | ||
537 | |||
538 | /*****************************************************************************/ | ||
539 | |||
540 | void pci_outsb(void *addr, void *buf, int len) | ||
541 | { | ||
542 | volatile unsigned long *rp; | ||
543 | volatile unsigned char *bp; | ||
544 | unsigned char *dp = (unsigned char *) buf; | ||
545 | unsigned int a = (unsigned int) addr; | ||
546 | |||
547 | #ifdef DEBUGIO | ||
548 | printk(KERN_DEBUG "pci_outsb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); | ||
549 | #endif | ||
550 | |||
551 | rp = (volatile unsigned long *) COMEM_BASE; | ||
552 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a); | ||
553 | |||
554 | a = (a & ~0x3) + (~a & 0x03); | ||
555 | bp = (volatile unsigned char *) | ||
556 | (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); | ||
557 | |||
558 | while (len--) | ||
559 | *bp = *dp++; | ||
560 | } | ||
561 | |||
562 | /*****************************************************************************/ | ||
563 | |||
564 | void pci_outsw(void *addr, void *buf, int len) | ||
565 | { | ||
566 | volatile unsigned long *rp; | ||
567 | volatile unsigned short *wp; | ||
568 | unsigned short w, *dp = (unsigned short *) buf; | ||
569 | unsigned int a = (unsigned int) addr; | ||
570 | |||
571 | #ifdef DEBUGIO | ||
572 | printk(KERN_DEBUG "pci_outsw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); | ||
573 | #endif | ||
574 | |||
575 | rp = (volatile unsigned long *) COMEM_BASE; | ||
576 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a); | ||
577 | |||
578 | a = (a & ~0x3) + (~a & 0x2); | ||
579 | wp = (volatile unsigned short *) | ||
580 | (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); | ||
581 | |||
582 | while (len--) { | ||
583 | w = *dp++; | ||
584 | if (pci_byteswap) | ||
585 | w = ((w & 0xff) << 8) | ((w >> 8) & 0xff); | ||
586 | *wp = w; | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /*****************************************************************************/ | ||
591 | |||
592 | void pci_outsl(void *addr, void *buf, int len) | ||
593 | { | ||
594 | volatile unsigned long *rp; | ||
595 | volatile unsigned long *lp; | ||
596 | unsigned long l, *dp = (unsigned long *) buf; | ||
597 | unsigned int a = (unsigned int) addr; | ||
598 | |||
599 | #ifdef DEBUGIO | ||
600 | printk(KERN_DEBUG "pci_outsl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); | ||
601 | #endif | ||
602 | |||
603 | rp = (volatile unsigned long *) COMEM_BASE; | ||
604 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a); | ||
605 | |||
606 | lp = (volatile unsigned long *) | ||
607 | (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); | ||
608 | |||
609 | while (len--) { | ||
610 | l = *dp++; | ||
611 | if (pci_byteswap) | ||
612 | l = (l << 24) | ((l & 0x0000ff00) << 8) | | ||
613 | ((l & 0x00ff0000) >> 8) | (l >> 24); | ||
614 | *lp = l; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | /*****************************************************************************/ | ||
619 | |||
620 | void pci_insb(void *addr, void *buf, int len) | ||
621 | { | ||
622 | volatile unsigned long *rp; | ||
623 | volatile unsigned char *bp; | ||
624 | unsigned char *dp = (unsigned char *) buf; | ||
625 | unsigned int a = (unsigned int) addr; | ||
626 | |||
627 | #ifdef DEBUGIO | ||
628 | printk(KERN_DEBUG "pci_insb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); | ||
629 | #endif | ||
630 | |||
631 | rp = (volatile unsigned long *) COMEM_BASE; | ||
632 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a); | ||
633 | |||
634 | a = (a & ~0x3) + (~a & 0x03); | ||
635 | bp = (volatile unsigned char *) | ||
636 | (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); | ||
637 | |||
638 | while (len--) | ||
639 | *dp++ = *bp; | ||
640 | } | ||
641 | |||
642 | /*****************************************************************************/ | ||
643 | |||
644 | void pci_insw(void *addr, void *buf, int len) | ||
645 | { | ||
646 | volatile unsigned long *rp; | ||
647 | volatile unsigned short *wp; | ||
648 | unsigned short w, *dp = (unsigned short *) buf; | ||
649 | unsigned int a = (unsigned int) addr; | ||
650 | |||
651 | #ifdef DEBUGIO | ||
652 | printk(KERN_DEBUG "pci_insw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); | ||
653 | #endif | ||
654 | |||
655 | rp = (volatile unsigned long *) COMEM_BASE; | ||
656 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a); | ||
657 | |||
658 | a = (a & ~0x3) + (~a & 0x2); | ||
659 | wp = (volatile unsigned short *) | ||
660 | (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); | ||
661 | |||
662 | while (len--) { | ||
663 | w = *wp; | ||
664 | if (pci_byteswap) | ||
665 | w = ((w & 0xff) << 8) | ((w >> 8) & 0xff); | ||
666 | *dp++ = w; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | /*****************************************************************************/ | ||
671 | |||
672 | void pci_insl(void *addr, void *buf, int len) | ||
673 | { | ||
674 | volatile unsigned long *rp; | ||
675 | volatile unsigned long *lp; | ||
676 | unsigned long l, *dp = (unsigned long *) buf; | ||
677 | unsigned int a = (unsigned int) addr; | ||
678 | |||
679 | #ifdef DEBUGIO | ||
680 | printk(KERN_DEBUG "pci_insl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); | ||
681 | #endif | ||
682 | |||
683 | rp = (volatile unsigned long *) COMEM_BASE; | ||
684 | rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a); | ||
685 | |||
686 | lp = (volatile unsigned long *) | ||
687 | (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); | ||
688 | |||
689 | while (len--) { | ||
690 | l = *lp; | ||
691 | if (pci_byteswap) | ||
692 | l = (l << 24) | ((l & 0x0000ff00) << 8) | | ||
693 | ((l & 0x00ff0000) >> 8) | (l >> 24); | ||
694 | *dp++ = l; | ||
695 | } | ||
696 | } | ||
697 | |||
698 | /*****************************************************************************/ | ||
699 | |||
700 | struct pci_localirqlist { | ||
701 | void (*handler)(int, void *, struct pt_regs *); | ||
702 | const char *device; | ||
703 | void *dev_id; | ||
704 | }; | ||
705 | |||
706 | struct pci_localirqlist pci_irqlist[COMEM_MAXPCI]; | ||
707 | |||
708 | /*****************************************************************************/ | ||
709 | |||
710 | int pci_request_irq(unsigned int irq, | ||
711 | void (*handler)(int, void *, struct pt_regs *), | ||
712 | unsigned long flags, const char *device, void *dev_id) | ||
713 | { | ||
714 | int i; | ||
715 | |||
716 | #ifdef DEBUGIO | ||
717 | printk(KERN_DEBUG "pci_request_irq(irq=%d,handler=%x,flags=%x,device=%s," | ||
718 | "dev_id=%x)\n", irq, (int) handler, (int) flags, device, | ||
719 | (int) dev_id); | ||
720 | #endif | ||
721 | |||
722 | /* Check if this interrupt handler is already lodged */ | ||
723 | for (i = 0; (i < COMEM_MAXPCI); i++) { | ||
724 | if (pci_irqlist[i].handler == handler) | ||
725 | return(0); | ||
726 | } | ||
727 | |||
728 | /* Find a free spot to put this handler */ | ||
729 | for (i = 0; (i < COMEM_MAXPCI); i++) { | ||
730 | if (pci_irqlist[i].handler == 0) { | ||
731 | pci_irqlist[i].handler = handler; | ||
732 | pci_irqlist[i].device = device; | ||
733 | pci_irqlist[i].dev_id = dev_id; | ||
734 | return(0); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | /* Couldn't fit?? */ | ||
739 | return(1); | ||
740 | } | ||
741 | |||
742 | /*****************************************************************************/ | ||
743 | |||
744 | void pci_free_irq(unsigned int irq, void *dev_id) | ||
745 | { | ||
746 | int i; | ||
747 | |||
748 | #ifdef DEBUGIO | ||
749 | printk(KERN_DEBUG "pci_free_irq(irq=%d,dev_id=%x)\n", irq, (int) dev_id); | ||
750 | #endif | ||
751 | |||
752 | if (dev_id == (void *) NULL) | ||
753 | return; | ||
754 | |||
755 | /* Check if this interrupt handler is lodged */ | ||
756 | for (i = 0; (i < COMEM_MAXPCI); i++) { | ||
757 | if (pci_irqlist[i].dev_id == dev_id) { | ||
758 | pci_irqlist[i].handler = NULL; | ||
759 | pci_irqlist[i].device = NULL; | ||
760 | pci_irqlist[i].dev_id = NULL; | ||
761 | break; | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | |||
766 | /*****************************************************************************/ | ||
767 | |||
768 | void pci_interrupt(int irq, void *id, struct pt_regs *fp) | ||
769 | { | ||
770 | int i; | ||
771 | |||
772 | #ifdef DEBUGIO | ||
773 | printk(KERN_DEBUG "pci_interrupt(irq=%d,id=%x,fp=%x)\n", irq, (int) id, (int) fp); | ||
774 | #endif | ||
775 | |||
776 | for (i = 0; (i < COMEM_MAXPCI); i++) { | ||
777 | if (pci_irqlist[i].handler) | ||
778 | (*pci_irqlist[i].handler)(irq,pci_irqlist[i].dev_id,fp); | ||
779 | } | ||
780 | } | ||
781 | |||
782 | /*****************************************************************************/ | ||
783 | |||
784 | /* | ||
785 | * The shared memory region is broken up into contiguous 512 byte | ||
786 | * regions for easy allocation... This is not an optimal solution | ||
787 | * but it makes allocation and freeing regions really easy. | ||
788 | */ | ||
789 | |||
790 | #define PCI_MEMSLOTSIZE 512 | ||
791 | #define PCI_MEMSLOTS (COMEM_SHMEMSIZE / PCI_MEMSLOTSIZE) | ||
792 | |||
793 | char pci_shmemmap[PCI_MEMSLOTS]; | ||
794 | |||
795 | |||
796 | void *pci_bmalloc(int size) | ||
797 | { | ||
798 | int i, j, nrslots; | ||
799 | |||
800 | #ifdef DEBUGIO | ||
801 | printk(KERN_DEBUG "pci_bmalloc(size=%d)\n", size); | ||
802 | #endif | ||
803 | |||
804 | if (size <= 0) | ||
805 | return((void *) NULL); | ||
806 | |||
807 | nrslots = (size - 1) / PCI_MEMSLOTSIZE; | ||
808 | |||
809 | for (i = 0; (i < (PCI_MEMSLOTS-nrslots)); i++) { | ||
810 | if (pci_shmemmap[i] == 0) { | ||
811 | for (j = i+1; (j < (i+nrslots)); j++) { | ||
812 | if (pci_shmemmap[j]) | ||
813 | goto restart; | ||
814 | } | ||
815 | |||
816 | for (j = i; (j <= i+nrslots); j++) | ||
817 | pci_shmemmap[j] = 1; | ||
818 | break; | ||
819 | } | ||
820 | restart: | ||
821 | } | ||
822 | |||
823 | return((void *) (COMEM_BASE + COMEM_SHMEM + (i * PCI_MEMSLOTSIZE))); | ||
824 | } | ||
825 | |||
826 | /*****************************************************************************/ | ||
827 | |||
828 | void pci_bmfree(void *mp, int size) | ||
829 | { | ||
830 | int i, j, nrslots; | ||
831 | |||
832 | #ifdef DEBUGIO | ||
833 | printk(KERN_DEBUG "pci_bmfree(mp=%x,size=%d)\n", (int) mp, size); | ||
834 | #endif | ||
835 | |||
836 | nrslots = size / PCI_MEMSLOTSIZE; | ||
837 | i = (((unsigned long) mp) - (COMEM_BASE + COMEM_SHMEM)) / | ||
838 | PCI_MEMSLOTSIZE; | ||
839 | |||
840 | for (j = i; (j < (i+nrslots)); j++) | ||
841 | pci_shmemmap[j] = 0; | ||
842 | } | ||
843 | |||
844 | /*****************************************************************************/ | ||
845 | |||
846 | unsigned long pci_virt_to_bus(volatile void *address) | ||
847 | { | ||
848 | unsigned long l; | ||
849 | |||
850 | #ifdef DEBUGIO | ||
851 | printk(KERN_DEBUG "pci_virt_to_bus(address=%x)", (int) address); | ||
852 | #endif | ||
853 | |||
854 | l = ((unsigned long) address) - COMEM_BASE; | ||
855 | #ifdef DEBUGIO | ||
856 | printk(KERN_DEBUG "=%x\n", (int) (l+pci_shmemaddr)); | ||
857 | #endif | ||
858 | return(l + pci_shmemaddr); | ||
859 | } | ||
860 | |||
861 | /*****************************************************************************/ | ||
862 | |||
863 | void *pci_bus_to_virt(unsigned long address) | ||
864 | { | ||
865 | unsigned long l; | ||
866 | |||
867 | #ifdef DEBUGIO | ||
868 | printk(KERN_DEBUG "pci_bus_to_virt(address=%x)", (int) address); | ||
869 | #endif | ||
870 | |||
871 | l = address - pci_shmemaddr; | ||
872 | #ifdef DEBUGIO | ||
873 | printk(KERN_DEBUG "=%x\n", (int) (address + COMEM_BASE)); | ||
874 | #endif | ||
875 | return((void *) (address + COMEM_BASE)); | ||
876 | } | ||
877 | |||
878 | /*****************************************************************************/ | ||
879 | |||
880 | void pci_bmcpyto(void *dst, void *src, int len) | ||
881 | { | ||
882 | unsigned long *dp, *sp, val; | ||
883 | unsigned char *dcp, *scp; | ||
884 | int i, j; | ||
885 | |||
886 | #ifdef DEBUGIO | ||
887 | printk(KERN_DEBUG "pci_bmcpyto(dst=%x,src=%x,len=%d)\n", (int)dst, (int)src, len); | ||
888 | #endif | ||
889 | |||
890 | dp = (unsigned long *) dst; | ||
891 | sp = (unsigned long *) src; | ||
892 | i = len >> 2; | ||
893 | |||
894 | #if 0 | ||
895 | printk(KERN_INFO "DATA:"); | ||
896 | scp = (unsigned char *) sp; | ||
897 | for (i = 0; (i < len); i++) { | ||
898 | if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i); | ||
899 | printk(KERN_INFO "%02x ", *scp++); | ||
900 | } | ||
901 | printk(KERN_INFO "\n"); | ||
902 | #endif | ||
903 | |||
904 | for (j = 0; (i >= 0); i--, j++) { | ||
905 | val = *sp++; | ||
906 | val = (val << 24) | ((val & 0x0000ff00) << 8) | | ||
907 | ((val & 0x00ff0000) >> 8) | (val >> 24); | ||
908 | *dp++ = val; | ||
909 | } | ||
910 | |||
911 | if (len & 0x3) { | ||
912 | dcp = (unsigned char *) dp; | ||
913 | scp = ((unsigned char *) sp) + 3; | ||
914 | for (i = 0; (i < (len & 0x3)); i++) | ||
915 | *dcp++ = *scp--; | ||
916 | } | ||
917 | } | ||
918 | |||
919 | /*****************************************************************************/ | ||
920 | |||
921 | void pci_bmcpyfrom(void *dst, void *src, int len) | ||
922 | { | ||
923 | unsigned long *dp, *sp, val; | ||
924 | unsigned char *dcp, *scp; | ||
925 | int i; | ||
926 | |||
927 | #ifdef DEBUGIO | ||
928 | printk(KERN_DEBUG "pci_bmcpyfrom(dst=%x,src=%x,len=%d)\n",(int)dst,(int)src,len); | ||
929 | #endif | ||
930 | |||
931 | dp = (unsigned long *) dst; | ||
932 | sp = (unsigned long *) src; | ||
933 | i = len >> 2; | ||
934 | |||
935 | for (; (i >= 0); i--) { | ||
936 | val = *sp++; | ||
937 | val = (val << 24) | ((val & 0x0000ff00) << 8) | | ||
938 | ((val & 0x00ff0000) >> 8) | (val >> 24); | ||
939 | *dp++ = val; | ||
940 | } | ||
941 | |||
942 | if (len & 0x3) { | ||
943 | dcp = ((unsigned char *) dp) + 3; | ||
944 | scp = (unsigned char *) sp; | ||
945 | for (i = 0; (i < (len & 0x3)); i++) | ||
946 | *dcp++ = *scp--; | ||
947 | } | ||
948 | |||
949 | #if 0 | ||
950 | printk(KERN_INFO "DATA:"); | ||
951 | dcp = (unsigned char *) dst; | ||
952 | for (i = 0; (i < len); i++) { | ||
953 | if ((i % 16) == 0) printk(KERN_INFO "\n%04x: ", i); | ||
954 | printk(KERN_INFO "%02x ", *dcp++); | ||
955 | } | ||
956 | printk(KERN_INFO "\n"); | ||
957 | #endif | ||
958 | } | ||
959 | |||
960 | /*****************************************************************************/ | ||
961 | |||
962 | void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addr) | ||
963 | { | ||
964 | void *mp; | ||
965 | if ((mp = pci_bmalloc(size)) != NULL) { | ||
966 | dma_addr = mp - (COMEM_BASE + COMEM_SHMEM); | ||
967 | return(mp); | ||
968 | } | ||
969 | *dma_addr = (dma_addr_t) NULL; | ||
970 | return(NULL); | ||
971 | } | ||
972 | |||
973 | /*****************************************************************************/ | ||
974 | |||
975 | void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr) | ||
976 | { | ||
977 | pci_bmfree(cpu_addr, size); | ||
978 | } | ||
979 | |||
980 | /*****************************************************************************/ | ||