1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "platform.h"
27#include "pc.h"
28#include "debuglib.h"
29#include "di_defs.h"
30#include "divasync.h"
31#include "dadapter.h"
32
33
34
35typedef 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
41static didd_adapter_change_notification_t\
42 NotificationTable[DIVA_DIDD_MAX_NOTIFICATIONS];
43
44
45
46static DESCRIPTOR HandleTable[NEW_MAX_DESCRIPTORS];
47static dword Adapters = 0;
48
49
50
51
52static void no_printf (unsigned char * format, ...)
53{
54#ifdef EBUG
55 va_list ap;
56 va_start (ap, format);
57 debug((format, ap));
58 va_end (ap);
59#endif
60}
61
62
63
64
65#include "debuglib.c"
66
67static DESCRIPTOR MAdapter = {IDI_DIMAINT,
68 0x00,
69 0x0000,
70 (IDI_CALL)no_printf};
71
72
73
74
75
76static void IDI_CALL_LINK_T diva_dadapter_request (ENTITY IDI_CALL_ENTITY_T *);
77static DESCRIPTOR DAdapter = {IDI_DADAPTER,
78 0x00,
79 0x0000,
80 diva_dadapter_request };
81
82
83
84static dword diva_register_adapter_callback (\
85 didd_adapter_change_callback_t callback,
86 void IDI_CALL_ENTITY_T* context);
87static void diva_remove_adapter_callback (dword handle);
88static void diva_notify_adapter_change (DESCRIPTOR* d, int removal);
89static diva_os_spin_lock_t didd_spin;
90
91
92
93void 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");
97}
98
99
100
101void diva_didd_load_time_finit (void) {
102 diva_os_destroy_spin_lock (&didd_spin, "didd");
103}
104
105
106
107
108
109static int diva_didd_add_descriptor (DESCRIPTOR* d) {
110 diva_os_spin_lock_magic_t irql;
111 int i;
112 if (d->type == IDI_DIMAINT) {
113 if (d->request) {
114 MAdapter.request = d->request;
115 dprintf = (DIVA_DI_PRINTF)d->request;
116 diva_notify_adapter_change (&MAdapter, 0);
117 DBG_TRC (("DIMAINT registered, dprintf=%08x", d->request))
118 } else {
119 DBG_TRC (("DIMAINT removed"))
120 diva_notify_adapter_change (&MAdapter, 1);
121 MAdapter.request = (IDI_CALL)no_printf;
122 dprintf = no_printf;
123 }
124 return (NEW_MAX_DESCRIPTORS);
125 }
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));
130 Adapters++;
131 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_add");
132 diva_notify_adapter_change (d, 0);
133 DBG_TRC (("Add adapter[%d], request=%08x", (i+1), d->request))
134 return (i+1);
135 }
136 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_add");
137 }
138 DBG_ERR (("Can't add adapter, out of resources"))
139 return (-1);
140}
141
142
143
144
145
146static int diva_didd_remove_descriptor (IDI_CALL request) {
147 diva_os_spin_lock_magic_t irql;
148 int i;
149 if (request == MAdapter.request) {
150 DBG_TRC(("DIMAINT removed"))
151 dprintf = no_printf;
152 diva_notify_adapter_change (&MAdapter, 1);
153 MAdapter.request = (IDI_CALL)no_printf;
154 return (0);
155 }
156 for (i = 0; (Adapters && (i < NEW_MAX_DESCRIPTORS)); i++) {
157 if (HandleTable[i].request == request) {
158 diva_notify_adapter_change (&HandleTable[i], 1);
159 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_rm");
160 memset (&HandleTable[i], 0x00, sizeof(HandleTable[0]));
161 Adapters--;
162 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_rm");
163 DBG_TRC (("Remove adapter[%d], request=%08x", (i+1), request))
164 return (0);
165 }
166 }
167 DBG_ERR (("Invalid request=%08x, can't remove adapter", request))
168 return (-1);
169}
170
171
172
173
174static int diva_didd_read_adapter_array (DESCRIPTOR* buffer, int length) {
175 diva_os_spin_lock_magic_t irql;
176 int src, dst;
177 memset (buffer, 0x00, length);
178 length /= sizeof(DESCRIPTOR);
179 DBG_TRC (("DIDD_Read, space = %d, Adapters = %d", length, Adapters+2))
180
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));
184 src++) {
185 if (HandleTable[src].type) {
186 memcpy (&buffer[dst], &HandleTable[src], sizeof(DESCRIPTOR));
187 dst++;
188 }
189 }
190 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_read");
191 if (dst < length) {
192 memcpy (&buffer[dst], &MAdapter, sizeof(DESCRIPTOR));
193 dst++;
194 } else {
195 DBG_ERR (("Can't write DIMAINT. Array too small"))
196 }
197 if (dst < length) {
198 memcpy (&buffer[dst], &DAdapter, sizeof(DESCRIPTOR));
199 dst++;
200 } else {
201 DBG_ERR (("Can't write DADAPTER. Array too small"))
202 }
203 DBG_TRC (("Read %d adapters", dst))
204 return (dst == length);
205}
206
207
208
209
210
211static 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) {
215 e->Rc = OUT_OF_RESOURCES;
216 DBG_ERR (("Can't process async request, Req=%02x", e->Req))
217 return;
218 }
219
220
221
222 switch (e->Rc) {
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);
228 e->Rc = 0xff;
229 } break;
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);
233 e->Rc = 0xff;
234 } break;
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;
239 } else {
240 e->Rc = 0xff;
241 }
242 } break;
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;
247 } else {
248 e->Rc = 0xff;
249 }
250 } break;
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;
257 } else {
258 e->Rc = 0xff;
259 }
260 } break;
261 default:
262 DBG_ERR (("Can't process sync request, Req=%02x", e->Rc))
263 e->Rc = OUT_OF_RESOURCES;
264 }
265}
266
267
268
269static 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;
273 dword i;
274
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))
282 return (i+1);
283 }
284 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy_add");
285 }
286 DBG_ERR (("Can't register adapter notification, overflow"))
287 return (0);
288}
289
290
291
292static 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)))
300 return;
301 }
302 DBG_ERR(("Can't remove adapter notification, handle=%d", handle))
303}
304
305
306
307
308
309
310static void diva_notify_adapter_change (DESCRIPTOR* d, int removal) {
311 int i, do_notify;
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++) {
315 do_notify = 0;
316 diva_os_enter_spin_lock (&didd_spin, &irql, "didd_nfy");
317 if (NotificationTable[i].callback) {
318 memcpy (&nfy, &NotificationTable[i], sizeof(nfy));
319 do_notify = 1;
320 }
321 diva_os_leave_spin_lock (&didd_spin, &irql, "didd_nfy");
322 if (do_notify) {
323 (*(nfy.callback))(nfy.context, d, removal);
324 }
325 }
326}
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362void IDI_CALL_LINK_T DIVA_DIDD_Read (void IDI_CALL_ENTITY_T * buffer,
363 int length) {
364 diva_didd_read_adapter_array (buffer, length);
365}
366
367