PageRenderTime 70ms CodeModel.GetById 13ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/m68knommu/kernel/comempci.c

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