1 /* $Id: divasfunc.c,v 1.23.4.2 2004/08/28 20:03:53 armin Exp $
2  *
3  * Low level driver for Eicon DIVA Server ISDN cards.
4  *
5  * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
6  * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  */
11 
12 #include "platform.h"
13 #include "di_defs.h"
14 #include "pc.h"
15 #include "di.h"
16 #include "io.h"
17 #include "divasync.h"
18 #include "diva.h"
19 #include "xdi_vers.h"
20 
21 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
22 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
23 
24 static int debugmask;
25 
26 extern void DIVA_DIDD_Read(void *, int);
27 
28 extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
29 
30 extern char *DRIVERRELEASE_DIVAS;
31 
32 static dword notify_handle;
33 static DESCRIPTOR DAdapter;
34 static DESCRIPTOR MAdapter;
35 
36 /* --------------------------------------------------------------------------
37    MAINT driver connector section
38    -------------------------------------------------------------------------- */
no_printf(unsigned char * x,...)39 static void no_printf(unsigned char *x, ...)
40 {
41 	/* dummy debug function */
42 }
43 
44 #include "debuglib.c"
45 
46 /*
47  * get the adapters serial number
48  */
diva_get_vserial_number(PISDN_ADAPTER IoAdapter,char * buf)49 void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf)
50 {
51 	int contr = 0;
52 
53 	if ((contr = ((IoAdapter->serialNo & 0xff000000) >> 24))) {
54 		sprintf(buf, "%d-%d",
55 			IoAdapter->serialNo & 0x00ffffff, contr + 1);
56 	} else {
57 		sprintf(buf, "%d", IoAdapter->serialNo);
58 	}
59 }
60 
61 /*
62  * register a new adapter
63  */
diva_xdi_didd_register_adapter(int card)64 void diva_xdi_didd_register_adapter(int card)
65 {
66 	DESCRIPTOR d;
67 	IDI_SYNC_REQ req;
68 
69 	if (card && ((card - 1) < MAX_ADAPTER) &&
70 	    IoAdapters[card - 1] && Requests[card - 1]) {
71 		d.type = IoAdapters[card - 1]->Properties.DescType;
72 		d.request = Requests[card - 1];
73 		d.channels = IoAdapters[card - 1]->Properties.Channels;
74 		d.features = IoAdapters[card - 1]->Properties.Features;
75 		DBG_TRC(("DIDD register A(%d) channels=%d", card,
76 			 d.channels))
77 			/* workaround for different Name in structure */
78 			strlcpy(IoAdapters[card - 1]->Name,
79 				IoAdapters[card - 1]->Properties.Name,
80 				sizeof(IoAdapters[card - 1]->Name));
81 		req.didd_remove_adapter.e.Req = 0;
82 		req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
83 		req.didd_add_adapter.info.descriptor = (void *) &d;
84 		DAdapter.request((ENTITY *)&req);
85 		if (req.didd_add_adapter.e.Rc != 0xff) {
86 			DBG_ERR(("DIDD register A(%d) failed !", card))
87 				}
88 		IoAdapters[card - 1]->os_trap_nfy_Fnc = NULL;
89 	}
90 }
91 
92 /*
93  * remove an adapter
94  */
diva_xdi_didd_remove_adapter(int card)95 void diva_xdi_didd_remove_adapter(int card)
96 {
97 	IDI_SYNC_REQ req;
98 	ADAPTER *a = &IoAdapters[card - 1]->a;
99 
100 	IoAdapters[card - 1]->os_trap_nfy_Fnc = NULL;
101 	DBG_TRC(("DIDD de-register A(%d)", card))
102 		req.didd_remove_adapter.e.Req = 0;
103 	req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
104 	req.didd_remove_adapter.info.p_request =
105 		(IDI_CALL) Requests[card - 1];
106 	DAdapter.request((ENTITY *)&req);
107 	memset(&(a->IdTable), 0x00, 256);
108 }
109 
110 /*
111  * start debug
112  */
start_dbg(void)113 static void start_dbg(void)
114 {
115 	DbgRegister("DIVAS", DRIVERRELEASE_DIVAS, (debugmask) ? debugmask : DBG_DEFAULT);
116 	DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s])",
117 		 DIVA_BUILD, diva_xdi_common_code_build))
118 		}
119 
120 /*
121  * stop debug
122  */
stop_dbg(void)123 static void stop_dbg(void)
124 {
125 	DbgDeregister();
126 	memset(&MAdapter, 0, sizeof(MAdapter));
127 	dprintf = no_printf;
128 }
129 
130 /*
131  * didd callback function
132  */
didd_callback(void * context,DESCRIPTOR * adapter,int removal)133 static void *didd_callback(void *context, DESCRIPTOR *adapter,
134 			   int removal)
135 {
136 	if (adapter->type == IDI_DADAPTER) {
137 		DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
138 		return (NULL);
139 	}
140 
141 	if (adapter->type == IDI_DIMAINT) {
142 		if (removal) {
143 			stop_dbg();
144 		} else {
145 			memcpy(&MAdapter, adapter, sizeof(MAdapter));
146 			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
147 			start_dbg();
148 		}
149 	}
150 	return (NULL);
151 }
152 
153 /*
154  * connect to didd
155  */
connect_didd(void)156 static int __init connect_didd(void)
157 {
158 	int x = 0;
159 	int dadapter = 0;
160 	IDI_SYNC_REQ req;
161 	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
162 
163 	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
164 
165 	for (x = 0; x < MAX_DESCRIPTORS; x++) {
166 		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
167 			dadapter = 1;
168 			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
169 			req.didd_notify.e.Req = 0;
170 			req.didd_notify.e.Rc =
171 				IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
172 			req.didd_notify.info.callback = (void *)didd_callback;
173 			req.didd_notify.info.context = NULL;
174 			DAdapter.request((ENTITY *)&req);
175 			if (req.didd_notify.e.Rc != 0xff) {
176 				stop_dbg();
177 				return (0);
178 			}
179 			notify_handle = req.didd_notify.info.handle;
180 		} else if (DIDD_Table[x].type == IDI_DIMAINT) {	/* MAINT found */
181 			memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
182 			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
183 			start_dbg();
184 		}
185 	}
186 
187 	if (!dadapter) {
188 		stop_dbg();
189 	}
190 
191 	return (dadapter);
192 }
193 
194 /*
195  * disconnect from didd
196  */
disconnect_didd(void)197 static void disconnect_didd(void)
198 {
199 	IDI_SYNC_REQ req;
200 
201 	stop_dbg();
202 
203 	req.didd_notify.e.Req = 0;
204 	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
205 	req.didd_notify.info.handle = notify_handle;
206 	DAdapter.request((ENTITY *)&req);
207 }
208 
209 /*
210  * init
211  */
divasfunc_init(int dbgmask)212 int __init divasfunc_init(int dbgmask)
213 {
214 	char *version;
215 
216 	debugmask = dbgmask;
217 
218 	if (!connect_didd()) {
219 		DBG_ERR(("divasfunc: failed to connect to DIDD."))
220 			return (0);
221 	}
222 
223 	version = diva_xdi_common_code_build;
224 
225 	divasa_xdi_driver_entry();
226 
227 	return (1);
228 }
229 
230 /*
231  * exit
232  */
divasfunc_exit(void)233 void divasfunc_exit(void)
234 {
235 	divasa_xdi_driver_unload();
236 	disconnect_didd();
237 }
238