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#include "platform.h"
26#include "pc.h"
27#include "debuglib.h"
28#include "di_defs.h"
29#include "divasync.h"
30#include "dadapter.h"
31
32
33
34typedef struct _didd_adapter_change_notification {
35 didd_adapter_change_callback_t callback;
36 void IDI_CALL_ENTITY_T *context;
37} didd_adapter_change_notification_t, \
38 * IDI_CALL_ENTITY_T pdidd_adapter_change_notification_t;
39#define DIVA_DIDD_MAX_NOTIFICATIONS 256
40static didd_adapter_change_notification_t \
41NotificationTable[DIVA_DIDD_MAX_NOTIFICATIONS];
42
43
44
45static DESCRIPTOR HandleTable[NEW_MAX_DESCRIPTORS];
46static dword Adapters = 0;
47
48
49
50
51static void no_printf(unsigned char *format, ...)
52{
53#ifdef EBUG
54 va_list ap;
55 va_start(ap, format);
56 debug((format, ap));
57 va_end(ap);
58#endif
59}
60
61
62
63
64#include "debuglib.c"
65
66static DESCRIPTOR MAdapter = {IDI_DIMAINT,
67 0x00,
68 0x0000,
69 (IDI_CALL)no_printf};
70
71
72
73
74
75static void IDI_CALL_LINK_T diva_dadapter_request(ENTITY IDI_CALL_ENTITY_T *);
76static DESCRIPTOR DAdapter = {IDI_DADAPTER,
77 0x00,
78 0x0000,
79 diva_dadapter_request };
80
81
82
83static dword diva_register_adapter_callback(\
84 didd_adapter_change_callback_t callback,
85 void IDI_CALL_ENTITY_T *context);
86static void diva_remove_adapter_callback(dword handle);
87static void diva_notify_adapter_change(DESCRIPTOR *d, int removal);
88static diva_os_spin_lock_t didd_spin;
89
90
91
92void diva_didd_load_time_init(void) {
93 memset(&HandleTable[0], 0x00, sizeof(HandleTable));
94 memset(&NotificationTable[0], 0x00, sizeof(NotificationTable));
95 diva_os_initialize_spin_lock(&didd_spin, "didd");
96}
97
98
99
100void diva_didd_load_time_finit(void) {
101 diva_os_destroy_spin_lock(&didd_spin, "didd");
102}
103
104
105
106
107
108static int diva_didd_add_descriptor(DESCRIPTOR *d) {
109 diva_os_spin_lock_magic_t irql;
110 int i;
111 if (d->type == IDI_DIMAINT) {
112 if (d->request) {
113 MAdapter.request = d->request;
114 dprintf = (DIVA_DI_PRINTF)d->request;
115 diva_notify_adapter_change(&MAdapter, 0);
116 DBG_TRC(("DIMAINT registered, dprintf=%08x", d->request))
117 } else {
118 DBG_TRC(("DIMAINT removed"))
119 diva_notify_adapter_change(&MAdapter, 1);
120 MAdapter.request = (IDI_CALL)no_printf;
121 dprintf = no_printf;
122 }
123 return (NEW_MAX_DESCRIPTORS);
124 }
125 for (i = 0; i < NEW_MAX_DESCRIPTORS; i++) {
126 diva_os_enter_spin_lock(&didd_spin, &irql, "didd_add");
127 if (HandleTable[i].type == 0) {
128 memcpy(&HandleTable[i], d, sizeof(*d));
129 Adapters++;
130 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_add");
131 diva_notify_adapter_change(d, 0);
132 DBG_TRC(("Add adapter[%d], request=%08x", (i + 1), d->request))
133 return (i + 1);
134 }
135 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_add");
136 }
137 DBG_ERR(("Can't add adapter, out of resources"))
138 return (-1);
139}
140
141
142
143
144
145static int diva_didd_remove_descriptor(IDI_CALL request) {
146 diva_os_spin_lock_magic_t irql;
147 int i;
148 if (request == MAdapter.request) {
149 DBG_TRC(("DIMAINT removed"))
150 dprintf = no_printf;
151 diva_notify_adapter_change(&MAdapter, 1);
152 MAdapter.request = (IDI_CALL)no_printf;
153 return (0);
154 }
155 for (i = 0; (Adapters && (i < NEW_MAX_DESCRIPTORS)); i++) {
156 if (HandleTable[i].request == request) {
157 diva_notify_adapter_change(&HandleTable[i], 1);
158 diva_os_enter_spin_lock(&didd_spin, &irql, "didd_rm");
159 memset(&HandleTable[i], 0x00, sizeof(HandleTable[0]));
160 Adapters--;
161 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_rm");
162 DBG_TRC(("Remove adapter[%d], request=%08x", (i + 1), request))
163 return (0);
164 }
165 }
166 DBG_ERR(("Invalid request=%08x, can't remove adapter", request))
167 return (-1);
168}
169
170
171
172
173static int diva_didd_read_adapter_array(DESCRIPTOR *buffer, int length) {
174 diva_os_spin_lock_magic_t irql;
175 int src, dst;
176 memset(buffer, 0x00, length);
177 length /= sizeof(DESCRIPTOR);
178 DBG_TRC(("DIDD_Read, space = %d, Adapters = %d", length, Adapters + 2))
179
180 diva_os_enter_spin_lock(&didd_spin, &irql, "didd_read");
181 for (src = 0, dst = 0;
182 (Adapters && (src < NEW_MAX_DESCRIPTORS) && (dst < length));
183 src++) {
184 if (HandleTable[src].type) {
185 memcpy(&buffer[dst], &HandleTable[src], sizeof(DESCRIPTOR));
186 dst++;
187 }
188 }
189 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_read");
190 if (dst < length) {
191 memcpy(&buffer[dst], &MAdapter, sizeof(DESCRIPTOR));
192 dst++;
193 } else {
194 DBG_ERR(("Can't write DIMAINT. Array too small"))
195 }
196 if (dst < length) {
197 memcpy(&buffer[dst], &DAdapter, sizeof(DESCRIPTOR));
198 dst++;
199 } else {
200 DBG_ERR(("Can't write DADAPTER. Array too small"))
201 }
202 DBG_TRC(("Read %d adapters", dst))
203 return (dst == length);
204}
205
206
207
208
209
210static void IDI_CALL_LINK_T diva_dadapter_request( \
211 ENTITY IDI_CALL_ENTITY_T *e) {
212 IDI_SYNC_REQ *syncReq = (IDI_SYNC_REQ *)e;
213 if (e->Req) {
214 e->Rc = OUT_OF_RESOURCES;
215 DBG_ERR(("Can't process async request, Req=%02x", e->Req))
216 return;
217 }
218
219
220
221 switch (e->Rc) {
222 case IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY: {
223 diva_didd_adapter_notify_t *pinfo = &syncReq->didd_notify.info;
224 pinfo->handle = diva_register_adapter_callback( \
225 (didd_adapter_change_callback_t)pinfo->callback,
226 (void IDI_CALL_ENTITY_T *)pinfo->context);
227 e->Rc = 0xff;
228 } break;
229 case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY: {
230 diva_didd_adapter_notify_t *pinfo = &syncReq->didd_notify.info;
231 diva_remove_adapter_callback(pinfo->handle);
232 e->Rc = 0xff;
233 } break;
234 case IDI_SYNC_REQ_DIDD_ADD_ADAPTER: {
235 diva_didd_add_adapter_t *pinfo = &syncReq->didd_add_adapter.info;
236 if (diva_didd_add_descriptor((DESCRIPTOR *)pinfo->descriptor) < 0) {
237 e->Rc = OUT_OF_RESOURCES;
238 } else {
239 e->Rc = 0xff;
240 }
241 } break;
242 case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER: {
243 diva_didd_remove_adapter_t *pinfo = &syncReq->didd_remove_adapter.info;
244 if (diva_didd_remove_descriptor((IDI_CALL)pinfo->p_request) < 0) {
245 e->Rc = OUT_OF_RESOURCES;
246 } else {
247 e->Rc = 0xff;
248 }
249 } break;
250 case IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY: {
251 diva_didd_read_adapter_array_t *pinfo =\
252 &syncReq->didd_read_adapter_array.info;
253 if (diva_didd_read_adapter_array((DESCRIPTOR *)pinfo->buffer,
254 (int)pinfo->length)) {
255 e->Rc = OUT_OF_RESOURCES;
256 } else {
257 e->Rc = 0xff;
258 }
259 } break;
260 default:
261 DBG_ERR(("Can't process sync request, Req=%02x", e->Rc))
262 e->Rc = OUT_OF_RESOURCES;
263 }
264}
265
266
267
268static dword diva_register_adapter_callback( \
269 didd_adapter_change_callback_t callback,
270 void IDI_CALL_ENTITY_T *context) {
271 diva_os_spin_lock_magic_t irql;
272 dword i;
273
274 for (i = 0; i < DIVA_DIDD_MAX_NOTIFICATIONS; i++) {
275 diva_os_enter_spin_lock(&didd_spin, &irql, "didd_nfy_add");
276 if (!NotificationTable[i].callback) {
277 NotificationTable[i].callback = callback;
278 NotificationTable[i].context = context;
279 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_nfy_add");
280 DBG_TRC(("Register adapter notification[%d]=%08x", i + 1, callback))
281 return (i + 1);
282 }
283 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_nfy_add");
284 }
285 DBG_ERR(("Can't register adapter notification, overflow"))
286 return (0);
287}
288
289
290
291static void diva_remove_adapter_callback(dword handle) {
292 diva_os_spin_lock_magic_t irql;
293 if (handle && ((--handle) < DIVA_DIDD_MAX_NOTIFICATIONS)) {
294 diva_os_enter_spin_lock(&didd_spin, &irql, "didd_nfy_rm");
295 NotificationTable[handle].callback = NULL;
296 NotificationTable[handle].context = NULL;
297 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_nfy_rm");
298 DBG_TRC(("Remove adapter notification[%d]", (int)(handle + 1)))
299 return;
300 }
301 DBG_ERR(("Can't remove adapter notification, handle=%d", handle))
302 }
303
304
305
306
307
308
309static void diva_notify_adapter_change(DESCRIPTOR *d, int removal) {
310 int i, do_notify;
311 didd_adapter_change_notification_t nfy;
312 diva_os_spin_lock_magic_t irql;
313 for (i = 0; i < DIVA_DIDD_MAX_NOTIFICATIONS; i++) {
314 do_notify = 0;
315 diva_os_enter_spin_lock(&didd_spin, &irql, "didd_nfy");
316 if (NotificationTable[i].callback) {
317 memcpy(&nfy, &NotificationTable[i], sizeof(nfy));
318 do_notify = 1;
319 }
320 diva_os_leave_spin_lock(&didd_spin, &irql, "didd_nfy");
321 if (do_notify) {
322 (*(nfy.callback))(nfy.context, d, removal);
323 }
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
361void IDI_CALL_LINK_T DIVA_DIDD_Read(void IDI_CALL_ENTITY_T *buffer,
362 int length) {
363 diva_didd_read_adapter_array(buffer, length);
364}
365