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