File: /usr/src/linux/drivers/isdn/eicon/linio.c

1     
2     /*
3      *
4      * Copyright (C) Eicon Technology Corporation, 2000.
5      *
6      * Eicon File Revision :    1.16  
7      *
8      * This program is free software; you can redistribute it and/or modify
9      * it under the terms of the GNU General Public License as published by
10      * the Free Software Foundation; either version 2, or (at your option)
11      * any later version.
12      *
13      * This program is distributed in the hope that it will be useful,
14      * but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY 
15      * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
16      * See the GNU General Public License for more details.
17      *
18      * You should have received a copy of the GNU General Public License
19      * along with this program; if not, write to the Free Software
20      * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21      *
22      */
23     
24     
25     #define N_DATA
26     
27     #include <asm/io.h>
28     #include <asm/system.h>
29     #include <linux/slab.h>
30     #include <linux/pci.h>
31     #include <linux/delay.h>
32     #undef N_DATA
33     
34     #include "uxio.h"
35     
36     static
37     int log_on=0;
38     
39     int		Divasdevflag = 0;
40     
41     //spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
42     
43     static
44     ux_diva_card_t card_pool[MAX_CARDS];
45     
46     void UxPause(long int ms)
47     {
48     	int timeout = jiffies + ((ms * HZ) / 1000);
49     
50     	while (time_before(jiffies, timeout));
51     }
52     
53     int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
54     {
55     	int 		i;
56     	ux_diva_card_t	*c;
57     
58     	if (cfg->bus_type != DIA_BUS_TYPE_PCI)
59     	{
60     		DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
61     		return -1;
62     	}
63     
64     	for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
65     	{
66     		;
67     	}
68     
69     	if (i == DIM(card_pool))
70     	{
71     		DPRINTF(("divas hw: card_pool exhausted"));
72     		return -1;
73     	}
74     
75     	c = *card = &card_pool[i];
76     
77     	switch (cfg->bus_type)
78     	{
79     	case DIA_BUS_TYPE_PCI:
80     		c->bus_num = cfg->bus_num;
81     		c->func_num = cfg->func_num;
82     		c->io_base = cfg->io_base;
83     		c->reset_base = cfg->reset_base;
84     		c->card_type    = cfg->card_type;
85     		c->mapped = NULL;
86     		c->slot 	= cfg->slot;
87     		c->irq 		= (int) cfg->irq;
88     		c->pDRAM    	= cfg->memory[DIVAS_RAM_MEMORY];
89     		c->pDEVICES 	= cfg->memory[DIVAS_REG_MEMORY];
90     		c->pCONFIG  	= cfg->memory[DIVAS_CFG_MEMORY];
91     		c->pSHARED  	= cfg->memory[DIVAS_SHARED_MEMORY];
92     		c->pCONTROL  	= cfg->memory[DIVAS_CTL_MEMORY];
93     
94     	/*		c->bus_type 	= DIA_BUS_TYPE_PCI;
95     		c->bus_num 	= cfg->bus_num & 0x3f;
96     		c->slot 	= cfg->slot;
97     		c->irq 		= (int) cfg->irq;
98     		c->int_priority = (int) cfg->int_priority;
99     		c->card_type    = cfg->card_type;
100     		c->io_base      = cfg->io_base;
101     		c->reset_base   = cfg->reset_base;
102     		c->pDRAM    	= cfg->memory[DIVAS_RAM_MEMORY];
103     		c->pDEVICES 	= cfg->memory[DIVAS_REG_MEMORY];
104     		c->pCONFIG  	= cfg->memory[DIVAS_CFG_MEMORY];
105     		c->pSHARED  	= cfg->memory[DIVAS_SHARED_MEMORY];
106     		DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
107     		DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
108     		DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
109     		c->cm_key		= cm_getbrdkey("Divas", cfg->card_id);*/
110     		break;
111     	default:
112     		break;
113     	}
114     
115     	c->in_use = TRUE;
116     
117     	return 0;
118     }
119     
120     void UxCardHandleFree(ux_diva_card_t *card)
121     {
122     	card->in_use = FALSE;
123     }
124     
125     
126     #define PLX_IOBASE 0
127     #define DIVAS_IOBASE 1
128     void *UxCardMemAttach(ux_diva_card_t *card, int id)
129     {
130     	if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
131     	{
132     		switch (id)
133     		{
134     		case DIVAS_SHARED_MEMORY:
135     			card->mapped = card->pSHARED;
136     			return card->pSHARED;
137     			break;
138     		case DIVAS_RAM_MEMORY:
139     			card->mapped = card->pDRAM;
140     			return card->pDRAM;
141     			break;
142     		case DIVAS_REG_MEMORY:
143     			card->mapped = card->pDEVICES;
144     			return card->pDEVICES;
145     			break;
146     		case DIVAS_CFG_MEMORY:
147     			card->mapped = card->pCONFIG;
148     			return card->pCONFIG;
149     			break;
150     		default:
151     			ASSERT(FALSE);
152     			card->mapped = NULL;
153     			return (void *) 0;
154     		}
155     	}
156     	else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
157     	{
158     		switch (id)
159     		{
160     		case PLX_IOBASE:
161     			return (void *) card->reset_base;
162     			break;
163     		case DIVAS_IOBASE:
164     			return (void *) card->io_base;
165     			break;
166     		default:
167     			ASSERT(FALSE);
168     			return 0;
169     		}
170     	}
171     	
172     	else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
173     	{
174     		switch (id)
175     		{
176     		case DIVAS_SHARED_MEMORY:
177     			card->mapped = card->pSHARED;
178     			return card->pSHARED;
179     			break;
180     		case DIVAS_RAM_MEMORY:
181     			card->mapped = card->pDRAM;
182     			return card->pDRAM;
183     			break;
184     		case DIVAS_REG_MEMORY:
185     			card->mapped = (void *) card->io_base;
186     			return (void *) card->io_base;
187     			break;
188     		case DIVAS_CTL_MEMORY:
189     			card->mapped = card->pCONTROL;
190     			return card->pCONTROL;
191     			break;
192     		default:
193     			// ASSERT(FALSE);
194     			DPRINTF(("divas: Trying to attach to mem %d", id));
195     			card->mapped = NULL;
196     			return (void *) 0;
197     		}
198     	} else
199     		DPRINTF(("divas: Tried to attach to unknown card"));
200     
201     	/* Unknown card type */
202     	return NULL;
203     }
204     
205     void UxCardMemDetach(ux_diva_card_t *card, void *address)
206     {
207     	return; // Just a place holder. No un-mapping done.
208     }
209     
210     void UxCardLog(int turn_on)
211     {
212     	log_on = turn_on;
213     }
214     
215     /*
216      * Control Register I/O Routines to be performed on Attached I/O ports
217      */
218     
219     void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
220     {
221     	word base = (word) (dword) AttachedBase;
222     
223     	base += offset;
224     
225     	outb(the_byte, base);
226     }
227     
228     void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
229     {
230     	word base = (word) (dword) AttachedBase;
231     
232     	base += offset;
233     
234     	outw(the_word, base);
235     }
236     
237     void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
238     {
239     	word base = (word) (dword) AttachedBase;
240     
241     	base += offset;
242     
243     	outl(the_dword, base);
244     }
245     
246     byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
247     {
248     	word base = (word) (dword) AttachedBase;
249     
250     	base += offset;
251     
252     	return inb(base);
253     }
254     
255     word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
256     {
257     	word base = (word) (dword) AttachedBase;
258     
259     	base += offset;
260     
261     	return inw(base);
262     }
263     
264     /*
265      * Memory mapped card I/O functions
266      */
267     
268     byte UxCardMemIn(ux_diva_card_t *card, void *address)
269     {
270     	byte	b;
271     	volatile byte* t = (byte*)address;
272     
273     	b = *t;
274     
275     	if (log_on)
276     	{
277     		byte *a = address;
278     		a -= (int) card->mapped;
279     		DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
280         	}
281     
282         return(b); 
283     }
284     
285     word UxCardMemInW(ux_diva_card_t *card, void *address)
286     {
287     	word	w;
288     	volatile word* t = (word*)address;
289     
290         w = *t;
291     
292     	if (log_on)
293         {
294     		byte *a = address;
295     		a -= (int) card->mapped;
296     		DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
297         }
298     
299         return (w);
300     }
301     
302     dword UxCardMemInD(ux_diva_card_t *card, void *address)
303     {
304     	dword	dw;
305     	volatile dword* t = (dword*)address;
306     
307         dw = *t;
308     
309     	if (log_on)
310         {
311     		byte *a = address;
312     		a -= (int) card->mapped;
313     		DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
314         }
315     
316         return (dw);
317     }
318     
319     void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
320     {
321     	volatile byte *pSource = address;
322     	byte *pDest = buffer;
323     
324     	while (length--)
325     	{
326     		*pDest++ = *pSource++;
327     	}
328     
329     	if (log_on)
330         {
331     		byte *a = address;
332     		a -= (int) card->mapped;
333     		pDest = buffer;
334     		DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)", 
335     		pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
336     		pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
337     		a));
338         }
339     
340         return;
341     }
342     
343     void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
344     {
345     	volatile byte* t = (byte*)address;
346     
347     	if (log_on)
348     	{
349     		byte *a = address;
350     		a -= (int) card->mapped;
351     		DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
352     	}
353     
354     	*t = data;
355     
356         	return;
357     }
358     
359     void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
360     {
361     	volatile word* t = (word*)address;
362     
363     	if (log_on)
364     	{
365     		byte *a = address;
366     		a -= (int) card->mapped;
367     		DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
368     	}
369     
370     	*t = data;
371         return;
372     }
373     
374     void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
375     {
376     	volatile dword* t = (dword*)address;
377     
378     	if (log_on)
379     	{
380     		byte *a = address;
381     		a -= (int) card->mapped;
382     		DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
383     	}
384     
385     	*t = data;
386         return;
387     }
388     
389     void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
390     {
391     	byte 	*pSource = buffer;
392     	byte	*pDest = address;
393     
394     	while (length--)
395     	{
396     		*pDest++ = *pSource++;
397     	}
398     
399     	if (log_on)
400         {
401     		byte *a = address;
402     		a -= (int) card->mapped;
403     		pDest = buffer;
404     		DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)", 
405     		pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
406     		pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
407     		a));
408         }
409     
410         return;
411     }
412     
413     /*
414      * Memory mapped card I/O functions
415      */
416     
417     byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
418     
419     {
420     	byte the_byte;
421     
422         outb(0xFF, card->io_base + 0xC);
423     	outw((word) (dword) address, card->io_base + 4);
424     
425     	the_byte = inb(card->io_base);
426     
427     	if (log_on)
428         {
429     		DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)", 
430     					the_byte & 0xff, address));
431         }
432         
433     	return the_byte;
434     }
435     
436     word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
437     
438     {
439     	word the_word;
440     
441     	outb(0xFF, card->io_base + 0xC);
442     	outw((word) (dword) address, card->io_base + 4);
443     	the_word = inw(card->io_base);
444     
445     	if (log_on)
446         {
447     		DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)", 
448     					the_word & 0xffff, address));
449         }
450     
451     	return the_word;
452     }
453     
454     dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
455     
456     {
457     	dword the_dword;
458     
459     	outb(0xFF, card->io_base + 0xC);
460     	outw((word) (dword) address, card->io_base + 4);
461     	the_dword = inl(card->io_base);
462     
463     	if (log_on)
464         {
465     		DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)", 
466     					the_dword, address));
467         }
468     
469         return the_dword;
470     }
471     
472     void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
473     
474     {
475     	byte *pSource = address;
476     	byte *pDest = buffer;
477     
478     	if ((word) (dword) address & 0x1)
479     	{
480     		outb(0xFF, card->io_base + 0xC);
481     		outw((word) (dword) pSource, card->io_base + 4);
482     		*pDest = (byte) inb(card->io_base);
483     		pDest++;
484     		pSource++;
485     		length--;
486     		if (!length)
487             {
488                 return;
489             }
490         }
491     
492     	outb(0xFF, card->io_base + 0xC);
493     	outw((word) (dword) pSource, card->io_base + 4);
494     	insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
495     
496     	if (log_on)
497         {
498     		pDest = buffer;
499     		DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)", 
500     		pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
501     		pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
502     		address));
503         }
504     
505         return;
506     }
507     
508     /* Output */
509     
510     void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
511     {
512     	if (log_on)
513         {
514     		DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)", 
515     					data & 0xff, address));
516         }
517     
518     	outb(0xFF, card->io_base + 0xC);
519     	outw((word) (dword) address, card->io_base + 4);
520     	outb((byte) data & 0xFF, card->io_base);
521     
522         return;
523     }
524     
525     void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
526     {
527     	if (log_on)
528         {
529     		DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)", 
530     					data & 0xffff, address));
531         }
532     
533     	outb(0xFF, card->io_base + 0xC);
534     	outw((word) (dword) address, card->io_base + 4);
535     	outw((word) data & 0xFFFF, card->io_base);
536     
537         return;
538     }
539     
540     void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
541     {
542     	if (log_on)
543         {
544     		DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
545         }
546     
547     	outb(0xFF, card->io_base + 0xC);
548     	outw((word) (dword) address, card->io_base + 4);
549     	outl((dword) data & 0xFFFFFFFF, card->io_base);
550     
551         return;
552     }
553     
554     void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
555     
556     {
557     	byte 	*pSource = buffer;
558     	byte	*pDest = address;
559     
560     	if ((word) (dword) address & 1)
561     	{
562     		outb(0xFF, card->io_base + 0xC);
563     		outw((word) (dword) pDest, card->io_base + 4);
564     		outb(*pSource, card->io_base);
565     		pSource++;
566     		pDest++;
567     		length--;
568     		if (!length)
569             {
570     			return;
571             }
572     	}
573     
574         outb(0xFF, card->io_base + 0xC);
575     	outw((word) (dword) pDest, card->io_base + 4);
576     	outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
577     
578     	if (log_on)
579         {
580     		pDest = buffer;
581     		DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)", 
582     		pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
583     		pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
584     		address));
585         }
586     
587         return;
588     }
589     
590     void 	Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
591     {
592     	int i;
593     	card_t *card = NULL;
594     	ux_diva_card_t *ux_ref = NULL;
595     
596     	for (i = 0; i < DivasCardNext; i++)
597     	{
598     
599     		if (arg == DivasCards[i].cfg.irq)
600     		{
601     			card = &DivasCards[i];
602     			ux_ref = card->hw;
603     	
604     			if ((ux_ref) && (card->is_live))
605     			{
606     				(*ux_ref->user_isr)(ux_ref->user_isr_arg);	
607     			}
608     			else 
609     			{
610     				DPRINTF(("divas: ISR couldn't locate card"));
611     			}
612     		}
613     	}
614     
615     	return;
616     }
617     
618     
619     int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
620     {
621     	int result;
622     
623             card->user_isr = isr_fn;
624             card->user_isr_arg = isr_arg;
625     
626     	result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
627     
628     	return result;
629     }
630     
631     void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
632     {
633     	free_irq(card->irq, card->user_isr_arg);
634     }
635     
636     void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
637     {
638     	switch (size)
639     	{
640     	case sizeof(byte):
641     		pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
642     		break;
643     	case sizeof(word):
644     		pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
645     		break;
646     	case sizeof(dword):
647     		pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
648     		break;
649     	default:
650     		printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
651     	}
652     }
653     
654     void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
655     {
656     	switch (size)
657     	{
658     	case sizeof(byte):
659     		pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
660     		break;
661     	case sizeof(word):
662     		pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
663     		break;
664     	case sizeof(dword):
665     		pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
666     		break;
667     	default:
668     		printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
669     	}
670     }
671     
672     void *UxAlloc(unsigned int size)
673     {
674     	void *m;
675     
676     	m = kmalloc(size, GFP_ATOMIC);
677     
678     	return m;
679     }
680     
681     void UxFree(void *ptr)
682     {
683     	kfree(ptr);
684     }
685     
686     long UxCardLock(ux_diva_card_t *card)
687     {
688     	unsigned long flags;
689     
690      	//spin_lock_irqsave(&diva_lock, flags);
691     	
692     	save_flags(flags);
693     	cli();
694     	return flags;
695     	
696     }
697     
698     void UxCardUnlock(ux_diva_card_t *card, long ipl)
699     {
700     	//spin_unlock_irqrestore(&diva_lock, ipl);
701     
702     	restore_flags(ipl);
703     
704     }
705     
706     dword UxTimeGet(void)
707     {
708     	return jiffies;
709     }
710     
711     long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
712     {
713     	register volatile long *p;
714     	register long ret;
715     	int ipl;
716     
717     	p =dst;
718     	
719     	ipl = UxCardLock(card);
720     
721     	*p += 1;
722     	ret = *p;
723     
724     	UxCardUnlock(card,ipl);
725     
726     	return(ret);
727     
728     }
729     
730     long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
731     {
732     	register volatile long *p;
733     	register long ret;
734     	int ipl;
735     
736     	p =dst;
737     	
738     	ipl = UxCardLock(card);
739     
740     	*p -= 1;
741     	ret = *p;
742     
743     	UxCardUnlock(card,ipl);
744     
745     	return(ret);
746     
747     }
748