4
Copyright (c) Eicon Networks, 2002.
6
This source file is supplied for the use with
7
Eicon Networks range of DIVA Server Adapters.
9
Eicon File Revision : 2.1
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2, or (at your option)
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
18
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
See the GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software
23
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32
/* --------------------------------------------------------------------------
33
Adapter array change notification framework
34
-------------------------------------------------------------------------- */
35
typedef struct _didd_adapter_change_notification {
36
didd_adapter_change_callback_t callback;
37
void IDI_CALL_ENTITY_T * context;
38
} didd_adapter_change_notification_t, \
39
* IDI_CALL_ENTITY_T pdidd_adapter_change_notification_t;
40
#define DIVA_DIDD_MAX_NOTIFICATIONS 256
41
static didd_adapter_change_notification_t\
42
NotificationTable[DIVA_DIDD_MAX_NOTIFICATIONS];
43
/* --------------------------------------------------------------------------
44
Array to held adapter information
45
-------------------------------------------------------------------------- */
46
static DESCRIPTOR HandleTable[NEW_MAX_DESCRIPTORS];
47
static dword Adapters = 0; /* Number of adapters */
48
/* --------------------------------------------------------------------------
50
and 'shadow' debug stuff
51
-------------------------------------------------------------------------- */
52
static void no_printf (unsigned char * format, ...)
56
va_start (ap, format);
62
/* -------------------------------------------------------------------------
63
Portable debug Library
64
------------------------------------------------------------------------- */
67
static DESCRIPTOR MAdapter = {IDI_DIMAINT, /* Adapter Type */
69
0x0000, /* Features */
71
/* --------------------------------------------------------------------------
72
DAdapter. Only IDI clients with buffer, that is huge enough to
73
get all descriptors will receive information about DAdapter
74
{ byte type, byte channels, word features, IDI_CALL request }
75
-------------------------------------------------------------------------- */
76
static void IDI_CALL_LINK_T diva_dadapter_request (ENTITY IDI_CALL_ENTITY_T *);
77
static DESCRIPTOR DAdapter = {IDI_DADAPTER, /* Adapter Type */
79
0x0000, /* Features */
80
diva_dadapter_request };
81
/* --------------------------------------------------------------------------
83
-------------------------------------------------------------------------- */
84
static dword diva_register_adapter_callback (\
85
didd_adapter_change_callback_t callback,
86
void IDI_CALL_ENTITY_T* context);
87
static void diva_remove_adapter_callback (dword handle);
88
static void diva_notify_adapter_change (DESCRIPTOR* d, int removal);
89
static diva_os_spin_lock_t didd_spin;
90
/* --------------------------------------------------------------------------
91
Should be called as first step, after driver init
92
-------------------------------------------------------------------------- */
93
void diva_didd_load_time_init (void) {
94
memset (&HandleTable[0], 0x00, sizeof(HandleTable));
95
memset (&NotificationTable[0], 0x00, sizeof(NotificationTable));
96
diva_os_initialize_spin_lock (&didd_spin, "didd");
98
/* --------------------------------------------------------------------------
99
Should be called as last step, if driver does unload
100
-------------------------------------------------------------------------- */
101
void diva_didd_load_time_finit (void) {
102
diva_os_destroy_spin_lock (&didd_spin, "didd");
104
/* --------------------------------------------------------------------------
105
Called in order to register new adapter in adapter array
106
return adapter handle (> 0) on success
107
return -1 adapter array overflow
108
-------------------------------------------------------------------------- */
109
static int diva_didd_add_descriptor (DESCRIPTOR* d) {
110
diva_os_spin_lock_magic_t irql;
112
if (d->type == IDI_DIMAINT) {
114
MAdapter.request = d->request;
115
dprintf = (DIVA_DI_PRINTF)d->request;
116
diva_notify_adapter_change (&MAdapter, 0); /* Inserted */
117
DBG_TRC (("DIMAINT registered, dprintf=%08x", d->request))
119
DBG_TRC (("DIMAINT removed"))
120
diva_notify_adapter_change (&MAdapter, 1); /* About to remove */
121
MAdapter.request = (IDI_CALL)no_printf;
124
return (NEW_MAX_DESCRIPTORS);
126
for (i = 0; i < NEW_MAX_DESCRIPTORS; i++) {
127
diva_os_enter_spin_lock (&didd_spin, &irql, "didd_add");
128
if (HandleTable[i].type == 0) {
129
memcpy (&HandleTable[i], d, sizeof(*d));
131
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_add");
132
diva_notify_adapter_change (d, 0); /* we have new adapter */
133
DBG_TRC (("Add adapter[%d], request=%08x", (i+1), d->request))
136
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_add");
138
DBG_ERR (("Can't add adapter, out of resources"))
141
/* --------------------------------------------------------------------------
142
Called in order to remove one registered adapter from array
143
return adapter handle (> 0) on success
145
-------------------------------------------------------------------------- */
146
static int diva_didd_remove_descriptor (IDI_CALL request) {
147
diva_os_spin_lock_magic_t irql;
149
if (request == MAdapter.request) {
150
DBG_TRC(("DIMAINT removed"))
152
diva_notify_adapter_change (&MAdapter, 1); /* About to remove */
153
MAdapter.request = (IDI_CALL)no_printf;
156
for (i = 0; (Adapters && (i < NEW_MAX_DESCRIPTORS)); i++) {
157
if (HandleTable[i].request == request) {
158
diva_notify_adapter_change (&HandleTable[i], 1); /* About to remove */
159
diva_os_enter_spin_lock (&didd_spin, &irql, "didd_rm");
160
memset (&HandleTable[i], 0x00, sizeof(HandleTable[0]));
162
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_rm");
163
DBG_TRC (("Remove adapter[%d], request=%08x", (i+1), request))
167
DBG_ERR (("Invalid request=%08x, can't remove adapter", request))
170
/* --------------------------------------------------------------------------
172
return 1 if not enough space to save all available adapters
173
-------------------------------------------------------------------------- */
174
static int diva_didd_read_adapter_array (DESCRIPTOR* buffer, int length) {
175
diva_os_spin_lock_magic_t irql;
177
memset (buffer, 0x00, length);
178
length /= sizeof(DESCRIPTOR);
179
DBG_TRC (("DIDD_Read, space = %d, Adapters = %d", length, Adapters+2))
181
diva_os_enter_spin_lock (&didd_spin, &irql, "didd_read");
182
for (src = 0, dst = 0;
183
(Adapters && (src < NEW_MAX_DESCRIPTORS) && (dst < length));
185
if (HandleTable[src].type) {
186
memcpy (&buffer[dst], &HandleTable[src], sizeof(DESCRIPTOR));
190
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_read");
192
memcpy (&buffer[dst], &MAdapter, sizeof(DESCRIPTOR));
195
DBG_ERR (("Can't write DIMAINT. Array too small"))
198
memcpy (&buffer[dst], &DAdapter, sizeof(DESCRIPTOR));
201
DBG_ERR (("Can't write DADAPTER. Array too small"))
203
DBG_TRC (("Read %d adapters", dst))
204
return (dst == length);
206
/* --------------------------------------------------------------------------
207
DAdapter request function.
208
This function does process only synchronous requests, and is used
209
for reception/registration of new interfaces
210
-------------------------------------------------------------------------- */
211
static void IDI_CALL_LINK_T diva_dadapter_request (\
212
ENTITY IDI_CALL_ENTITY_T *e) {
213
IDI_SYNC_REQ *syncReq = (IDI_SYNC_REQ *)e ;
214
if (e->Req) { /* We do not process it, also return error */
215
e->Rc = OUT_OF_RESOURCES;
216
DBG_ERR (("Can't process async request, Req=%02x", e->Req))
220
So, we process sync request
223
case IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY: {
224
diva_didd_adapter_notify_t* pinfo = &syncReq->didd_notify.info;
225
pinfo->handle = diva_register_adapter_callback (\
226
(didd_adapter_change_callback_t)pinfo->callback,
227
(void IDI_CALL_ENTITY_T *)pinfo->context);
230
case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY: {
231
diva_didd_adapter_notify_t* pinfo = &syncReq->didd_notify.info;
232
diva_remove_adapter_callback (pinfo->handle);
235
case IDI_SYNC_REQ_DIDD_ADD_ADAPTER: {
236
diva_didd_add_adapter_t* pinfo = &syncReq->didd_add_adapter.info;
237
if (diva_didd_add_descriptor ((DESCRIPTOR*)pinfo->descriptor) < 0) {
238
e->Rc = OUT_OF_RESOURCES;
243
case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER: {
244
diva_didd_remove_adapter_t* pinfo = &syncReq->didd_remove_adapter.info;
245
if (diva_didd_remove_descriptor ((IDI_CALL)pinfo->p_request) < 0) {
246
e->Rc = OUT_OF_RESOURCES;
251
case IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY: {
252
diva_didd_read_adapter_array_t* pinfo =\
253
&syncReq->didd_read_adapter_array.info;
254
if (diva_didd_read_adapter_array ((DESCRIPTOR*)pinfo->buffer,
255
(int)pinfo->length)) {
256
e->Rc = OUT_OF_RESOURCES;
262
DBG_ERR (("Can't process sync request, Req=%02x", e->Rc))
263
e->Rc = OUT_OF_RESOURCES;
266
/* --------------------------------------------------------------------------
267
IDI client does register his notification function
268
-------------------------------------------------------------------------- */
269
static dword diva_register_adapter_callback (\
270
didd_adapter_change_callback_t callback,
271
void IDI_CALL_ENTITY_T* context) {
272
diva_os_spin_lock_magic_t irql;
275
for (i = 0; i < DIVA_DIDD_MAX_NOTIFICATIONS; i++) {
276
diva_os_enter_spin_lock (&didd_spin, &irql, "didd_nfy_add");
277
if (!NotificationTable[i].callback) {
278
NotificationTable[i].callback = callback;
279
NotificationTable[i].context = context;
280
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy_add");
281
DBG_TRC(("Register adapter notification[%d]=%08x", i+1, callback))
284
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy_add");
286
DBG_ERR (("Can't register adapter notification, overflow"))
289
/* --------------------------------------------------------------------------
290
IDI client does register his notification function
291
-------------------------------------------------------------------------- */
292
static void diva_remove_adapter_callback (dword handle) {
293
diva_os_spin_lock_magic_t irql;
294
if (handle && ((--handle) < DIVA_DIDD_MAX_NOTIFICATIONS)) {
295
diva_os_enter_spin_lock (&didd_spin, &irql, "didd_nfy_rm");
296
NotificationTable[handle].callback = NULL;
297
NotificationTable[handle].context = NULL;
298
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy_rm");
299
DBG_TRC(("Remove adapter notification[%d]", (int)(handle+1)))
302
DBG_ERR(("Can't remove adapter notification, handle=%d", handle))
304
/* --------------------------------------------------------------------------
305
Notify all client about adapter array change
306
Does suppose following behavior in the client side:
307
Step 1: Redister Notification
308
Step 2: Read Adapter Array
309
-------------------------------------------------------------------------- */
310
static void diva_notify_adapter_change (DESCRIPTOR* d, int removal) {
312
didd_adapter_change_notification_t nfy;
313
diva_os_spin_lock_magic_t irql;
314
for (i = 0; i < DIVA_DIDD_MAX_NOTIFICATIONS; i++) {
316
diva_os_enter_spin_lock (&didd_spin, &irql, "didd_nfy");
317
if (NotificationTable[i].callback) {
318
memcpy (&nfy, &NotificationTable[i], sizeof(nfy));
321
diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy");
323
(*(nfy.callback))(nfy.context, d, removal);
327
/* --------------------------------------------------------------------------
328
For all systems, that are linked by Kernel Mode Linker this is ONLY one
329
function thet should be exported by this device driver
330
IDI clients should look for IDI_DADAPTER, and use request function
331
of this adapter (sync request) in order to receive appropriate services:
333
- remove existing adapter
334
- add adapter array notification
335
- remove adapter array notification
336
(read adapter is redundant in this case)
338
buffer - pointer to buffer that will receive adapter array
339
length - length (in bytes) of space in buffer
341
Adapter array will be written to memory described by 'buffer'
342
If the last adapter seen in the returned adapter array is
343
IDI_DADAPTER or if last adapter in array does have type '0', then
344
it was enougth space in buffer to accommodate all available
346
*NOTE 1 (debug interface):
347
The IDI adapter of type 'IDI_DIMAINT' does register as 'request'
348
famous 'dprintf' function (of type DI_PRINTF, please look
349
include/debuglib.c and include/debuglib.h) for details.
350
So dprintf is not exported from module debug module directly,
351
instead of this IDI_DIMAINT is registered.
352
Module load order will receive in this case:
354
2. DIMAINT does load and register 'IDI_DIMAINT', at this step
355
DIDD should be able to get 'dprintf', save it, and
356
register with DIDD by means of 'dprintf' function.
357
3. any other driver is loaded and is able to access adapter array
359
This approach does allow to load/unload debug interface on demand,
360
and save memory, it it is necessary.
361
-------------------------------------------------------------------------- */
362
void IDI_CALL_LINK_T DIVA_DIDD_Read (void IDI_CALL_ENTITY_T * buffer,
364
diva_didd_read_adapter_array (buffer, length);