GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / isdn / hardware / eicon / os_bri.c
1 // SPDX-License-Identifier: GPL-2.0
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"
20 #include "dsrv_bri.h"
21
22 /*
23 **  IMPORTS
24 */
25 extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter);
26 extern void diva_xdi_display_adapter_features(int card);
27 extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
28
29 /*
30 **  LOCALS
31 */
32 static int bri_bar_length[3] = {
33         0x80,
34         0x80,
35         0x20
36 };
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);
39 static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
40                                   diva_xdi_um_cfg_cmd_t *cmd, int length);
41 static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a);
42 static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter);
43 static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
44                                       dword address,
45                                       const byte *data, dword length);
46 static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
47                                   dword start_address, dword features);
48 static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a);
49
50 static void diva_bri_set_addresses(diva_os_xdi_adapter_t *a)
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;
58
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 */
76 int diva_bri_init_card(diva_os_xdi_adapter_t *a)
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         /*
86           Set properties
87         */
88         a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
89         DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
90
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                         }
103                 }
104
105         a->resources.pci.irq =
106                 (byte) divasa_get_pci_irq(a->resources.pci.bus,
107                                           a->resources.pci.func,
108                                           a->resources.pci.hdev);
109         if (!a->resources.pci.irq) {
110                 DBG_ERR(("A: invalid irq"));
111                 return (-1);
112         }
113
114         /*
115           Get length of I/O bar 2 - it is different by older
116           EEPROM version
117         */
118         Bus = a->resources.pci.bus;
119         Slot = a->resources.pci.func;
120         hdev = a->resources.pci.hdev;
121
122         /*
123           Get plain original values of the BAR2 CDM registers
124         */
125         PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
126         PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
127         /*
128           Disable device and get BAR2 length
129         */
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         /*
134           Restore BAR2 and CMD registers
135         */
136         PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
137         PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
138
139         /*
140           Calculate BAR2 length
141         */
142         bar2_length = (~(bar2_length & ~7)) + 1;
143         DBG_LOG(("BAR[2] length=%lx", bar2_length))
144
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                 }
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]"))
162                         diva_bri_cleanup_adapter(a);
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]"))
171                         diva_bri_cleanup_adapter(a);
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         /*
178           Set all memory areas
179         */
180         diva_bri_set_addresses(a);
181
182         /*
183           Get Serial Number
184         */
185         a->xdi_adapter.serialNo = diva_bri_get_serial_number(a);
186
187         /*
188           Register I/O ports with correct name now
189         */
190         if (diva_bri_reregister_io(a)) {
191                 diva_bri_cleanup_adapter(a);
192                 return (-1);
193         }
194
195         /*
196           Initialize OS dependent objects
197         */
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         /*
217           Do not initialize second DPC - only one thread will be created
218         */
219         a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
220
221         /*
222           Create entity table
223         */
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         /*
234           Set up interface
235         */
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         /*
250           Set IRQ handler
251         */
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
269 static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
270 {
271         int i;
272
273         if (a->xdi_adapter.Initialized) {
274                 diva_bri_stop_adapter(a);
275         }
276
277         /*
278           Remove ISR Handler
279         */
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         /*
304           Free OS objects
305         */
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         /*
316           Free memory
317         */
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 */
333 static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t *a)
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
349                         confMem = (word __iomem *)DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter);
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
358                 return (serNo);
359 }
360
361 /*
362 **  Unregister I/O and register it with new name,
363 **  based on Serial Number
364 */
365 static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a)
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))
384                                 return (-1);
385                 }
386                 a->resources.pci.addr[i] =
387                         (void *) (unsigned long) a->resources.pci.bar[i];
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,
398                        diva_xdi_um_cfg_cmd_t *cmd, int length)
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))
405                         return (-1);
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 =
412                         diva_os_malloc(0, a->xdi_mbox.data_length);
413                 if (a->xdi_mbox.data) {
414                         *(dword *) a->xdi_mbox.data =
415                                 (dword) a->CardOrdinal;
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 =
424                         diva_os_malloc(0, a->xdi_mbox.data_length);
425                 if (a->xdi_mbox.data) {
426                         *(dword *) a->xdi_mbox.data =
427                                 (dword) a->xdi_adapter.serialNo;
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 =
436                         diva_os_malloc(0, a->xdi_mbox.data_length);
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 =
453                         diva_os_malloc(0, a->xdi_mbox.data_length);
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,
478                                                  (byte *)&cmd[1],
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 =
493                         cmd->command_data.features.features;
494                 a->xdi_adapter.a.protocol_capabilities =
495                         a->xdi_adapter.features;
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 +
534                 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
535         addrLo = Port + ADDR;
536         ioaddr = Port + DATA;
537         /*
538           recover
539         */
540         outpp(addrHi, (byte) 0);
541         outppw(addrLo, (word) 0);
542         outppw(ioaddr, (word) 0);
543         /*
544           clear shared memory
545         */
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         /*
555           clear signature
556         */
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         /*
572           Forget all outstanding entities
573         */
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,
606                            dword address, const byte *data, dword length)
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 +
617                 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
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
655                 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
656         addrHi = Port +
657                 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
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         /*
670           start the protocol code
671         */
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 +
678                 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
679         addrLo = Port + ADDR;
680         ioaddr = Port + DATA;
681         /*
682           wait for signature (max. 3 seconds)
683         */
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)))
697                                 started = 1;
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))
707                         (*(IoAdapter->trapFnc)) (IoAdapter);
708                 return (-1);
709         }
710
711         IoAdapter->Initialized = 1;
712
713         /*
714           Check Interrupt
715         */
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))
733                         IoAdapter->Initialized = 0;
734                 IoAdapter->stop(IoAdapter);
735                 return (-1);
736         }
737
738         IoAdapter->Properties.Features = (word) features;
739         diva_xdi_display_adapter_features(IoAdapter->ANum);
740         DBG_LOG(("A(%d) BRI adapter successfully started", IoAdapter->ANum))
741                 /*
742                   Register with DIDD
743                 */
744                 diva_xdi_didd_register_adapter(IoAdapter->ANum);
745
746         return (0);
747 }
748
749 static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t *a)
750 {
751         PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
752
753         /*
754           clear any pending interrupt
755         */
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         /*
763           kill pending dpcs
764         */
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 */
772 static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a)
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))
783                         return (-1);    /* nothing to stop */
784         }
785         IoAdapter->Initialized = 0;
786
787         /*
788           Disconnect Adapter from DIDD
789         */
790         diva_xdi_didd_remove_adapter(IoAdapter->ANum);
791
792         /*
793           Stop interrupts
794         */
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))
806                         }
807         IoAdapter->a.ReadyInt = 0;
808
809         /*
810           Stop and reset adapter
811         */
812         IoAdapter->stop(IoAdapter);
813
814         return (0);
815 }