diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hardware/eicon/os_bri.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hardware/eicon/os_bri.c')
-rw-r--r-- | drivers/isdn/hardware/eicon/os_bri.c | 813 |
1 files changed, 813 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c new file mode 100644 index 000000000000..4cc44a5dd1db --- /dev/null +++ b/drivers/isdn/hardware/eicon/os_bri.c | |||
@@ -0,0 +1,813 @@ | |||
1 | /* $Id: os_bri.c,v 1.21 2004/03/21 17:26:01 armin Exp $ */ | ||
2 | |||
3 | #include "platform.h" | ||
4 | #include "debuglib.h" | ||
5 | #include "cardtype.h" | ||
6 | #include "pc.h" | ||
7 | #include "pr_pc.h" | ||
8 | #include "di_defs.h" | ||
9 | #include "dsp_defs.h" | ||
10 | #include "di.h" | ||
11 | #include "io.h" | ||
12 | |||
13 | #include "xdi_msg.h" | ||
14 | #include "xdi_adapter.h" | ||
15 | #include "os_bri.h" | ||
16 | #include "diva_pci.h" | ||
17 | #include "mi_pc.h" | ||
18 | #include "pc_maint.h" | ||
19 | |||
20 | /* | ||
21 | ** IMPORTS | ||
22 | */ | ||
23 | extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter); | ||
24 | extern void diva_xdi_display_adapter_features(int card); | ||
25 | extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a); | ||
26 | |||
27 | /* | ||
28 | ** LOCALS | ||
29 | */ | ||
30 | static int bri_bar_length[3] = { | ||
31 | 0x80, | ||
32 | 0x80, | ||
33 | 0x20 | ||
34 | }; | ||
35 | static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a); | ||
36 | static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a); | ||
37 | static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | ||
38 | diva_xdi_um_cfg_cmd_t * cmd, int length); | ||
39 | static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a); | ||
40 | static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter); | ||
41 | static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter, | ||
42 | dword address, | ||
43 | const byte * data, dword length); | ||
44 | static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, | ||
45 | dword start_address, dword features); | ||
46 | static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a); | ||
47 | |||
48 | static void diva_bri_set_addresses(diva_os_xdi_adapter_t * a) | ||
49 | { | ||
50 | a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0; | ||
51 | a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 1; | ||
52 | a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2; | ||
53 | a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 1; | ||
54 | a->resources.pci.mem_type_id[MEM_TYPE_PORT] = 2; | ||
55 | a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 2; | ||
56 | |||
57 | a->xdi_adapter.ram = a->resources.pci.addr[0]; | ||
58 | a->xdi_adapter.cfg = a->resources.pci.addr[1]; | ||
59 | a->xdi_adapter.Address = a->resources.pci.addr[2]; | ||
60 | |||
61 | a->xdi_adapter.reset = a->xdi_adapter.cfg; | ||
62 | a->xdi_adapter.port = a->xdi_adapter.Address; | ||
63 | |||
64 | a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET; | ||
65 | |||
66 | a->xdi_adapter.reset += 0x4C; /* PLX 9050 !! */ | ||
67 | } | ||
68 | |||
69 | /* | ||
70 | ** BAR0 - MEM Addr - 0x80 - NOT USED | ||
71 | ** BAR1 - I/O Addr - 0x80 | ||
72 | ** BAR2 - I/O Addr - 0x20 | ||
73 | */ | ||
74 | int diva_bri_init_card(diva_os_xdi_adapter_t * a) | ||
75 | { | ||
76 | int bar; | ||
77 | dword bar2 = 0, bar2_length = 0xffffffff; | ||
78 | word cmd = 0, cmd_org; | ||
79 | byte Bus, Slot; | ||
80 | void *hdev; | ||
81 | byte __iomem *p; | ||
82 | |||
83 | /* | ||
84 | Set properties | ||
85 | */ | ||
86 | a->xdi_adapter.Properties = CardProperties[a->CardOrdinal]; | ||
87 | DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name)) | ||
88 | |||
89 | /* | ||
90 | Get resources | ||
91 | */ | ||
92 | for (bar = 0; bar < 3; bar++) { | ||
93 | a->resources.pci.bar[bar] = | ||
94 | divasa_get_pci_bar(a->resources.pci.bus, | ||
95 | a->resources.pci.func, bar, | ||
96 | a->resources.pci.hdev); | ||
97 | if (!a->resources.pci.bar[bar]) { | ||
98 | DBG_ERR(("A: can't get BAR[%d]", bar)) | ||
99 | return (-1); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | a->resources.pci.irq = | ||
104 | (byte) divasa_get_pci_irq(a->resources.pci.bus, | ||
105 | a->resources.pci.func, | ||
106 | a->resources.pci.hdev); | ||
107 | if (!a->resources.pci.irq) { | ||
108 | DBG_ERR(("A: invalid irq")); | ||
109 | return (-1); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | Get length of I/O bar 2 - it is different by older | ||
114 | EEPROM version | ||
115 | */ | ||
116 | Bus = a->resources.pci.bus; | ||
117 | Slot = a->resources.pci.func; | ||
118 | hdev = a->resources.pci.hdev; | ||
119 | |||
120 | /* | ||
121 | Get plain original values of the BAR2 CDM registers | ||
122 | */ | ||
123 | PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev); | ||
124 | PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev); | ||
125 | /* | ||
126 | Disable device and get BAR2 length | ||
127 | */ | ||
128 | PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev); | ||
129 | PCIwrite(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev); | ||
130 | PCIread(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev); | ||
131 | /* | ||
132 | Restore BAR2 and CMD registers | ||
133 | */ | ||
134 | PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev); | ||
135 | PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev); | ||
136 | |||
137 | /* | ||
138 | Calculate BAR2 length | ||
139 | */ | ||
140 | bar2_length = (~(bar2_length & ~7)) + 1; | ||
141 | DBG_LOG(("BAR[2] length=%lx", bar2_length)) | ||
142 | |||
143 | /* | ||
144 | Map and register resources | ||
145 | */ | ||
146 | if (!(a->resources.pci.addr[0] = | ||
147 | divasa_remap_pci_bar(a, 0, a->resources.pci.bar[0], | ||
148 | bri_bar_length[0]))) { | ||
149 | DBG_ERR(("A: BRI, can't map BAR[0]")) | ||
150 | diva_bri_cleanup_adapter(a); | ||
151 | return (-1); | ||
152 | } | ||
153 | |||
154 | sprintf(&a->port_name[0], "BRI %02x:%02x", | ||
155 | a->resources.pci.bus, a->resources.pci.func); | ||
156 | |||
157 | if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1], | ||
158 | bri_bar_length[1], &a->port_name[0], 1)) { | ||
159 | DBG_ERR(("A: BRI, can't register BAR[1]")) | ||
160 | diva_bri_cleanup_adapter(a); | ||
161 | return (-1); | ||
162 | } | ||
163 | a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1]; | ||
164 | a->resources.pci.length[1] = bri_bar_length[1]; | ||
165 | |||
166 | if (diva_os_register_io_port(a, 1, a->resources.pci.bar[2], | ||
167 | bar2_length, &a->port_name[0], 2)) { | ||
168 | DBG_ERR(("A: BRI, can't register BAR[2]")) | ||
169 | diva_bri_cleanup_adapter(a); | ||
170 | return (-1); | ||
171 | } | ||
172 | a->resources.pci.addr[2] = (void *) (unsigned long) a->resources.pci.bar[2]; | ||
173 | a->resources.pci.length[2] = bar2_length; | ||
174 | |||
175 | /* | ||
176 | Set all memory areas | ||
177 | */ | ||
178 | diva_bri_set_addresses(a); | ||
179 | |||
180 | /* | ||
181 | Get Serial Number | ||
182 | */ | ||
183 | a->xdi_adapter.serialNo = diva_bri_get_serial_number(a); | ||
184 | |||
185 | /* | ||
186 | Register I/O ports with correct name now | ||
187 | */ | ||
188 | if (diva_bri_reregister_io(a)) { | ||
189 | diva_bri_cleanup_adapter(a); | ||
190 | return (-1); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | Initialize OS dependent objects | ||
195 | */ | ||
196 | if (diva_os_initialize_spin_lock | ||
197 | (&a->xdi_adapter.isr_spin_lock, "isr")) { | ||
198 | diva_bri_cleanup_adapter(a); | ||
199 | return (-1); | ||
200 | } | ||
201 | if (diva_os_initialize_spin_lock | ||
202 | (&a->xdi_adapter.data_spin_lock, "data")) { | ||
203 | diva_bri_cleanup_adapter(a); | ||
204 | return (-1); | ||
205 | } | ||
206 | |||
207 | strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasbrid"); | ||
208 | |||
209 | if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr, | ||
210 | DIDpcRoutine, &a->xdi_adapter)) { | ||
211 | diva_bri_cleanup_adapter(a); | ||
212 | return (-1); | ||
213 | } | ||
214 | /* | ||
215 | Do not initialize second DPC - only one thread will be created | ||
216 | */ | ||
217 | a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object; | ||
218 | |||
219 | /* | ||
220 | Create entity table | ||
221 | */ | ||
222 | a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels; | ||
223 | a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info; | ||
224 | a->xdi_adapter.e_tbl = diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO)); | ||
225 | if (!a->xdi_adapter.e_tbl) { | ||
226 | diva_bri_cleanup_adapter(a); | ||
227 | return (-1); | ||
228 | } | ||
229 | memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO)); | ||
230 | |||
231 | /* | ||
232 | Set up interface | ||
233 | */ | ||
234 | a->xdi_adapter.a.io = &a->xdi_adapter; | ||
235 | a->xdi_adapter.DIRequest = request; | ||
236 | a->interface.cleanup_adapter_proc = diva_bri_cleanup_adapter; | ||
237 | a->interface.cmd_proc = diva_bri_cmd_card_proc; | ||
238 | |||
239 | p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); | ||
240 | outpp(p, 0x41); | ||
241 | DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); | ||
242 | |||
243 | prepare_maestra_functions(&a->xdi_adapter); | ||
244 | |||
245 | a->dsp_mask = 0x00000003; | ||
246 | |||
247 | /* | ||
248 | Set IRQ handler | ||
249 | */ | ||
250 | a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq; | ||
251 | sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA BRI %ld", | ||
252 | (long) a->xdi_adapter.serialNo); | ||
253 | if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr, | ||
254 | a->xdi_adapter.irq_info.irq_name)) { | ||
255 | diva_bri_cleanup_adapter(a); | ||
256 | return (-1); | ||
257 | } | ||
258 | a->xdi_adapter.irq_info.registered = 1; | ||
259 | |||
260 | diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name, | ||
261 | a->resources.pci.irq, a->xdi_adapter.serialNo); | ||
262 | |||
263 | return (0); | ||
264 | } | ||
265 | |||
266 | |||
267 | static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a) | ||
268 | { | ||
269 | int i; | ||
270 | |||
271 | if (a->xdi_adapter.Initialized) { | ||
272 | diva_bri_stop_adapter(a); | ||
273 | } | ||
274 | |||
275 | /* | ||
276 | Remove ISR Handler | ||
277 | */ | ||
278 | if (a->xdi_adapter.irq_info.registered) { | ||
279 | diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr); | ||
280 | } | ||
281 | a->xdi_adapter.irq_info.registered = 0; | ||
282 | |||
283 | if (a->resources.pci.addr[0] && a->resources.pci.bar[0]) { | ||
284 | divasa_unmap_pci_bar(a->resources.pci.addr[0]); | ||
285 | a->resources.pci.addr[0] = NULL; | ||
286 | a->resources.pci.bar[0] = 0; | ||
287 | } | ||
288 | |||
289 | for (i = 1; i < 3; i++) { | ||
290 | if (a->resources.pci.addr[i] && a->resources.pci.bar[i]) { | ||
291 | diva_os_register_io_port(a, 0, | ||
292 | a->resources.pci.bar[i], | ||
293 | a->resources.pci. | ||
294 | length[i], | ||
295 | &a->port_name[0], i); | ||
296 | a->resources.pci.addr[i] = NULL; | ||
297 | a->resources.pci.bar[i] = 0; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | Free OS objects | ||
303 | */ | ||
304 | diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr); | ||
305 | diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr); | ||
306 | |||
307 | diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr); | ||
308 | a->xdi_adapter.isr_soft_isr.object = NULL; | ||
309 | |||
310 | diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm"); | ||
311 | diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm"); | ||
312 | |||
313 | /* | ||
314 | Free memory | ||
315 | */ | ||
316 | if (a->xdi_adapter.e_tbl) { | ||
317 | diva_os_free(0, a->xdi_adapter.e_tbl); | ||
318 | a->xdi_adapter.e_tbl = NULL; | ||
319 | } | ||
320 | |||
321 | return (0); | ||
322 | } | ||
323 | |||
324 | void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter) | ||
325 | { | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | ** Get serial number | ||
330 | */ | ||
331 | static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a) | ||
332 | { | ||
333 | dword serNo = 0; | ||
334 | byte __iomem *confIO; | ||
335 | word serHi, serLo; | ||
336 | word __iomem *confMem; | ||
337 | |||
338 | confIO = DIVA_OS_MEM_ATTACH_CFG(&a->xdi_adapter); | ||
339 | serHi = (word) (inppw(&confIO[0x22]) & 0x0FFF); | ||
340 | serLo = (word) (inppw(&confIO[0x26]) & 0x0FFF); | ||
341 | serNo = ((dword) serHi << 16) | (dword) serLo; | ||
342 | DIVA_OS_MEM_DETACH_CFG(&a->xdi_adapter, confIO); | ||
343 | |||
344 | if ((serNo == 0) || (serNo == 0xFFFFFFFF)) { | ||
345 | DBG_FTL(("W: BRI use BAR[0] to get card serial number")) | ||
346 | |||
347 | confMem = (word __iomem *)DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter); | ||
348 | serHi = (word) (READ_WORD(&confMem[0x11]) & 0x0FFF); | ||
349 | serLo = (word) (READ_WORD(&confMem[0x13]) & 0x0FFF); | ||
350 | serNo = (((dword) serHi) << 16) | ((dword) serLo); | ||
351 | DIVA_OS_MEM_DETACH_RAM(&a->xdi_adapter, confMem); | ||
352 | } | ||
353 | |||
354 | DBG_LOG(("Serial Number=%ld", serNo)) | ||
355 | |||
356 | return (serNo); | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | ** Unregister I/O and register it with new name, | ||
361 | ** based on Serial Number | ||
362 | */ | ||
363 | static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a) | ||
364 | { | ||
365 | int i; | ||
366 | |||
367 | for (i = 1; i < 3; i++) { | ||
368 | diva_os_register_io_port(a, 0, a->resources.pci.bar[i], | ||
369 | a->resources.pci.length[i], | ||
370 | &a->port_name[0], i); | ||
371 | a->resources.pci.addr[i] = NULL; | ||
372 | } | ||
373 | |||
374 | sprintf(a->port_name, "DIVA BRI %ld", | ||
375 | (long) a->xdi_adapter.serialNo); | ||
376 | |||
377 | for (i = 1; i < 3; i++) { | ||
378 | if (diva_os_register_io_port(a, 1, a->resources.pci.bar[i], | ||
379 | a->resources.pci.length[i], | ||
380 | &a->port_name[0], i)) { | ||
381 | DBG_ERR(("A: failed to reregister BAR[%d]", i)) | ||
382 | return (-1); | ||
383 | } | ||
384 | a->resources.pci.addr[i] = | ||
385 | (void *) (unsigned long) a->resources.pci.bar[i]; | ||
386 | } | ||
387 | |||
388 | return (0); | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | ** Process command from user mode | ||
393 | */ | ||
394 | static int | ||
395 | diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | ||
396 | diva_xdi_um_cfg_cmd_t * cmd, int length) | ||
397 | { | ||
398 | int ret = -1; | ||
399 | |||
400 | if (cmd->adapter != a->controller) { | ||
401 | DBG_ERR(("A: pri_cmd, invalid controller=%d != %d", | ||
402 | cmd->adapter, a->controller)) | ||
403 | return (-1); | ||
404 | } | ||
405 | |||
406 | switch (cmd->command) { | ||
407 | case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL: | ||
408 | a->xdi_mbox.data_length = sizeof(dword); | ||
409 | a->xdi_mbox.data = | ||
410 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
411 | if (a->xdi_mbox.data) { | ||
412 | *(dword *) a->xdi_mbox.data = | ||
413 | (dword) a->CardOrdinal; | ||
414 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
415 | ret = 0; | ||
416 | } | ||
417 | break; | ||
418 | |||
419 | case DIVA_XDI_UM_CMD_GET_SERIAL_NR: | ||
420 | a->xdi_mbox.data_length = sizeof(dword); | ||
421 | a->xdi_mbox.data = | ||
422 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
423 | if (a->xdi_mbox.data) { | ||
424 | *(dword *) a->xdi_mbox.data = | ||
425 | (dword) a->xdi_adapter.serialNo; | ||
426 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
427 | ret = 0; | ||
428 | } | ||
429 | break; | ||
430 | |||
431 | case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG: | ||
432 | a->xdi_mbox.data_length = sizeof(dword) * 9; | ||
433 | a->xdi_mbox.data = | ||
434 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
435 | if (a->xdi_mbox.data) { | ||
436 | int i; | ||
437 | dword *data = (dword *) a->xdi_mbox.data; | ||
438 | |||
439 | for (i = 0; i < 8; i++) { | ||
440 | *data++ = a->resources.pci.bar[i]; | ||
441 | } | ||
442 | *data++ = (dword) a->resources.pci.irq; | ||
443 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
444 | ret = 0; | ||
445 | } | ||
446 | break; | ||
447 | |||
448 | case DIVA_XDI_UM_CMD_GET_CARD_STATE: | ||
449 | a->xdi_mbox.data_length = sizeof(dword); | ||
450 | a->xdi_mbox.data = | ||
451 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
452 | if (a->xdi_mbox.data) { | ||
453 | dword *data = (dword *) a->xdi_mbox.data; | ||
454 | if (!a->xdi_adapter.port) { | ||
455 | *data = 3; | ||
456 | } else if (a->xdi_adapter.trapped) { | ||
457 | *data = 2; | ||
458 | } else if (a->xdi_adapter.Initialized) { | ||
459 | *data = 1; | ||
460 | } else { | ||
461 | *data = 0; | ||
462 | } | ||
463 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
464 | ret = 0; | ||
465 | } | ||
466 | break; | ||
467 | |||
468 | case DIVA_XDI_UM_CMD_RESET_ADAPTER: | ||
469 | ret = diva_bri_reset_adapter(&a->xdi_adapter); | ||
470 | break; | ||
471 | |||
472 | case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK: | ||
473 | ret = diva_bri_write_sdram_block(&a->xdi_adapter, | ||
474 | cmd->command_data. | ||
475 | write_sdram.offset, | ||
476 | (byte *) & cmd[1], | ||
477 | cmd->command_data. | ||
478 | write_sdram.length); | ||
479 | break; | ||
480 | |||
481 | case DIVA_XDI_UM_CMD_START_ADAPTER: | ||
482 | ret = diva_bri_start_adapter(&a->xdi_adapter, | ||
483 | cmd->command_data.start. | ||
484 | offset, | ||
485 | cmd->command_data.start. | ||
486 | features); | ||
487 | break; | ||
488 | |||
489 | case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES: | ||
490 | a->xdi_adapter.features = | ||
491 | cmd->command_data.features.features; | ||
492 | a->xdi_adapter.a.protocol_capabilities = | ||
493 | a->xdi_adapter.features; | ||
494 | DBG_TRC( | ||
495 | ("Set raw protocol features (%08x)", | ||
496 | a->xdi_adapter.features)) ret = 0; | ||
497 | break; | ||
498 | |||
499 | case DIVA_XDI_UM_CMD_STOP_ADAPTER: | ||
500 | ret = diva_bri_stop_adapter(a); | ||
501 | break; | ||
502 | |||
503 | case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY: | ||
504 | ret = diva_card_read_xlog(a); | ||
505 | break; | ||
506 | |||
507 | default: | ||
508 | DBG_ERR( | ||
509 | ("A: A(%d) invalid cmd=%d", a->controller, | ||
510 | cmd->command))} | ||
511 | |||
512 | return (ret); | ||
513 | } | ||
514 | |||
515 | static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter) | ||
516 | { | ||
517 | byte __iomem *addrHi, *addrLo, *ioaddr; | ||
518 | dword i; | ||
519 | byte __iomem *Port; | ||
520 | |||
521 | if (!IoAdapter->port) { | ||
522 | return (-1); | ||
523 | } | ||
524 | if (IoAdapter->Initialized) { | ||
525 | DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first", | ||
526 | IoAdapter->ANum)) return (-1); | ||
527 | } | ||
528 | (*(IoAdapter->rstFnc)) (IoAdapter); | ||
529 | diva_os_wait(100); | ||
530 | Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); | ||
531 | addrHi = Port + | ||
532 | ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); | ||
533 | addrLo = Port + ADDR; | ||
534 | ioaddr = Port + DATA; | ||
535 | /* | ||
536 | recover | ||
537 | */ | ||
538 | outpp(addrHi, (byte) 0); | ||
539 | outppw(addrLo, (word) 0); | ||
540 | outppw(ioaddr, (word) 0); | ||
541 | /* | ||
542 | clear shared memory | ||
543 | */ | ||
544 | outpp(addrHi, | ||
545 | (byte) ( | ||
546 | (IoAdapter->MemoryBase + IoAdapter->MemorySize - | ||
547 | BRI_SHARED_RAM_SIZE) >> 16)); | ||
548 | outppw(addrLo, 0); | ||
549 | for (i = 0; i < 0x8000; outppw(ioaddr, 0), ++i); | ||
550 | diva_os_wait(100); | ||
551 | |||
552 | /* | ||
553 | clear signature | ||
554 | */ | ||
555 | outpp(addrHi, | ||
556 | (byte) ( | ||
557 | (IoAdapter->MemoryBase + IoAdapter->MemorySize - | ||
558 | BRI_SHARED_RAM_SIZE) >> 16)); | ||
559 | outppw(addrLo, 0x1e); | ||
560 | outpp(ioaddr, 0); | ||
561 | outpp(ioaddr, 0); | ||
562 | |||
563 | outpp(addrHi, (byte) 0); | ||
564 | outppw(addrLo, (word) 0); | ||
565 | outppw(ioaddr, (word) 0); | ||
566 | |||
567 | DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); | ||
568 | |||
569 | /* | ||
570 | Forget all outstanding entities | ||
571 | */ | ||
572 | IoAdapter->e_count = 0; | ||
573 | if (IoAdapter->e_tbl) { | ||
574 | memset(IoAdapter->e_tbl, 0x00, | ||
575 | IoAdapter->e_max * sizeof(E_INFO)); | ||
576 | } | ||
577 | IoAdapter->head = 0; | ||
578 | IoAdapter->tail = 0; | ||
579 | IoAdapter->assign = 0; | ||
580 | IoAdapter->trapped = 0; | ||
581 | |||
582 | memset(&IoAdapter->a.IdTable[0], 0x00, | ||
583 | sizeof(IoAdapter->a.IdTable)); | ||
584 | memset(&IoAdapter->a.IdTypeTable[0], 0x00, | ||
585 | sizeof(IoAdapter->a.IdTypeTable)); | ||
586 | memset(&IoAdapter->a.FlowControlIdTable[0], 0x00, | ||
587 | sizeof(IoAdapter->a.FlowControlIdTable)); | ||
588 | memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00, | ||
589 | sizeof(IoAdapter->a.FlowControlSkipTable)); | ||
590 | memset(&IoAdapter->a.misc_flags_table[0], 0x00, | ||
591 | sizeof(IoAdapter->a.misc_flags_table)); | ||
592 | memset(&IoAdapter->a.rx_stream[0], 0x00, | ||
593 | sizeof(IoAdapter->a.rx_stream)); | ||
594 | memset(&IoAdapter->a.tx_stream[0], 0x00, | ||
595 | sizeof(IoAdapter->a.tx_stream)); | ||
596 | memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos)); | ||
597 | memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos)); | ||
598 | |||
599 | return (0); | ||
600 | } | ||
601 | |||
602 | static int | ||
603 | diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter, | ||
604 | dword address, const byte * data, dword length) | ||
605 | { | ||
606 | byte __iomem *addrHi, *addrLo, *ioaddr; | ||
607 | byte __iomem *Port; | ||
608 | |||
609 | if (!IoAdapter->port) { | ||
610 | return (-1); | ||
611 | } | ||
612 | |||
613 | Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); | ||
614 | addrHi = Port + | ||
615 | ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); | ||
616 | addrLo = Port + ADDR; | ||
617 | ioaddr = Port + DATA; | ||
618 | |||
619 | while (length--) { | ||
620 | outpp(addrHi, (word) (address >> 16)); | ||
621 | outppw(addrLo, (word) (address & 0x0000ffff)); | ||
622 | outpp(ioaddr, *data++); | ||
623 | address++; | ||
624 | } | ||
625 | |||
626 | DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); | ||
627 | return (0); | ||
628 | } | ||
629 | |||
630 | static int | ||
631 | diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, | ||
632 | dword start_address, dword features) | ||
633 | { | ||
634 | byte __iomem *Port; | ||
635 | dword i, test; | ||
636 | byte __iomem *addrHi, *addrLo, *ioaddr; | ||
637 | int started = 0; | ||
638 | ADAPTER *a = &IoAdapter->a; | ||
639 | |||
640 | if (IoAdapter->Initialized) { | ||
641 | DBG_ERR( | ||
642 | ("A: A(%d) bri_start_adapter, adapter already running", | ||
643 | IoAdapter->ANum)) return (-1); | ||
644 | } | ||
645 | if (!IoAdapter->port) { | ||
646 | DBG_ERR(("A: A(%d) bri_start_adapter, adapter not mapped", | ||
647 | IoAdapter->ANum)) return (-1); | ||
648 | } | ||
649 | |||
650 | sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum); | ||
651 | DBG_LOG(("A(%d) start BRI", IoAdapter->ANum)) | ||
652 | |||
653 | Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); | ||
654 | addrHi = Port + | ||
655 | ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); | ||
656 | addrLo = Port + ADDR; | ||
657 | ioaddr = Port + DATA; | ||
658 | |||
659 | outpp(addrHi, | ||
660 | (byte) ( | ||
661 | (IoAdapter->MemoryBase + IoAdapter->MemorySize - | ||
662 | BRI_SHARED_RAM_SIZE) >> 16)); | ||
663 | outppw(addrLo, 0x1e); | ||
664 | outppw(ioaddr, 0x00); | ||
665 | DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); | ||
666 | |||
667 | /* | ||
668 | start the protocol code | ||
669 | */ | ||
670 | Port = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); | ||
671 | outpp(Port, 0x08); | ||
672 | DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, Port); | ||
673 | |||
674 | Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); | ||
675 | addrHi = Port + | ||
676 | ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); | ||
677 | addrLo = Port + ADDR; | ||
678 | ioaddr = Port + DATA; | ||
679 | /* | ||
680 | wait for signature (max. 3 seconds) | ||
681 | */ | ||
682 | for (i = 0; i < 300; ++i) { | ||
683 | diva_os_wait(10); | ||
684 | outpp(addrHi, | ||
685 | (byte) ( | ||
686 | (IoAdapter->MemoryBase + | ||
687 | IoAdapter->MemorySize - | ||
688 | BRI_SHARED_RAM_SIZE) >> 16)); | ||
689 | outppw(addrLo, 0x1e); | ||
690 | test = (dword) inppw(ioaddr); | ||
691 | if (test == 0x4447) { | ||
692 | DBG_LOG( | ||
693 | ("Protocol startup time %d.%02d seconds", | ||
694 | (i / 100), (i % 100))) | ||
695 | started = 1; | ||
696 | break; | ||
697 | } | ||
698 | } | ||
699 | DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); | ||
700 | |||
701 | if (!started) { | ||
702 | DBG_FTL(("A: A(%d) %s: Adapter selftest failed 0x%04X", | ||
703 | IoAdapter->ANum, IoAdapter->Properties.Name, | ||
704 | test)) | ||
705 | (*(IoAdapter->trapFnc)) (IoAdapter); | ||
706 | return (-1); | ||
707 | } | ||
708 | |||
709 | IoAdapter->Initialized = 1; | ||
710 | |||
711 | /* | ||
712 | Check Interrupt | ||
713 | */ | ||
714 | IoAdapter->IrqCount = 0; | ||
715 | a->ReadyInt = 1; | ||
716 | |||
717 | if (IoAdapter->reset) { | ||
718 | Port = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); | ||
719 | outpp(Port, 0x41); | ||
720 | DIVA_OS_MEM_DETACH_RESET(IoAdapter, Port); | ||
721 | } | ||
722 | |||
723 | a->ram_out(a, &PR_RAM->ReadyInt, 1); | ||
724 | for (i = 0; ((!IoAdapter->IrqCount) && (i < 100)); i++) { | ||
725 | diva_os_wait(10); | ||
726 | } | ||
727 | if (!IoAdapter->IrqCount) { | ||
728 | DBG_ERR( | ||
729 | ("A: A(%d) interrupt test failed", | ||
730 | IoAdapter->ANum)) | ||
731 | IoAdapter->Initialized = 0; | ||
732 | IoAdapter->stop(IoAdapter); | ||
733 | return (-1); | ||
734 | } | ||
735 | |||
736 | IoAdapter->Properties.Features = (word) features; | ||
737 | diva_xdi_display_adapter_features(IoAdapter->ANum); | ||
738 | DBG_LOG(("A(%d) BRI adapter successfull started", IoAdapter->ANum)) | ||
739 | /* | ||
740 | Register with DIDD | ||
741 | */ | ||
742 | diva_xdi_didd_register_adapter(IoAdapter->ANum); | ||
743 | |||
744 | return (0); | ||
745 | } | ||
746 | |||
747 | static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t * a) | ||
748 | { | ||
749 | PISDN_ADAPTER IoAdapter = &a->xdi_adapter; | ||
750 | |||
751 | /* | ||
752 | clear any pending interrupt | ||
753 | */ | ||
754 | IoAdapter->disIrq(IoAdapter); | ||
755 | |||
756 | IoAdapter->tst_irq(&IoAdapter->a); | ||
757 | IoAdapter->clr_irq(&IoAdapter->a); | ||
758 | IoAdapter->tst_irq(&IoAdapter->a); | ||
759 | |||
760 | /* | ||
761 | kill pending dpcs | ||
762 | */ | ||
763 | diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr); | ||
764 | diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr); | ||
765 | } | ||
766 | |||
767 | /* | ||
768 | ** Stop card | ||
769 | */ | ||
770 | static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a) | ||
771 | { | ||
772 | PISDN_ADAPTER IoAdapter = &a->xdi_adapter; | ||
773 | int i = 100; | ||
774 | |||
775 | if (!IoAdapter->port) { | ||
776 | return (-1); | ||
777 | } | ||
778 | if (!IoAdapter->Initialized) { | ||
779 | DBG_ERR(("A: A(%d) can't stop BRI adapter - not running", | ||
780 | IoAdapter->ANum)) | ||
781 | return (-1); /* nothing to stop */ | ||
782 | } | ||
783 | IoAdapter->Initialized = 0; | ||
784 | |||
785 | /* | ||
786 | Disconnect Adapter from DIDD | ||
787 | */ | ||
788 | diva_xdi_didd_remove_adapter(IoAdapter->ANum); | ||
789 | |||
790 | /* | ||
791 | Stop interrupts | ||
792 | */ | ||
793 | a->clear_interrupts_proc = diva_bri_clear_interrupts; | ||
794 | IoAdapter->a.ReadyInt = 1; | ||
795 | IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt); | ||
796 | do { | ||
797 | diva_os_sleep(10); | ||
798 | } while (i-- && a->clear_interrupts_proc); | ||
799 | if (a->clear_interrupts_proc) { | ||
800 | diva_bri_clear_interrupts(a); | ||
801 | a->clear_interrupts_proc = NULL; | ||
802 | DBG_ERR(("A: A(%d) no final interrupt from BRI adapter", | ||
803 | IoAdapter->ANum)) | ||
804 | } | ||
805 | IoAdapter->a.ReadyInt = 0; | ||
806 | |||
807 | /* | ||
808 | Stop and reset adapter | ||
809 | */ | ||
810 | IoAdapter->stop(IoAdapter); | ||
811 | |||
812 | return (0); | ||
813 | } | ||