ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / isdn / hardware / eicon / divasfunc.c
1 /* $Id: divasfunc.c,v 1.23 2004/04/08 01:17:57 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 #define MAX_DESCRIPTORS  32
31
32 extern char *DRIVERRELEASE_DIVAS;
33
34 static dword notify_handle;
35 static DESCRIPTOR DAdapter;
36 static DESCRIPTOR MAdapter;
37
38 /* --------------------------------------------------------------------------
39     MAINT driver connector section
40    -------------------------------------------------------------------------- */
41 static void no_printf(unsigned char *x, ...)
42 {
43         /* dummy debug function */
44 }
45
46 #include "debuglib.c"
47
48 /*
49  * get the adapters serial number
50  */
51 void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf)
52 {
53         int contr = 0;
54
55         if ((contr = ((IoAdapter->serialNo & 0xff000000) >> 24))) {
56                 sprintf(buf, "%d-%d",
57                         IoAdapter->serialNo & 0x00ffffff, contr + 1);
58         } else {
59                 sprintf(buf, "%d", IoAdapter->serialNo);
60         }
61 }
62
63 /*
64  * register a new adapter
65  */
66 void diva_xdi_didd_register_adapter(int card)
67 {
68         DESCRIPTOR d;
69         IDI_SYNC_REQ req;
70
71         if (card && ((card - 1) < MAX_ADAPTER) &&
72             IoAdapters[card - 1] && Requests[card - 1]) {
73                 d.type = IoAdapters[card - 1]->Properties.DescType;
74                 d.request = Requests[card - 1];
75                 d.channels = IoAdapters[card - 1]->Properties.Channels;
76                 d.features = IoAdapters[card - 1]->Properties.Features;
77                 DBG_TRC(("DIDD register A(%d) channels=%d", card,
78                          d.channels))
79                 /* workaround for different Name in structure */
80                 strlcpy(IoAdapters[card - 1]->Name,
81                         IoAdapters[card - 1]->Properties.Name,
82                         sizeof(IoAdapters[card - 1]->Name));
83                 req.didd_remove_adapter.e.Req = 0;
84                 req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
85                 req.didd_add_adapter.info.descriptor = (void *) &d;
86                 DAdapter.request((ENTITY *) & req);
87                 if (req.didd_add_adapter.e.Rc != 0xff) {
88                         DBG_ERR(("DIDD register A(%d) failed !", card))
89                 }
90                 IoAdapters[card - 1]->os_trap_nfy_Fnc = NULL;
91         }
92 }
93
94 /*
95  * remove an adapter
96  */
97 void diva_xdi_didd_remove_adapter(int card)
98 {
99         IDI_SYNC_REQ req;
100         ADAPTER *a = &IoAdapters[card - 1]->a;
101
102         IoAdapters[card - 1]->os_trap_nfy_Fnc = NULL;
103         DBG_TRC(("DIDD de-register A(%d)", card))
104         req.didd_remove_adapter.e.Req = 0;
105         req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
106         req.didd_remove_adapter.info.p_request =
107             (IDI_CALL) Requests[card - 1];
108         DAdapter.request((ENTITY *) & req);
109         memset(&(a->IdTable), 0x00, 256);
110 }
111
112 /*
113  * start debug
114  */
115 static void start_dbg(void)
116 {
117         DbgRegister("DIVAS", DRIVERRELEASE_DIVAS, (debugmask) ? debugmask : DBG_DEFAULT);
118         DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s]-%s-%s)",
119                  DIVA_BUILD, diva_xdi_common_code_build, __DATE__,
120                  __TIME__))
121 }
122
123 /*
124  * stop debug
125  */
126 static void stop_dbg(void)
127 {
128         DbgDeregister();
129         memset(&MAdapter, 0, sizeof(MAdapter));
130         dprintf = no_printf;
131 }
132
133 /*
134  * didd callback function
135  */
136 static void *didd_callback(void *context, DESCRIPTOR * adapter,
137                            int removal)
138 {
139         if (adapter->type == IDI_DADAPTER) {
140                 DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
141                 return (NULL);
142         }
143
144         if (adapter->type == IDI_DIMAINT) {
145                 if (removal) {
146                         stop_dbg();
147                 } else {
148                         memcpy(&MAdapter, adapter, sizeof(MAdapter));
149                         dprintf = (DIVA_DI_PRINTF) MAdapter.request;
150                         start_dbg();
151                 }
152         }
153         return (NULL);
154 }
155
156 /*
157  * connect to didd
158  */
159 static int DIVA_INIT_FUNCTION connect_didd(void)
160 {
161         int x = 0;
162         int dadapter = 0;
163         IDI_SYNC_REQ req;
164         DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
165
166         DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
167
168         for (x = 0; x < MAX_DESCRIPTORS; x++) {
169                 if (DIDD_Table[x].type == IDI_DADAPTER) {       /* DADAPTER found */
170                         dadapter = 1;
171                         memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
172                         req.didd_notify.e.Req = 0;
173                         req.didd_notify.e.Rc =
174                             IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
175                         req.didd_notify.info.callback = (void *)didd_callback;
176                         req.didd_notify.info.context = 0;
177                         DAdapter.request((ENTITY *) & req);
178                         if (req.didd_notify.e.Rc != 0xff) {
179                                 stop_dbg();
180                                 return (0);
181                         }
182                         notify_handle = req.didd_notify.info.handle;
183                 } else if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */
184                         memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
185                         dprintf = (DIVA_DI_PRINTF) MAdapter.request;
186                         start_dbg();
187                 }
188         }
189
190         if (!dadapter) {
191                 stop_dbg();
192         }
193
194         return (dadapter);
195 }
196
197 /*
198  * disconnect from didd
199  */
200 static void DIVA_EXIT_FUNCTION disconnect_didd(void)
201 {
202         IDI_SYNC_REQ req;
203
204         stop_dbg();
205
206         req.didd_notify.e.Req = 0;
207         req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
208         req.didd_notify.info.handle = notify_handle;
209         DAdapter.request((ENTITY *) & req);
210 }
211
212 /*
213  * init
214  */
215 int DIVA_INIT_FUNCTION divasfunc_init(int dbgmask)
216 {
217         char *version;
218
219         debugmask = dbgmask;
220         
221         if (!connect_didd()) {
222                 DBG_ERR(("divasfunc: failed to connect to DIDD."))
223                 return (0);
224         }
225
226         version = diva_xdi_common_code_build;
227
228         divasa_xdi_driver_entry();
229
230         return (1);
231 }
232
233 /*
234  * exit
235  */
236 void DIVA_EXIT_FUNCTION divasfunc_exit(void)
237 {
238         divasa_xdi_driver_unload();
239         disconnect_didd();
240 }