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

1     
2     /*
3      *
4      * Copyright (C) Eicon Technology Corporation, 2000.
5      *
6      * Eicon File Revision :    1.15  
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     #include "eicon.h"
26     #include "sys.h"
27     #include "idi.h"
28     #include "constant.h"
29     #include "divas.h"
30     #include "pc.h"
31     #include "pr_pc.h"
32     
33     #include "uxio.h"
34     
35     #define DIVAS_LOAD_CMD		0x02
36     #define DIVAS_START_CMD		0x03
37     #define DIVAS_IRQ_RESET		0xC18
38     #define DIVAS_IRQ_RESET_VAL	0xFE
39     
40     #define TEST_INT_DIVAS		0x11
41     #define TEST_INT_DIVAS_BRI	0x12
42     #define TEST_INT_DIVAS_Q	0x13
43     
44     #define DIVAS_RESET	0x81
45     #define DIVAS_LED1	0x04
46     #define DIVAS_LED2	0x08
47     #define DIVAS_LED3	0x20
48     #define DIVAS_LED4	0x40
49     
50     #define DIVAS_SIGNATURE 0x4447
51     
52     #define MP_PROTOCOL_ADDR 0xA0011000
53     
54     #define PLX_IOBASE	0
55     #define	DIVAS_IOBASE	1
56     
57     typedef struct {
58     		dword cmd;
59     		dword addr;
60     		dword len;
61     		dword err;
62     		dword live;
63     		dword reserved[(0x1020>>2)-6];
64     		dword signature;
65     		byte  data[1];
66     } diva_server_boot_t;
67     
68     int		DivasCardNext;
69     card_t	DivasCards[MAX_CARDS];
70     
71     dia_config_t *DivasConfig(card_t *, dia_config_t *);
72     
73     static
74     DESCRIPTOR DIDD_Table[32];
75     
76     void    DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength )
77     {
78             memset(table, 0, tablelength);
79     
80             if (tablelength > sizeof(DIDD_Table))
81               tablelength = sizeof(DIDD_Table);
82     
83             if(tablelength % sizeof(DESCRIPTOR)) {
84               tablelength /= sizeof(DESCRIPTOR);
85               tablelength *= sizeof(DESCRIPTOR);
86             }
87     
88             if (tablelength > 0)
89               memcpy((void *)table, (void *)DIDD_Table, tablelength);
90     
91     	return;
92     }
93     
94     void 	DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength)
95     {
96             if (tablelength > sizeof(DIDD_Table))
97               tablelength = sizeof(DIDD_Table);
98     
99     	memcpy((void *)DIDD_Table, (void *)table, tablelength);
100     
101     	return;
102     }
103     
104     static
105     void    init_idi_tab(void)
106     {
107         DESCRIPTOR d[32];
108     
109         memset(d, 0, sizeof(d));
110     
111         d[0].type = IDI_DIMAINT;  /* identify the DIMAINT entry */
112         d[0].channels = 0; /* zero channels associated with dimaint*/
113         d[0].features = 0; /* no features associated with dimaint */
114         d[0].request = (IDI_CALL) DivasPrintf;
115         
116         DIVA_DIDD_Write(d, sizeof(d));
117     
118         return;
119     }
120     
121     /*
122      * I/O routines for memory mapped cards
123      */
124     
125     byte mem_in(ADAPTER *a, void *adr)
126     {
127     	card_t			*card = a->io;
128     	unsigned char	*b, *m;
129     	byte			value;
130     
131     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
132     
133     	m += (unsigned int) adr;
134     
135     	value = UxCardMemIn(card->hw, m);
136     
137     	UxCardMemDetach(card->hw, b);
138     
139     	return value;
140     }
141     
142     word mem_inw(ADAPTER *a, void *adr)
143     {
144     	card_t			*card = a->io;
145     	unsigned char	*b, *m;
146     	word			value;
147     
148     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
149     
150     	m += (unsigned int) adr;
151     
152     	value = UxCardMemInW(card->hw, m);
153     
154     	UxCardMemDetach(card->hw, b);
155     
156     	return value;
157     }
158     
159     void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length)
160     {
161     	card_t			*card = a->io;
162     	unsigned char	*b, *m;
163     
164     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
165     
166     	m += (unsigned int) adr;
167     
168     	UxCardMemInBuffer(card->hw, m, P, length);
169     
170     	UxCardMemDetach(card->hw, b);
171     
172     	return;
173     }
174     
175     void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
176     {
177     	card_t			*card = a->io;
178     	unsigned char	*b, *m;
179     
180     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
181     
182     	m += (dword) &RBuffer->length;
183     	card->RBuffer.length = UxCardMemInW(card->hw, m);
184     
185     	m = b;
186     	m += (dword) &RBuffer->P;
187     	UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
188     
189     	e->RBuffer = (DBUFFER *) &card->RBuffer;
190     
191     	UxCardMemDetach(card->hw, b);
192     
193     	return;
194     }
195     
196     void mem_out(ADAPTER *a, void *adr, byte data)
197     {
198     	card_t			*card = a->io;
199     	unsigned char	*b, *m;
200     
201     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
202     
203     	m += (unsigned int) adr;
204     
205     	UxCardMemOut(card->hw, m, data);
206     
207     	UxCardMemDetach(card->hw, b);
208     
209     	return;
210     }
211     
212     void mem_outw(ADAPTER *a, void *adr, word data)
213     {
214     	card_t			*card = a->io;
215     	unsigned char	*b, *m;
216     
217     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
218     
219     	m += (unsigned int) adr;
220     
221     	UxCardMemOutW(card->hw, m, data);
222     
223     	UxCardMemDetach(card->hw, b);
224     
225     	return;
226     }
227     
228     void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length)
229     {
230     	card_t			*card = a->io;
231     	unsigned char	*b, *m;
232     
233     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
234     
235     	m += (unsigned int) adr;
236     
237     	UxCardMemOutBuffer(card->hw, m, P, length);
238     
239     	UxCardMemDetach(card->hw, b);
240     
241     	return;
242     }
243     
244     void mem_inc(ADAPTER *a, void *adr)
245     {
246     	word			value;
247     	card_t			*card = a->io;
248     	unsigned char	*b, *m;
249     
250     	m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
251     
252     	m += (unsigned int) adr;
253     
254     	value = UxCardMemInW(card->hw, m);
255     	value++;
256     	UxCardMemOutW(card->hw, m, value);
257     
258     	UxCardMemDetach(card->hw, b);
259     
260     	return;
261     }
262     
263     /*
264      * I/O routines for I/O mapped cards
265      */
266     
267     byte io_in(ADAPTER *a, void *adr)
268     {
269     	card_t		    *card = a->io;
270     	byte		    value;
271     	byte	*DivasIOBase = NULL;
272     
273     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
274     
275     	value = UxCardIoIn(card->hw, DivasIOBase, adr);
276     
277     	UxCardMemDetach(card->hw, DivasIOBase);
278     
279         return value;
280     }
281     
282     word io_inw(ADAPTER *a, void *adr)
283     {
284     	card_t		*card = a->io;
285     	word		value;
286     	byte	*DivasIOBase = NULL;
287     
288     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
289     
290     	value = UxCardIoInW(card->hw, DivasIOBase, adr);
291     
292     	UxCardMemDetach(card->hw, DivasIOBase);
293     
294     	return value;
295     }
296     
297     void io_in_buffer(ADAPTER *a, void *adr, void *P, word length)
298     {
299     	card_t *card = a->io;
300     	byte *DivasIOBase = NULL;
301     
302     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
303     
304     	UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
305     
306     	UxCardMemDetach(card->hw, DivasIOBase);
307     
308         return;
309     }
310     
311     void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
312     {
313     	card_t *card = a->io;
314     	byte *DivasIOBase = NULL;
315     
316     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
317     
318     	card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
319     
320     	UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
321     
322     	UxCardMemDetach(card->hw, DivasIOBase);
323     
324     	e->RBuffer = (DBUFFER *) &card->RBuffer;
325     
326         return;
327     }
328     
329     void io_out(ADAPTER *a, void *adr, byte data)
330     {
331     	card_t		*card = a->io;
332     	byte	*DivasIOBase = NULL;
333     
334     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
335     
336     	UxCardIoOut(card->hw, DivasIOBase, adr, data);
337     
338     	UxCardMemDetach(card->hw, DivasIOBase);
339     
340         return;
341     }
342     
343     void io_outw(ADAPTER *a, void *adr, word data)
344     {
345     	card_t		*card = a->io;
346     	byte	*DivasIOBase = NULL;
347     
348     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
349     
350     	UxCardIoOutW(card->hw, DivasIOBase, adr, data);
351     
352     	UxCardMemDetach(card->hw, DivasIOBase);
353     
354         return;
355     }
356     
357     void io_out_buffer(ADAPTER *a, void *adr, void *P, word length)
358     {
359     	card_t		*card = a->io;
360     	byte *DivasIOBase = NULL;
361     
362     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
363     
364     	UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
365     
366     	UxCardMemDetach(card->hw, DivasIOBase);
367     
368         return;
369     }
370     
371     void io_inc(ADAPTER *a, void *adr)
372     {
373     	word		value;
374     	card_t		*card = a->io;
375     	byte *DivasIOBase;
376     
377     	DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
378     
379     	value = UxCardIoInW(card->hw, DivasIOBase, adr);
380     	
381     	value++;
382     
383     	UxCardIoOutW(card->hw, DivasIOBase, adr, value);
384     
385     	UxCardMemDetach(card->hw, DivasIOBase);
386     
387         return;
388     }
389     
390     static
391     void test_int(card_t *card)
392     
393     {
394     	byte *shared, *DivasIOBase;
395     
396     	switch (card->test_int_pend)
397     	{
398     		case TEST_INT_DIVAS:
399     			DPRINTF(("divas: test interrupt pending"));
400     			shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
401     
402     			if (UxCardMemIn(card->hw, &shared[0x3FE]))
403     			{
404     				UxCardMemOut(card->hw, 
405     								&(((struct pr_ram *)shared)->RcOutput), 0);
406     				UxCardMemDetach(card->hw, shared);
407                 	(*card->reset_int)(card);
408     				shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
409     				UxCardMemOut(card->hw, &shared[0x3FE], 0);
410     				DPRINTF(("divas: test interrupt cleared"));
411     			}
412     
413     			UxCardMemDetach(card->hw, shared);
414     
415     			card->test_int_pend = 0;
416     			break;
417     
418     		case TEST_INT_DIVAS_BRI:
419     			DPRINTF(("divas: BRI test interrupt pending"));
420     			(*card->reset_int)(card);
421     			DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
422     			UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0);
423     			UxCardMemDetach(card->hw, DivasIOBase);
424     			DPRINTF(("divas: test interrupt cleared"));
425     			card->test_int_pend = 0;
426     			break;
427     
428     		case TEST_INT_DIVAS_Q:
429     			DPRINTF(("divas: 4BRI test interrupt pending"));
430     			(*card->reset_int)(card);
431     			card->test_int_pend = 0;
432     			break;
433     
434     		default:
435     			DPRINTF(("divas: unknown test interrupt pending"));
436     			return;
437     	}
438     	return;
439     }
440     
441     void card_isr (void *dev_id)
442     {
443     	card_t *card = (card_t *) dev_id;
444     	ADAPTER *a = &card->a;
445     	int ipl;
446     
447     	if (card->test_int_pend)
448     	{
449     		ipl = UxCardLock(card->hw);
450     		card->int_pend=0;
451     		test_int(card);
452     		UxCardUnlock(card->hw,ipl);
453     		return;
454     	}
455     	
456     	if(card->card_isr)
457     	{
458     		(*(card->card_isr))(card);
459     	}
460     	else
461     	{
462     		ipl = UxCardLock(card->hw);
463     	
464     		if ((card->test_int)(a))
465     		{
466     			(card->reset_int)(card);
467     		}
468     		
469     		UxCardUnlock(card->hw,ipl);
470     		
471     	}
472     
473     }
474     
475     int DivasCardNew(dia_card_t *card_info)
476     {
477     	card_t *card;
478     	static boolean_t first_call = TRUE;
479     	boolean_t NeedISRandReset = FALSE;
480     
481     	DPRINTF(("divas: new card "));
482     
483     	if (first_call)
484     	{
485     		first_call = FALSE;
486     		init_idi_tab();
487     	}
488     
489     	DivasConfigGet(card_info);
490     	
491     	if (DivasCardNext == DIM(DivasCards))
492     	{
493     		KDPRINTF((KERN_WARNING "Divas: no space available for new card"));
494     		return -1;
495     	}
496     
497     	card = &DivasCards[DivasCardNext];
498     
499     	card->state = DIA_UNKNOWN;
500     
501     	card->cfg = *card_info;
502     
503     	card->a.io = card;
504     
505     	if (UxCardHandleGet(&card->hw, card_info))
506     	{
507     		KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card"));
508     		return -1;
509     	}
510     
511     	if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
512     	{
513     		DivasBriPatch(card);
514     		card_info->io_base = card->cfg.io_base;
515     	}
516     
517     	switch (card_info->card_type)
518     	{
519     		case DIA_CARD_TYPE_DIVA_SERVER:
520     			if (DivasPriInit(card, card_info))
521     			{
522     				return -1;
523     			}
524     			NeedISRandReset = TRUE;
525     			break;
526     
527     		case DIA_CARD_TYPE_DIVA_SERVER_B:
528     			if (DivasBriInit(card, card_info))
529     			{
530     				return -1;
531     			}
532     			NeedISRandReset = TRUE;
533     			break;
534     
535      		case DIA_CARD_TYPE_DIVA_SERVER_Q:
536     			if (Divas4BriInit(card, card_info))
537     			{
538     				return -1;
539     			}
540     
541     			if (card_info->name[6] == '0')
542     			{
543     				NeedISRandReset = TRUE;
544     			}
545     			else // Need to set paramater for ISR anyway
546     			{
547     				card->hw->user_isr_arg = card;
548     				card->hw->user_isr = card_isr;
549     			}
550     			break;   
551     
552     		default:
553     			KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type));
554     			return -1;
555     	}
556     
557     	if (NeedISRandReset)
558     	{
559     		if (UxIsrInstall(card->hw, card_isr, card))
560     		{
561     			KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq));
562     			UxCardHandleFree(card->hw);
563     			return -1;
564     		}
565     
566     		if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
567     		{
568     			if ((*card->card_reset)(card))
569     			{
570     				KDPRINTF((KERN_WARNING "Divas: Adapter reset failed"));
571     				return -1;
572     			}
573     			card->state = DIA_RESET;
574     		}
575     
576     		NeedISRandReset = FALSE;
577     	}
578     
579     	DivasCardNext++;
580     
581     	return 0;
582     }
583     
584     void	*get_card(int card_id)
585     {
586     	int i;
587     
588     	for (i=0; i < DivasCardNext; i++)
589     	{
590     		if (DivasCards[i].cfg.card_id == card_id)
591     		{
592     			return(&DivasCards[i]);
593     		}
594     	}
595     
596     	DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
597     
598     	return NULL;
599     }
600     
601     int DivasCardConfig(dia_config_t *config)
602     {
603     	card_t *card;
604     	int status;
605     
606     	DPRINTF(("divas: configuring card"));
607     
608     	card = get_card(config->card_id);
609     	if (!card)
610     	{
611     		return -1;
612     	}
613     
614     	config = DivasConfig(card, config);
615     
616     	status = (*card->card_config)(card, config);
617     
618     	if (!status)
619     	{
620     		card->state = DIA_CONFIGURED;
621     	}
622     	return status;
623     }
624     
625     int DivasCardLoad(dia_load_t *load)
626     {
627     	card_t *card;
628     	int	status;
629     
630     	card = get_card(load->card_id);
631     	if (!card)
632     	{
633     		return -1;
634     	}
635     
636     	if (card->state == DIA_RUNNING)
637     	{
638     		(*card->card_reset)(card);
639     	}
640     
641     	status = (*card->card_load)(card, load);
642     	if (!status)
643     	{
644     		card->state = DIA_LOADED;
645     	}
646     	return status;
647     }
648     
649     static int idi_register(card_t *card, byte channels)
650     {
651         DESCRIPTOR d[32];
652         int length, num_entities;
653     
654     	DPRINTF(("divas: registering card with IDI"));
655     
656     	num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES;
657     	card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
658     
659     	if (!card->e_tbl)
660     	{
661     		KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available"));
662     		return -1;
663     	}
664     
665     	memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities);
666     	card->e_max = num_entities;
667     
668         DIVA_DIDD_Read(d, sizeof(d));
669     
670             for(length=0; length < DIM(d); length++)
671               if (d[length].type == 0) break;
672     
673     	if (length >= DIM(d))
674     	{
675     		KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
676     		return -1;
677     	}
678     
679     	switch (card->cfg.card_type)
680     	{
681     		case DIA_CARD_TYPE_DIVA_SERVER:
682     		d[length].type = IDI_ADAPTER_PR;
683     		/* d[length].serial = card->serial_no; */
684     		break;
685     
686     		case DIA_CARD_TYPE_DIVA_SERVER_B:
687     		d[length].type = IDI_ADAPTER_MAESTRA;
688     		/* d[length].serial = card->serial_no; */
689     		break;
690     
691     		// 4BRI is treated as 4 BRI adapters
692     		case DIA_CARD_TYPE_DIVA_SERVER_Q:
693     		d[length].type = IDI_ADAPTER_MAESTRA;
694     		/* d[length].serial = card->cfg.serial; */
695     	}
696     
697     	d[length].features = 0;
698     	d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
699     
700     	if ( card->hw->features & PROTCAP_MANIF )
701     	{
702     		d[length].features |= DI_MANAGE ;
703     	}
704     	if ( card->hw->features & PROTCAP_V_42 )
705     	{
706     		d[length].features |= DI_V_42 ;
707     	}
708     	if ( card->hw->features & PROTCAP_EXTD_FAX )
709     	{
710     		d[length].features |= DI_EXTD_FAX ;
711     	}
712     
713     	d[length].channels = channels;
714     	d[length].request = DivasIdiRequest[card - DivasCards];
715     
716     	length++;
717     
718     	DIVA_DIDD_Write(d, sizeof(d));
719     
720         return 0;
721     }
722     
723     int DivasCardStart(int card_id)
724     {
725     	card_t *card;
726     	byte channels;
727     	int status;
728     
729     	DPRINTF(("divas: starting card"));
730     
731     	card = get_card(card_id);
732     	if (!card)
733     	{
734     		return -1;
735     	}
736     
737     	status = (*card->card_start)(card, &channels);
738     	if (status)
739     	{
740     		return status;
741     	}
742     
743     	/* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
744     	if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
745     	{
746     		int i;
747     		card_t *FourBRISlave;
748     
749     		for (i=3; i >= 0; i--)
750     		{
751     			FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */
752     			if (FourBRISlave)
753     			{
754     				idi_register(FourBRISlave, 2);
755     				FourBRISlave->state = DIA_RUNNING;
756     			}
757     		}
758     		card->serial_no = card->cfg.serial;
759     
760     		DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels", 
761     				card_id - 3, card->serial_no, (int) channels));
762     	}
763     	else
764     	{
765     		status = idi_register(card, channels);
766     		if (!status)
767     		{
768     			card->state = DIA_RUNNING;
769     			DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels", 
770     						card_id, card->serial_no, (int) channels));
771     		}
772     	}
773     
774     	return status;
775     }
776     
777     int DivasGetMem(mem_block_t *mem_block)
778     {
779     	card_t *card;
780     	word	card_id = mem_block->card_id;
781     
782     	card = get_card(card_id);
783     	if (!card)
784     	{
785     		return 0;
786     	}
787     
788     	return (*card->card_mem_get)(card, mem_block);
789     }
790     
791     
792     /*
793      * Deleyed Procedure Call for handling interrupts from card
794      */
795     
796     void	DivaDoCardDpc(card_t *card)
797     {
798     	ADAPTER	*a;
799     
800     	a = &card->a;
801     
802     	if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1)
803     	{
804     		return;
805     	}
806     
807     	do{
808     		if((*(card->test_int))(a))
809     		{
810     			(*(card->dpc))(a);
811     			(*(card->clear_int))(a);
812     		}
813     			(*(card->out))(a);
814     	}while(UxInterlockedDecrement(card->hw, &card->dpc_reentered));
815     			
816     }
817     
818     void	DivasDoDpc(void *pData)
819     {
820     	card_t	*card = DivasCards;
821     	int 	i = DivasCardNext;
822     	
823     	while(i--)
824     	{
825     		DivaDoCardDpc(card++);
826     	}
827     }
828     
829     void	DivasDoRequestDpc(void *pData)
830     {
831     	DivasDoDpc(pData);
832     }
833     
834     /*
835      * DivasGetNum
836      * Returns the number of active adapters
837      */
838     
839     int DivasGetNum(void)
840     {
841     	return(DivasCardNext);
842     }
843     
844     /*
845      * DivasGetList
846      * Returns a list of active adapters
847      */
848     int DivasGetList(dia_card_list_t *card_list)
849     {
850     	int i;
851     
852     	memset(card_list, 0, sizeof(dia_card_list_t));
853     
854     	for(i = 0; i < DivasCardNext; i++)
855     	{
856     		card_list->card_type = DivasCards[i].cfg.card_type;
857     		card_list->card_slot = DivasCards[i].cfg.slot;
858     		card_list->state     = DivasCards[i].state;
859     		card_list++;
860     	}
861     
862     	return 0;
863     
864     }
865     
866     /*
867      * control logging for specified card
868      */
869     
870     void	DivasLog(dia_log_t *log)
871     {
872     	card_t *card;
873     
874     	card = get_card(log->card_id);
875     	if (!card)
876     	{
877     		return;
878     	}
879     
880     	card->log_types = log->log_types;
881     
882     	return;
883     }
884     
885