]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer1/ifpi/i4b_ifpi_pci.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer1 / ifpi / i4b_ifpi_pci.c
1 /*-
2  *   Copyright (c) 1999, 2000 Gary Jennejohn. All rights reserved.
3  *
4  *   Redistribution and use in source and binary forms, with or without
5  *   modification, are permitted provided that the following conditions
6  *   are met:
7  *
8  *   1. Redistributions of source code must retain the above copyright
9  *      notice, this list of conditions and the following disclaimer.
10  *   2. Redistributions in binary form must reproduce the above copyright
11  *      notice, this list of conditions and the following disclaimer in the
12  *      documentation and/or other materials provided with the distribution.
13  *   3. Neither the name of the author nor the names of any co-contributors
14  *      may be used to endorse or promote products derived from this software
15  *      without specific prior written permission.
16  *   4. Altered versions must be plainly marked as such, and must not be
17  *      misrepresented as being the original software and/or documentation.
18  *   
19  *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  *   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  *   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  *   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  *   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  *   SUCH DAMAGE.
30  */
31
32 /*---------------------------------------------------------------------------
33  *
34  *      i4b_ifpi_pci.c: AVM Fritz!Card PCI hardware driver
35  *      --------------------------------------------------
36  *      $Id: i4b_ifpi_pci.c,v 1.4 2000/06/02 11:58:56 hm Exp $
37  *      last edit-date: [Fri Jan 12 17:01:26 2001]
38  *
39  *---------------------------------------------------------------------------*/
40
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 #include "opt_i4b.h"
45
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/systm.h>
49 #include <sys/mbuf.h>
50
51 #include <machine/bus.h>
52 #include <sys/bus.h>
53 #include <sys/rman.h>
54
55 #include <dev/pci/pcireg.h>
56 #include <dev/pci/pcivar.h>
57
58 #include <sys/socket.h>
59 #include <net/if.h>
60
61 #include <i4b/include/i4b_debug.h>
62 #include <i4b/include/i4b_ioctl.h>
63 #include <i4b/include/i4b_trace.h>
64
65 #include <i4b/include/i4b_global.h>
66 #include <i4b/include/i4b_mbuf.h>
67
68 #include <i4b/layer1/i4b_l1.h>
69 #include <i4b/layer1/isic/i4b_isic.h>
70 #include <i4b/layer1/isic/i4b_isac.h>
71 #include <i4b/layer1/isic/i4b_hscx.h>
72
73 #include <i4b/layer1/ifpi/i4b_ifpi_ext.h>
74
75 #define PCI_AVMA1_VID 0x1244
76 #define PCI_AVMA1_DID 0x0a00
77
78 /* prototypes */
79
80 static void avma1pp_disable(device_t);
81 static void avma1pp_intr(void *);
82 static void hscx_write_reg(int, u_int, u_int, struct l1_softc *);
83 static u_char hscx_read_reg(int, u_int, struct l1_softc *);
84 static u_int hscx_read_reg_int(int, u_int, struct l1_softc *);
85 static void hscx_read_fifo(int, void *, size_t, struct l1_softc *);
86 static void hscx_write_fifo(int, void *, size_t, struct l1_softc *);
87 static void avma1pp_hscx_int_handler(struct l1_softc *);
88 static void avma1pp_hscx_intr(int, u_int, struct l1_softc *);
89 static void avma1pp_init_linktab(struct l1_softc *);
90 static void avma1pp_bchannel_setup(int, int, int, int);
91 static void avma1pp_bchannel_start(int, int);
92 static void avma1pp_hscx_init(struct l1_softc *, int, int);
93 static void avma1pp_bchannel_stat(int, int, bchan_statistics_t *);
94 static void avma1pp_set_linktab(int, int, drvr_link_t *);
95 static isdn_link_t * avma1pp_ret_linktab(int, int);
96 static int avma1pp_pci_probe(device_t);
97 static int avma1pp_hscx_fifo(l1_bchan_state_t *, struct l1_softc *);
98 int avma1pp_attach_avma1pp(device_t);
99 static void ifpi_isac_intr(struct l1_softc *sc);
100
101 static device_method_t avma1pp_pci_methods[] = {
102         /* Device interface */
103         DEVMETHOD(device_probe,         avma1pp_pci_probe),
104         DEVMETHOD(device_attach,        avma1pp_attach_avma1pp),
105         DEVMETHOD(device_shutdown,      avma1pp_disable),
106
107         /* bus interface */
108         DEVMETHOD(bus_print_child,      bus_generic_print_child),
109         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
110
111         { 0, 0 }
112 };
113
114 #if 0 /* use what's in l1_softc */
115 /* a minimal softc for the Fritz!Card PCI */
116 struct avma1pp_softc 
117 {
118         bus_space_handle_t      avma1pp_bhandle;
119         bus_space_tag_t         avma1pp_btag;
120         void                    *avma1pp_intrhand;
121         struct resource         *avma1pp_irq;
122         struct resource         *avma1pp_res;
123         /* pointer to ifpi_sc */
124         struct l1_softc *avma1pp_isc;
125 };
126 #endif
127
128 static driver_t avma1pp_pci_driver = {
129         "ifpi",
130         avma1pp_pci_methods,
131         sizeof(struct l1_softc)
132 };
133
134 static devclass_t avma1pp_pci_devclass;
135
136 DRIVER_MODULE(avma1pp, pci, avma1pp_pci_driver, avma1pp_pci_devclass, 0, 0);
137
138 /* jump table for multiplex routines */
139
140 struct i4b_l1mux_func avma1pp_l1mux_func = {
141         avma1pp_ret_linktab,
142         avma1pp_set_linktab,
143         ifpi_mph_command_req,
144         ifpi_ph_data_req,
145         ifpi_ph_activate_req,
146 };
147
148 struct l1_softc *ifpi_scp[IFPI_MAXUNIT];
149
150 /*---------------------------------------------------------------------------*
151  *      AVM PCI Fritz!Card special registers
152  *---------------------------------------------------------------------------*/
153
154 /*
155  *      register offsets from i/o base
156  */
157 #define STAT0_OFFSET            0x02
158 #define STAT1_OFFSET            0x03
159 #define ADDR_REG_OFFSET         0x04
160 /*#define MODREG_OFFSET         0x06
161 #define VERREG_OFFSET           0x07*/
162
163 /* these 2 are used to select an ISAC register set */
164 #define ISAC_LO_REG_OFFSET      0x04
165 #define ISAC_HI_REG_OFFSET      0x06
166
167 /* offset higher than this goes to the HI register set */
168 #define MAX_LO_REG_OFFSET       0x2f
169
170 /* mask for the offset */
171 #define ISAC_REGSET_MASK        0x0f
172
173 /* the offset from the base to the ISAC registers */
174 #define ISAC_REG_OFFSET         0x10
175
176 /* the offset from the base to the ISAC FIFO */
177 #define ISAC_FIFO               0x02
178
179 /* not really the HSCX, but sort of */
180 #define HSCX_FIFO               0x00
181 #define HSCX_STAT               0x04
182
183 /*
184  *      AVM PCI Status Latch 0 read only bits
185  */
186 #define ASL_IRQ_ISAC            0x01    /* ISAC  interrupt, active low */
187 #define ASL_IRQ_HSCX            0x02    /* HSX   interrupt, active low */
188 #define ASL_IRQ_TIMER           0x04    /* Timer interrupt, active low */
189 #define ASL_IRQ_BCHAN           ASL_IRQ_HSCX
190 /* actually active LOW */
191 #define ASL_IRQ_Pending         (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER)
192
193 /*
194  *      AVM Status Latch 0 write only bits
195  */
196 #define ASL_RESET_ALL           0x01  /* reset siemens IC's, active 1 */
197 #define ASL_TIMERDISABLE        0x02  /* active high */
198 #define ASL_TIMERRESET          0x04  /* active high */
199 #define ASL_ENABLE_INT          0x08  /* active high */
200 #define ASL_TESTBIT             0x10  /* active high */
201
202 /*
203  *      AVM Status Latch 1 write only bits
204  */
205 #define ASL1_INTSEL              0x0f  /* active high */
206 #define ASL1_ENABLE_IOM          0x80  /* active high */
207
208 /*
209  * "HSCX" mode bits
210  */
211 #define  HSCX_MODE_ITF_FLG      0x01
212 #define  HSCX_MODE_TRANS        0x02
213 #define  HSCX_MODE_CCR_7        0x04
214 #define  HSCX_MODE_CCR_16       0x08
215 #define  HSCX_MODE_TESTLOOP     0x80
216
217 /*
218  * "HSCX" status bits
219  */
220 #define  HSCX_STAT_RME          0x01
221 #define  HSCX_STAT_RDO          0x10
222 #define  HSCX_STAT_CRCVFRRAB    0x0E
223 #define  HSCX_STAT_CRCVFR       0x06
224 #define  HSCX_STAT_RML_MASK     0x3f00
225
226 /*
227  * "HSCX" interrupt bits
228  */
229 #define  HSCX_INT_XPR           0x80
230 #define  HSCX_INT_XDU           0x40
231 #define  HSCX_INT_RPR           0x20
232 #define  HSCX_INT_MASK          0xE0
233
234 /*
235  * "HSCX" command bits
236  */
237 #define  HSCX_CMD_XRS           0x80
238 #define  HSCX_CMD_XME           0x01
239 #define  HSCX_CMD_RRS           0x20
240 #define  HSCX_CMD_XML_MASK      0x3f00
241
242 /*
243  * Commands and parameters are sent to the "HSCX" as a long, but the
244  * fields are handled as bytes.
245  *
246  * The long contains:
247  *      (prot << 16)|(txl << 8)|cmd
248  *
249  * where:
250  *      prot = protocol to use
251  *      txl = transmit length
252  *      cmd = the command to be executed
253  *
254  * The fields are defined as u_char in struct l1_softc.
255  *
256  * Macro to coalesce the byte fields into a u_int
257  */
258 #define AVMA1PPSETCMDLONG(f) (f) = ((sc->avma1pp_cmd) | (sc->avma1pp_txl << 8) \
259                                         | (sc->avma1pp_prot << 16))
260
261 /*
262  * to prevent deactivating the "HSCX" when both channels are active we
263  * define an HSCX_ACTIVE flag which is or'd into the channel's state
264  * flag in avma1pp_bchannel_setup upon active and cleared upon deactivation.
265  * It is set high to allow room for new flags.
266  */
267 #define HSCX_AVMA1PP_ACTIVE     0x1000 
268
269 /*---------------------------------------------------------------------------*
270  *      AVM read fifo routines
271  *---------------------------------------------------------------------------*/
272
273 static void
274 avma1pp_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
275 {
276         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
277         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
278
279         switch (what) {
280                 case ISIC_WHAT_ISAC:
281                         bus_space_write_1(btag, bhandle,  ADDR_REG_OFFSET, ISAC_FIFO);
282                         bus_space_read_multi_1(btag, bhandle,  ISAC_REG_OFFSET, buf, size);
283                         break;
284                 case ISIC_WHAT_HSCXA:
285                         hscx_read_fifo(0, buf, size, sc);
286                         break;
287                 case ISIC_WHAT_HSCXB:
288                         hscx_read_fifo(1, buf, size, sc);
289                         break;
290         }
291 }
292
293 static void
294 hscx_read_fifo(int chan, void *buf, size_t len, struct l1_softc *sc)
295 {
296         u_int32_t *ip;
297         size_t cnt;
298         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
299         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
300
301         bus_space_write_4(btag, bhandle, ADDR_REG_OFFSET, chan);
302         ip = (u_int32_t *)buf;
303         cnt = 0;
304         /* what if len isn't a multiple of sizeof(int) and buf is */
305         /* too small ???? */
306         while (cnt < len)
307         {
308                 *ip++ = bus_space_read_4(btag, bhandle, ISAC_REG_OFFSET);
309                 cnt += 4;
310         }
311 }
312
313 /*---------------------------------------------------------------------------*
314  *      AVM write fifo routines
315  *---------------------------------------------------------------------------*/
316 static void
317 avma1pp_write_fifo(struct l1_softc *sc, int what, void *buf, size_t size)
318 {
319         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
320         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
321
322         switch (what) {
323                 case ISIC_WHAT_ISAC:
324                         bus_space_write_1(btag, bhandle,  ADDR_REG_OFFSET, ISAC_FIFO);
325                         bus_space_write_multi_1(btag, bhandle,  ISAC_REG_OFFSET, (u_int8_t*)buf, size);
326                         break;
327                 case ISIC_WHAT_HSCXA:
328                         hscx_write_fifo(0, buf, size, sc);
329                         break;
330                 case ISIC_WHAT_HSCXB:
331                         hscx_write_fifo(1, buf, size, sc);
332                         break;
333         }
334 }
335
336 static void
337 hscx_write_fifo(int chan, void *buf, size_t len, struct l1_softc *sc)
338 {
339         u_int32_t *ip;
340         size_t cnt;
341         l1_bchan_state_t *Bchan = &sc->sc_chan[chan];
342         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
343         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
344
345
346         sc->avma1pp_cmd &= ~HSCX_CMD_XME;
347         sc->avma1pp_txl = 0;
348         if (Bchan->out_mbuf_cur == NULL)
349         {
350           if (Bchan->bprot != BPROT_NONE)
351                  sc->avma1pp_cmd |= HSCX_CMD_XME;
352         }
353         if (len != sc->sc_bfifolen)
354                 sc->avma1pp_txl = len;
355         
356         cnt = 0; /* borrow cnt */
357         AVMA1PPSETCMDLONG(cnt);
358         hscx_write_reg(chan, HSCX_STAT, cnt, sc);
359
360         ip = (u_int32_t *)buf;
361         cnt = 0;
362         while (cnt < len)
363         {
364                 bus_space_write_4(btag, bhandle, ISAC_REG_OFFSET, *ip);
365                 ip++;
366                 cnt += 4;
367         }
368 }
369
370 /*---------------------------------------------------------------------------*
371  *      AVM write register routines
372  *---------------------------------------------------------------------------*/
373
374 static void
375 avma1pp_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data)
376 {
377         u_char reg_bank;
378         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
379         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
380
381         switch (what) {
382                 case ISIC_WHAT_ISAC:
383                         reg_bank = (offs > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
384 #ifdef AVMA1PCI_DEBUG
385                         printf("write_reg bank %d  off %ld.. ", (int)reg_bank, (long)offs);
386 #endif
387                         /* set the register bank */
388                         bus_space_write_1(btag, bhandle, ADDR_REG_OFFSET, reg_bank);
389                         bus_space_write_1(btag, bhandle, ISAC_REG_OFFSET + (offs & ISAC_REGSET_MASK), data);
390                         break;
391                 case ISIC_WHAT_HSCXA:
392                         hscx_write_reg(0, offs, data, sc);
393                         break;
394                 case ISIC_WHAT_HSCXB:
395                         hscx_write_reg(1, offs, data, sc);
396                         break;
397         }
398 }
399
400 static void
401 hscx_write_reg(int chan, u_int off, u_int val, struct l1_softc *sc)
402 {
403         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
404         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
405
406         /* point at the correct channel */
407         bus_space_write_4(btag, bhandle, ADDR_REG_OFFSET, chan);
408         bus_space_write_4(btag, bhandle, ISAC_REG_OFFSET + off, val);
409 }
410
411 /*---------------------------------------------------------------------------*
412  *      AVM read register routines
413  *---------------------------------------------------------------------------*/
414 static u_int8_t
415 avma1pp_read_reg(struct l1_softc *sc, int what, bus_size_t offs)
416 {
417         u_char reg_bank;
418         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
419         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
420
421         switch (what) {
422                 case ISIC_WHAT_ISAC:
423                         reg_bank = (offs > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
424 #ifdef AVMA1PCI_DEBUG
425                         printf("read_reg bank %d  off %ld.. ", (int)reg_bank, (long)offs);
426 #endif
427                         /* set the register bank */
428                         bus_space_write_1(btag, bhandle, ADDR_REG_OFFSET, reg_bank);
429                         return(bus_space_read_1(btag, bhandle, ISAC_REG_OFFSET +
430                                 (offs & ISAC_REGSET_MASK)));
431                 case ISIC_WHAT_HSCXA:
432                         return hscx_read_reg(0, offs, sc);
433                 case ISIC_WHAT_HSCXB:
434                         return hscx_read_reg(1, offs, sc);
435         }
436         return 0;
437 }
438
439 static u_char
440 hscx_read_reg(int chan, u_int off, struct l1_softc *sc)
441 {
442         return(hscx_read_reg_int(chan, off, sc) & 0xff);
443 }
444
445 /*
446  * need to be able to return an int because the RBCH is in the 2nd
447  * byte.
448  */
449 static u_int
450 hscx_read_reg_int(int chan, u_int off, struct l1_softc *sc)
451 {
452         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
453         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
454
455         /* point at the correct channel */
456         bus_space_write_4(btag, bhandle, ADDR_REG_OFFSET, chan);
457         return(bus_space_read_4(btag, bhandle, ISAC_REG_OFFSET + off));
458 }
459
460 /*---------------------------------------------------------------------------*
461  *      avma1pp_probe - probe for a card
462  *---------------------------------------------------------------------------*/
463 static int
464 avma1pp_pci_probe(dev)
465         device_t                dev;
466 {
467         u_int16_t               did, vid;
468
469         vid = pci_get_vendor(dev);
470         did = pci_get_device(dev);
471
472         if ((vid == PCI_AVMA1_VID) && (did == PCI_AVMA1_DID)) {
473                 device_set_desc(dev, "AVM Fritz!Card PCI");
474                 return(0);
475         }
476
477         return(ENXIO);
478 }
479
480 /*---------------------------------------------------------------------------*
481  *      avma1pp_attach_avma1pp - attach Fritz!Card PCI
482  *---------------------------------------------------------------------------*/
483 int
484 avma1pp_attach_avma1pp(device_t dev)
485 {
486         struct l1_softc *sc;
487         u_int v;
488         int unit, error = 0;
489         int s;
490         u_int16_t did, vid;
491         void *ih = 0;
492         bus_space_handle_t bhandle;
493         bus_space_tag_t btag; 
494         l1_bchan_state_t *chan;
495
496         s = splimp();
497
498         vid = pci_get_vendor(dev);
499         did = pci_get_device(dev);
500         sc = device_get_softc(dev);
501         unit = device_get_unit(dev);
502         bzero(sc, sizeof(struct l1_softc));
503
504         /* probably not really required */
505         if(unit >= IFPI_MAXUNIT) {
506                 printf("avma1pp%d: Error, unit >= IFPI_MAXUNIT!\n", unit);
507                 splx(s);
508                 return(ENXIO);
509         }
510
511         if ((vid != PCI_AVMA1_VID) && (did != PCI_AVMA1_DID)) {
512                 printf("avma1pp%d: unknown device!?\n", unit);
513                 goto fail;
514         }
515
516         ifpi_scp[unit] = sc;
517
518         sc->sc_resources.io_rid[0] = PCIR_BAR(1);
519         sc->sc_resources.io_base[0] = bus_alloc_resource_any(dev,
520                 SYS_RES_IOPORT, &sc->sc_resources.io_rid[0], RF_ACTIVE);
521
522         if (sc->sc_resources.io_base[0] == NULL) {
523                 printf("avma1pp%d: couldn't map IO port\n", unit);
524                 error = ENXIO;
525                 goto fail;
526         }
527
528         bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
529         btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
530
531         /* Allocate interrupt */
532         sc->sc_resources.irq_rid = 0;
533         sc->sc_resources.irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
534                 &sc->sc_resources.irq_rid, RF_SHAREABLE | RF_ACTIVE);
535
536         if (sc->sc_resources.irq == NULL) {
537                 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(1), sc->sc_resources.io_base[0]);
538                 printf("avma1pp%d: couldn't map interrupt\n", unit);
539                 error = ENXIO;
540                 goto fail;
541         }
542
543         error = bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET, NULL, avma1pp_intr, sc, &ih);
544
545         if (error) {
546                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_resources.irq);
547                 bus_release_resource(dev, SYS_RES_IOPORT, PCIR_BAR(1), sc->sc_resources.io_base[0]);
548                 printf("avma1pp%d: couldn't set up irq\n", unit);
549                 goto fail;
550         }
551
552         sc->sc_unit = unit;
553
554         /* end of new-bus stuff */
555
556         ISAC_BASE = (caddr_t)ISIC_WHAT_ISAC;
557
558         HSCX_A_BASE = (caddr_t)ISIC_WHAT_HSCXA;
559         HSCX_B_BASE = (caddr_t)ISIC_WHAT_HSCXB;
560
561         /* setup access routines */
562
563         sc->clearirq = NULL;
564         sc->readreg = avma1pp_read_reg;
565         sc->writereg = avma1pp_write_reg;
566
567         sc->readfifo = avma1pp_read_fifo;
568         sc->writefifo = avma1pp_write_fifo;
569
570         /* setup card type */
571         
572         sc->sc_cardtyp = CARD_TYPEP_AVMA1PCI;
573
574         /* setup IOM bus type */
575         
576         sc->sc_bustyp = BUS_TYPE_IOM2;
577
578         /* set up some other miscellaneous things */
579         sc->sc_ipac = 0;
580         sc->sc_bfifolen = HSCX_FIFO_LEN;
581
582         /* reset the card */
583         /* the Linux driver does this to clear any pending ISAC interrupts */
584         v = 0;
585         v = ISAC_READ(I_STAR);
586 #ifdef AVMA1PCI_DEBUG
587         printf("avma1pp_attach: I_STAR %x...", v);
588 #endif
589         v = ISAC_READ(I_MODE);
590 #ifdef AVMA1PCI_DEBUG
591         printf("avma1pp_attach: I_MODE %x...", v);
592 #endif
593         v = ISAC_READ(I_ADF2);
594 #ifdef AVMA1PCI_DEBUG
595         printf("avma1pp_attach: I_ADF2 %x...", v);
596 #endif
597         v = ISAC_READ(I_ISTA);
598 #ifdef AVMA1PCI_DEBUG
599         printf("avma1pp_attach: I_ISTA %x...", v);
600 #endif
601         if (v & ISAC_ISTA_EXI)
602         {
603                  v = ISAC_READ(I_EXIR);
604 #ifdef AVMA1PCI_DEBUG
605                  printf("avma1pp_attach: I_EXIR %x...", v);
606 #endif
607         }
608         v = ISAC_READ(I_CIRR);
609 #ifdef AVMA1PCI_DEBUG
610         printf("avma1pp_attach: I_CIRR %x...", v);
611 #endif
612         ISAC_WRITE(I_MASK, 0xff);
613         /* the Linux driver does this to clear any pending HSCX interrupts */
614         v = hscx_read_reg_int(0, HSCX_STAT, sc);
615 #ifdef AVMA1PCI_DEBUG
616         printf("avma1pp_attach: 0 HSCX_STAT %x...", v);
617 #endif
618         v = hscx_read_reg_int(1, HSCX_STAT, sc);
619 #ifdef AVMA1PCI_DEBUG
620         printf("avma1pp_attach: 1 HSCX_STAT %x\n", v);
621 #endif
622
623         bus_space_write_1(btag, bhandle, STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
624         DELAY(SEC_DELAY/100); /* 10 ms */
625         bus_space_write_1(btag, bhandle, STAT0_OFFSET, ASL_TIMERRESET|ASL_ENABLE_INT|ASL_TIMERDISABLE);
626         DELAY(SEC_DELAY/100); /* 10 ms */
627 #ifdef AVMA1PCI_DEBUG
628         bus_space_write_1(btag, bhandle, STAT1_OFFSET, ASL1_ENABLE_IOM|sc->sc_irq);
629         DELAY(SEC_DELAY/100); /* 10 ms */
630         v = bus_space_read_1(btag, bhandle, STAT1_OFFSET);
631         printf("after reset: S1 %#x\n", v);
632
633         v = bus_space_read_4(btag, bhandle, 0);
634         printf("avma1pp_attach_avma1pp: v %#x\n", v);
635 #endif
636
637    /* from here to the end would normally be done in isic_pciattach */
638
639          printf("ifpi%d: ISAC %s (IOM-%c)\n", unit,
640                 "2085 Version A1/A2 or 2086/2186 Version 1.1",
641                  sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
642
643         /* init the ISAC */
644         ifpi_isac_init(sc);
645
646 #if defined (__FreeBSD__) && __FreeBSD__ > 4
647         /* Init the channel mutexes */
648         chan = &sc->sc_chan[HSCX_CH_A];
649         if(!mtx_initialized(&chan->rx_queue.ifq_mtx))
650                 mtx_init(&chan->rx_queue.ifq_mtx, "i4b_avma1pp_rx", NULL, MTX_DEF);
651         if(!mtx_initialized(&chan->tx_queue.ifq_mtx))
652                 mtx_init(&chan->tx_queue.ifq_mtx, "i4b_avma1pp_tx", NULL, MTX_DEF);
653         chan = &sc->sc_chan[HSCX_CH_B];
654         if(!mtx_initialized(&chan->rx_queue.ifq_mtx))
655                 mtx_init(&chan->rx_queue.ifq_mtx, "i4b_avma1pp_rx", NULL, MTX_DEF);
656         if(!mtx_initialized(&chan->tx_queue.ifq_mtx))
657                 mtx_init(&chan->tx_queue.ifq_mtx, "i4b_avma1pp_tx", NULL, MTX_DEF);
658 #endif
659
660         /* init the "HSCX" */
661         avma1pp_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
662         
663         avma1pp_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);
664
665         /* can't use the normal B-Channel stuff */
666         avma1pp_init_linktab(sc);
667
668         /* set trace level */
669
670         sc->sc_trace = TRACE_OFF;
671
672         sc->sc_state = ISAC_IDLE;
673
674         sc->sc_ibuf = NULL;
675         sc->sc_ib = NULL;
676         sc->sc_ilen = 0;
677
678         sc->sc_obuf = NULL;
679         sc->sc_op = NULL;
680         sc->sc_ol = 0;
681         sc->sc_freeflag = 0;
682
683         sc->sc_obuf2 = NULL;
684         sc->sc_freeflag2 = 0;
685
686 #if defined(__FreeBSD__) && __FreeBSD__ >=3
687         callout_handle_init(&sc->sc_T3_callout);
688         callout_handle_init(&sc->sc_T4_callout);        
689 #endif
690         
691         /* init higher protocol layers */
692         
693         i4b_l1_mph_status_ind(L0IFPIUNIT(sc->sc_unit), STI_ATTACH, sc->sc_cardtyp, &avma1pp_l1mux_func);
694
695   fail:
696         splx(s);
697         return(error);
698 }
699
700 /*
701  * this is the real interrupt routine
702  */
703 static void
704 avma1pp_hscx_intr(int h_chan, u_int stat, struct l1_softc *sc)
705 {
706         register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
707         int activity = -1;
708         u_int param = 0;
709         
710         NDBGL1(L1_H_IRQ, "%#x", stat);
711
712         if((stat & HSCX_INT_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
713         {
714                 chan->stat_XDU++;                       
715                 NDBGL1(L1_H_XFRERR, "xmit data underrun");
716                 /* abort the transmission */
717                 sc->avma1pp_txl = 0;
718                 sc->avma1pp_cmd |= HSCX_CMD_XRS;
719                 AVMA1PPSETCMDLONG(param);
720                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
721                 sc->avma1pp_cmd &= ~HSCX_CMD_XRS;
722                 AVMA1PPSETCMDLONG(param);
723                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
724
725                 if (chan->out_mbuf_head != NULL)  /* don't continue to transmit this buffer */
726                 {
727                         i4b_Bfreembuf(chan->out_mbuf_head);
728                         chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
729                 }
730         }
731
732         /*
733          * The following is based on examination of the Linux driver.
734          *
735          * The logic here is different than with a "real" HSCX; all kinds
736          * of information (interrupt/status bits) are in stat.
737          *              HSCX_INT_RPR indicates a receive interrupt
738          *                      HSCX_STAT_RDO indicates an overrun condition, abort -
739          *                      otherwise read the bytes ((stat & HSCX_STZT_RML_MASK) >> 8)
740          *                      HSCX_STAT_RME indicates end-of-frame and apparently any
741          *                      CRC/framing errors are only reported in this state.
742          *                              if ((stat & HSCX_STAT_CRCVFRRAB) != HSCX_STAT_CRCVFR)
743          *                                      CRC/framing error
744          */
745         
746         if(stat & HSCX_INT_RPR)
747         {
748                 register int fifo_data_len;
749                 int error = 0;
750                 /* always have to read the FIFO, so use a scratch buffer */
751                 u_char scrbuf[HSCX_FIFO_LEN];
752
753                 if(stat & HSCX_STAT_RDO)
754                 {
755                         chan->stat_RDO++;
756                         NDBGL1(L1_H_XFRERR, "receive data overflow");
757                         error++;                                
758                 }
759
760                 /*
761                  * check whether we're receiving data for an inactive B-channel
762                  * and discard it. This appears to happen for telephony when
763                  * both B-channels are active and one is deactivated. Since
764                  * it is not really possible to deactivate the channel in that
765                  * case (the ASIC seems to deactivate _both_ channels), the
766                  * "deactivated" channel keeps receiving data which can lead
767                  * to exhaustion of mbufs and a kernel panic.
768                  *
769                  * This is a hack, but it's the only solution I can think of
770                  * without having the documentation for the ASIC.
771                  * GJ - 28 Nov 1999
772                  */
773                  if (chan->state == HSCX_IDLE)
774                  {
775                         NDBGL1(L1_H_XFRERR, "toss data from %d", h_chan);
776                         error++;
777                  }
778
779                 fifo_data_len = ((stat & HSCX_STAT_RML_MASK) >> 8);
780                 
781                 if(fifo_data_len == 0)
782                         fifo_data_len = sc->sc_bfifolen;
783
784                 /* ALWAYS read data from HSCX fifo */
785         
786                 HSCX_RDFIFO(h_chan, scrbuf, fifo_data_len);
787                 chan->rxcount += fifo_data_len;
788
789                 /* all error conditions checked, now decide and take action */
790                 
791                 if(error == 0)
792                 {
793                         if(chan->in_mbuf == NULL)
794                         {
795                                 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
796                                         panic("L1 avma1pp_hscx_intr: RME, cannot allocate mbuf!\n");
797                                 chan->in_cbptr = chan->in_mbuf->m_data;
798                                 chan->in_len = 0;
799                         }
800
801                         if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
802                         {
803                                 /* OK to copy the data */
804                                 bcopy(scrbuf, chan->in_cbptr, fifo_data_len);
805                                 chan->in_cbptr += fifo_data_len;
806                                 chan->in_len += fifo_data_len;
807
808                                 /* setup mbuf data length */
809                                         
810                                 chan->in_mbuf->m_len = chan->in_len;
811                                 chan->in_mbuf->m_pkthdr.len = chan->in_len;
812
813                                 if(sc->sc_trace & TRACE_B_RX)
814                                 {
815                                         i4b_trace_hdr_t hdr;
816                                         hdr.unit = L0IFPIUNIT(sc->sc_unit);
817                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
818                                         hdr.dir = FROM_NT;
819                                         hdr.count = ++sc->sc_trace_bcount;
820                                         MICROTIME(hdr.time);
821                                         i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
822                                 }
823
824                                 if (stat & HSCX_STAT_RME)
825                                 {
826                                   if((stat & HSCX_STAT_CRCVFRRAB) == HSCX_STAT_CRCVFR)
827                                   {
828                                          (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
829                                          activity = ACT_RX;
830                                 
831                                          /* mark buffer ptr as unused */
832                                         
833                                          chan->in_mbuf = NULL;
834                                          chan->in_cbptr = NULL;
835                                          chan->in_len = 0;
836                                   }
837                                   else
838                                   {
839                                                 chan->stat_CRC++;
840                                                 NDBGL1(L1_H_XFRERR, "CRC/RAB");
841                                           if (chan->in_mbuf != NULL)
842                                           {
843                                                   i4b_Bfreembuf(chan->in_mbuf);
844                                                   chan->in_mbuf = NULL;
845                                                   chan->in_cbptr = NULL;
846                                                   chan->in_len = 0;
847                                           }
848                                   }
849                                 }
850                         } /* END enough space in mbuf */
851                         else
852                         {
853                                  if(chan->bprot == BPROT_NONE)
854                                  {
855                                           /* setup mbuf data length */
856                                 
857                                           chan->in_mbuf->m_len = chan->in_len;
858                                           chan->in_mbuf->m_pkthdr.len = chan->in_len;
859
860                                           if(sc->sc_trace & TRACE_B_RX)
861                                           {
862                                                         i4b_trace_hdr_t hdr;
863                                                         hdr.unit = L0IFPIUNIT(sc->sc_unit);
864                                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
865                                                         hdr.dir = FROM_NT;
866                                                         hdr.count = ++sc->sc_trace_bcount;
867                                                         MICROTIME(hdr.time);
868                                                         i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
869                                                 }
870
871                                           if(!(i4b_l1_bchan_tel_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
872                                                  activity = ACT_RX;
873                                 
874                                           /* move rx'd data to rx queue */
875
876 #if defined (__FreeBSD__) && __FreeBSD__ > 4
877                                           (void) IF_HANDOFF(&chan->rx_queue, chan->in_mbuf, NULL);
878 #else
879                                           if(!(IF_QFULL(&chan->rx_queue)))
880                                           {
881                                                 IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
882                                           }
883                                           else
884                                           {
885                                                 i4b_Bfreembuf(chan->in_mbuf);
886                                           }
887 #endif                                  
888                                           /* signal upper layer that data are available */
889                                           (*chan->isic_drvr_linktab->bch_rx_data_ready)(chan->isic_drvr_linktab->unit);
890
891                                           /* alloc new buffer */
892                                 
893                                           if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
894                                                  panic("L1 avma1pp_hscx_intr: RPF, cannot allocate new mbuf!\n");
895         
896                                           /* setup new data ptr */
897                                 
898                                           chan->in_cbptr = chan->in_mbuf->m_data;
899         
900                                           /* OK to copy the data */
901                                           bcopy(scrbuf, chan->in_cbptr, fifo_data_len);
902
903                                           chan->in_cbptr += fifo_data_len;
904                                           chan->in_len = fifo_data_len;
905
906                                           chan->rxcount += fifo_data_len;
907                                         }
908                                  else
909                                         {
910                                           NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
911                                           chan->in_cbptr = chan->in_mbuf->m_data;
912                                           chan->in_len = 0;
913                                         }
914                           }
915                 } /* if(error == 0) */
916                 else
917                 {
918                         /* land here for RDO */
919                         if (chan->in_mbuf != NULL)
920                         {
921                                 i4b_Bfreembuf(chan->in_mbuf);
922                                 chan->in_mbuf = NULL;
923                                 chan->in_cbptr = NULL;
924                                 chan->in_len = 0;
925                         }
926                         sc->avma1pp_txl = 0;
927                         sc->avma1pp_cmd |= HSCX_CMD_RRS;
928                         AVMA1PPSETCMDLONG(param);
929                         hscx_write_reg(h_chan, HSCX_STAT, param, sc);
930                         sc->avma1pp_cmd &= ~HSCX_CMD_RRS;
931                         AVMA1PPSETCMDLONG(param);
932                         hscx_write_reg(h_chan, HSCX_STAT, param, sc);
933                 }
934         }
935
936
937         /* transmit fifo empty, new data can be written to fifo */
938         
939         if(stat & HSCX_INT_XPR)
940         {
941                 /*
942                  * for a description what is going on here, please have
943                  * a look at isic_bchannel_start() in i4b_bchan.c !
944                  */
945
946                 NDBGL1(L1_H_IRQ, "unit %d, chan %d - XPR, Tx Fifo Empty!", sc->sc_unit, h_chan);
947
948                 if(chan->out_mbuf_cur == NULL)  /* last frame is transmitted */
949                 {
950                         IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
951
952                         if(chan->out_mbuf_head == NULL)
953                         {
954                                 chan->state &= ~HSCX_TX_ACTIVE;
955                                 (*chan->isic_drvr_linktab->bch_tx_queue_empty)(chan->isic_drvr_linktab->unit);
956                         }
957                         else
958                         {
959                                 chan->state |= HSCX_TX_ACTIVE;
960                                 chan->out_mbuf_cur = chan->out_mbuf_head;
961                                 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
962                                 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
963
964                                 if(sc->sc_trace & TRACE_B_TX)
965                                 {
966                                         i4b_trace_hdr_t hdr;
967                                         hdr.unit = L0IFPIUNIT(sc->sc_unit);
968                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
969                                         hdr.dir = FROM_TE;
970                                         hdr.count = ++sc->sc_trace_bcount;
971                                         MICROTIME(hdr.time);
972                                         i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
973                                 }
974                                 
975                                 if(chan->bprot == BPROT_NONE)
976                                 {
977                                         if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
978                                                 activity = ACT_TX;
979                                 }
980                                 else
981                                 {
982                                         activity = ACT_TX;
983                                 }
984                         }
985                 }
986                         
987                 avma1pp_hscx_fifo(chan, sc);
988         }
989
990         /* call timeout handling routine */
991         
992         if(activity == ACT_RX || activity == ACT_TX)
993                 (*chan->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity);
994 }
995
996 /*
997  * this is the main routine which checks each channel and then calls
998  * the real interrupt routine as appropriate
999  */
1000 static void
1001 avma1pp_hscx_int_handler(struct l1_softc *sc)
1002 {
1003         u_int stat;
1004
1005         /* has to be a u_int because the byte count is in the 2nd byte */
1006         stat = hscx_read_reg_int(0, HSCX_STAT, sc);
1007         if (stat & HSCX_INT_MASK)
1008           avma1pp_hscx_intr(0, stat, sc);
1009         stat = hscx_read_reg_int(1, HSCX_STAT, sc);
1010         if (stat & HSCX_INT_MASK)
1011           avma1pp_hscx_intr(1, stat, sc);
1012 }
1013
1014 static void
1015 avma1pp_disable(device_t dev)
1016 {
1017         struct l1_softc *sc = device_get_softc(dev);
1018         bus_space_handle_t bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
1019         bus_space_tag_t btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
1020
1021         bus_space_write_1(btag, bhandle, STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
1022 }
1023
1024 static void
1025 avma1pp_intr(void *xsc)
1026 {
1027         u_char stat;
1028         struct l1_softc *sc;
1029         bus_space_handle_t bhandle;
1030         bus_space_tag_t btag; 
1031
1032         sc = xsc;
1033         bhandle = rman_get_bushandle(sc->sc_resources.io_base[0]);
1034         btag = rman_get_bustag(sc->sc_resources.io_base[0]); 
1035
1036         stat = bus_space_read_1(btag, bhandle, STAT0_OFFSET);
1037         NDBGL1(L1_H_IRQ, "stat %x", stat);
1038         /* was there an interrupt from this card ? */
1039         if ((stat & ASL_IRQ_Pending) == ASL_IRQ_Pending)
1040                 return; /* no */
1041         /* interrupts are low active */
1042         if (!(stat & ASL_IRQ_TIMER))
1043           NDBGL1(L1_H_IRQ, "timer interrupt ???");
1044         if (!(stat & ASL_IRQ_HSCX))
1045         {
1046           NDBGL1(L1_H_IRQ, "HSCX");
1047                 avma1pp_hscx_int_handler(sc);
1048         }
1049         if (!(stat & ASL_IRQ_ISAC))
1050         {
1051           NDBGL1(L1_H_IRQ, "ISAC");
1052                 ifpi_isac_intr(sc);
1053         }
1054 }
1055
1056 static void
1057 avma1pp_hscx_init(struct l1_softc *sc, int h_chan, int activate)
1058 {
1059         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
1060         u_int param = 0;
1061
1062         NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s",
1063                 sc->sc_unit, h_chan, activate ? "activate" : "deactivate");
1064
1065         if (activate == 0)
1066         {
1067                 /* only deactivate if both channels are idle */
1068                 if (sc->sc_chan[HSCX_CH_A].state != HSCX_IDLE ||
1069                         sc->sc_chan[HSCX_CH_B].state != HSCX_IDLE)
1070                 {
1071                         return;
1072                 }
1073                 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
1074                 sc->avma1pp_prot = HSCX_MODE_TRANS;
1075                 AVMA1PPSETCMDLONG(param);
1076                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
1077                 return;
1078         }
1079         if(chan->bprot == BPROT_RHDLC)
1080         {
1081                   NDBGL1(L1_BCHAN, "BPROT_RHDLC");
1082
1083                 /* HDLC Frames, transparent mode 0 */
1084                 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
1085                 sc->avma1pp_prot = HSCX_MODE_ITF_FLG;
1086                 AVMA1PPSETCMDLONG(param);
1087                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
1088                 sc->avma1pp_cmd = HSCX_CMD_XRS;
1089                 AVMA1PPSETCMDLONG(param);
1090                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
1091                 sc->avma1pp_cmd = 0;
1092         }
1093         else
1094         {
1095                   NDBGL1(L1_BCHAN, "BPROT_NONE??");
1096
1097                 /* Raw Telephony, extended transparent mode 1 */
1098                 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
1099                 sc->avma1pp_prot = HSCX_MODE_TRANS;
1100                 AVMA1PPSETCMDLONG(param);
1101                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
1102                 sc->avma1pp_cmd = HSCX_CMD_XRS;
1103                 AVMA1PPSETCMDLONG(param);
1104                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
1105                 sc->avma1pp_cmd = 0;
1106         }
1107 }
1108
1109 static void
1110 avma1pp_bchannel_setup(int unit, int h_chan, int bprot, int activate)
1111 {
1112 #ifdef __FreeBSD__
1113         struct l1_softc *sc = ifpi_scp[unit];
1114 #else
1115         struct l1_softc *sc = isic_find_sc(unit);
1116 #endif
1117         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
1118
1119         int s = SPLI4B();
1120         
1121         if(activate == 0)
1122         {
1123                 /* deactivation */
1124                 chan->state = HSCX_IDLE;
1125                 avma1pp_hscx_init(sc, h_chan, activate);
1126         }
1127                 
1128         NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s",
1129                 sc->sc_unit, h_chan, activate ? "activate" : "deactivate");
1130
1131         /* general part */
1132
1133         chan->unit = sc->sc_unit;       /* unit number */
1134         chan->channel = h_chan;         /* B channel */
1135         chan->bprot = bprot;            /* B channel protocol */
1136         chan->state = HSCX_IDLE;        /* B channel state */
1137
1138         /* receiver part */
1139
1140         chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
1141
1142         i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
1143
1144         chan->rxcount = 0;              /* reset rx counter */
1145         
1146         i4b_Bfreembuf(chan->in_mbuf);   /* clean rx mbuf */
1147
1148         chan->in_mbuf = NULL;           /* reset mbuf ptr */
1149         chan->in_cbptr = NULL;          /* reset mbuf curr ptr */
1150         chan->in_len = 0;               /* reset mbuf data len */
1151         
1152         /* transmitter part */
1153
1154         chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
1155         
1156         i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
1157
1158         chan->txcount = 0;              /* reset tx counter */
1159         
1160         i4b_Bfreembuf(chan->out_mbuf_head);     /* clean tx mbuf */
1161
1162         chan->out_mbuf_head = NULL;     /* reset head mbuf ptr */
1163         chan->out_mbuf_cur = NULL;      /* reset current mbuf ptr */    
1164         chan->out_mbuf_cur_ptr = NULL;  /* reset current mbuf data ptr */
1165         chan->out_mbuf_cur_len = 0;     /* reset current mbuf data cnt */
1166         
1167         if(activate != 0)
1168         {
1169                 /* activation */
1170                 avma1pp_hscx_init(sc, h_chan, activate);
1171                 chan->state |= HSCX_AVMA1PP_ACTIVE;
1172         }
1173
1174         splx(s);
1175 }
1176
1177 static void
1178 avma1pp_bchannel_start(int unit, int h_chan)
1179 {
1180 #ifdef __FreeBSD__
1181         struct l1_softc *sc = ifpi_scp[unit];
1182 #else
1183         struct l1_softc *sc = isic_find_sc(unit);
1184 #endif
1185         register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
1186         int s;
1187         int activity = -1;
1188
1189         s = SPLI4B();                           /* enter critical section */
1190         if(chan->state & HSCX_TX_ACTIVE)        /* already running ? */
1191         {
1192                 splx(s);
1193                 return;                         /* yes, leave */
1194         }
1195
1196         /* get next mbuf from queue */
1197         
1198         IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
1199         
1200         if(chan->out_mbuf_head == NULL)         /* queue empty ? */
1201         {
1202                 splx(s);                        /* leave critical section */
1203                 return;                         /* yes, exit */
1204         }
1205
1206         /* init current mbuf values */
1207         
1208         chan->out_mbuf_cur = chan->out_mbuf_head;
1209         chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
1210         chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;    
1211         
1212         /* activity indicator for timeout handling */
1213
1214         if(chan->bprot == BPROT_NONE)
1215         {
1216                 if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
1217                         activity = ACT_TX;
1218         }
1219         else
1220         {
1221                 activity = ACT_TX;
1222         }
1223
1224         chan->state |= HSCX_TX_ACTIVE;          /* we start transmitting */
1225         
1226         if(sc->sc_trace & TRACE_B_TX)   /* if trace, send mbuf to trace dev */
1227         {
1228                 i4b_trace_hdr_t hdr;
1229                 hdr.unit = L0IFPIUNIT(sc->sc_unit);
1230                 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
1231                 hdr.dir = FROM_TE;
1232                 hdr.count = ++sc->sc_trace_bcount;
1233                 MICROTIME(hdr.time);
1234                 i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
1235         }                       
1236
1237         avma1pp_hscx_fifo(chan, sc);
1238
1239         /* call timeout handling routine */
1240         
1241         if(activity == ACT_RX || activity == ACT_TX)
1242                 (*chan->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity);
1243
1244         splx(s);        
1245 }
1246
1247 /*---------------------------------------------------------------------------*
1248  *      return the address of isic drivers linktab      
1249  *---------------------------------------------------------------------------*/
1250 static isdn_link_t *
1251 avma1pp_ret_linktab(int unit, int channel)
1252 {
1253 #ifdef __FreeBSD__
1254         struct l1_softc *sc = ifpi_scp[unit];
1255 #else
1256         struct l1_softc *sc = isic_find_sc(unit);
1257 #endif
1258         l1_bchan_state_t *chan = &sc->sc_chan[channel];
1259
1260         return(&chan->isic_isdn_linktab);
1261 }
1262  
1263 /*---------------------------------------------------------------------------*
1264  *      set the driver linktab in the b channel softc
1265  *---------------------------------------------------------------------------*/
1266 static void
1267 avma1pp_set_linktab(int unit, int channel, drvr_link_t *dlt)
1268 {
1269 #ifdef __FreeBSD__
1270         struct l1_softc *sc = ifpi_scp[unit];
1271 #else
1272         struct l1_softc *sc = isic_find_sc(unit);
1273 #endif
1274         l1_bchan_state_t *chan = &sc->sc_chan[channel];
1275
1276         chan->isic_drvr_linktab = dlt;
1277 }
1278
1279
1280 /*---------------------------------------------------------------------------*
1281  *      initialize our local linktab
1282  *---------------------------------------------------------------------------*/
1283 static void
1284 avma1pp_init_linktab(struct l1_softc *sc)
1285 {
1286         l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A];
1287         isdn_link_t *lt = &chan->isic_isdn_linktab;
1288
1289         /* make sure the hardware driver is known to layer 4 */
1290         /* avoid overwriting if already set */
1291         if (ctrl_types[CTRL_PASSIVE].set_linktab == NULL)
1292         {
1293                 ctrl_types[CTRL_PASSIVE].set_linktab = i4b_l1_set_linktab;
1294                 ctrl_types[CTRL_PASSIVE].get_linktab = i4b_l1_ret_linktab;
1295         }
1296
1297         /* local setup */
1298         lt->unit = sc->sc_unit;
1299         lt->channel = HSCX_CH_A;
1300         lt->bch_config = avma1pp_bchannel_setup;
1301         lt->bch_tx_start = avma1pp_bchannel_start;
1302         lt->bch_stat = avma1pp_bchannel_stat;
1303         lt->tx_queue = &chan->tx_queue;
1304
1305         /* used by non-HDLC data transfers, i.e. telephony drivers */
1306         lt->rx_queue = &chan->rx_queue;
1307
1308         /* used by HDLC data transfers, i.e. ipr and isp drivers */     
1309         lt->rx_mbuf = &chan->in_mbuf;   
1310                                                 
1311         chan = &sc->sc_chan[HSCX_CH_B];
1312         lt = &chan->isic_isdn_linktab;
1313
1314         lt->unit = sc->sc_unit;
1315         lt->channel = HSCX_CH_B;
1316         lt->bch_config = avma1pp_bchannel_setup;
1317         lt->bch_tx_start = avma1pp_bchannel_start;
1318         lt->bch_stat = avma1pp_bchannel_stat;
1319         lt->tx_queue = &chan->tx_queue;
1320
1321         /* used by non-HDLC data transfers, i.e. telephony drivers */
1322         lt->rx_queue = &chan->rx_queue;
1323
1324         /* used by HDLC data transfers, i.e. ipr and isp drivers */     
1325         lt->rx_mbuf = &chan->in_mbuf;   
1326 }
1327
1328 /*
1329  * use this instead of isic_bchannel_stat in i4b_bchan.c because it's static
1330  */
1331 static void
1332 avma1pp_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp)
1333 {
1334 #ifdef __FreeBSD__
1335         struct l1_softc *sc = ifpi_scp[unit];
1336 #else
1337         struct l1_softc *sc = isic_find_sc(unit);
1338 #endif
1339         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
1340         int s;
1341
1342         s = SPLI4B();
1343         
1344         bsp->outbytes = chan->txcount;
1345         bsp->inbytes = chan->rxcount;
1346
1347         chan->txcount = 0;
1348         chan->rxcount = 0;
1349
1350         splx(s);
1351 }
1352
1353 /*---------------------------------------------------------------------------*
1354  *      fill HSCX fifo with data from the current mbuf
1355  *      Put this here until it can go into i4b_hscx.c
1356  *---------------------------------------------------------------------------*/
1357 static int
1358 avma1pp_hscx_fifo(l1_bchan_state_t *chan, struct l1_softc *sc)
1359 {
1360         int len;
1361         int nextlen;
1362         int i;
1363         int cmd = 0;
1364         /* using a scratch buffer simplifies writing to the FIFO */
1365         u_char scrbuf[HSCX_FIFO_LEN];
1366
1367         len = 0;
1368
1369         /*
1370          * fill the HSCX tx fifo with data from the current mbuf. if
1371          * current mbuf holds less data than HSCX fifo length, try to
1372          * get the next mbuf from (a possible) mbuf chain. if there is
1373          * not enough data in a single mbuf or in a chain, then this
1374          * is the last mbuf and we tell the HSCX that it has to send
1375          * CRC and closing flag
1376          */
1377          
1378         while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
1379         {
1380                 nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
1381
1382 #ifdef NOTDEF
1383                 printf("i:mh=%p, mc=%p, mcp=%p, mcl=%d l=%d nl=%d # ",
1384                         chan->out_mbuf_head,
1385                         chan->out_mbuf_cur,                     
1386                         chan->out_mbuf_cur_ptr,
1387                         chan->out_mbuf_cur_len,
1388                         len,
1389                         nextlen);
1390 #endif
1391
1392                 cmd |= HSCX_CMDR_XTF;
1393                 /* collect the data in the scratch buffer */
1394                 for (i = 0; i < nextlen; i++)
1395                         scrbuf[i + len] = chan->out_mbuf_cur_ptr[i];
1396
1397                 len += nextlen;
1398                 chan->txcount += nextlen;
1399         
1400                 chan->out_mbuf_cur_ptr += nextlen;
1401                 chan->out_mbuf_cur_len -= nextlen;
1402                         
1403                 if(chan->out_mbuf_cur_len == 0) 
1404                 {
1405                         if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
1406                         {
1407                                 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
1408                                 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
1409         
1410                                 if(sc->sc_trace & TRACE_B_TX)
1411                                 {
1412                                         i4b_trace_hdr_t hdr;
1413                                         hdr.unit = L0IFPIUNIT(sc->sc_unit);
1414                                         hdr.type = (chan->channel == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
1415                                         hdr.dir = FROM_TE;
1416                                         hdr.count = ++sc->sc_trace_bcount;
1417                                         MICROTIME(hdr.time);
1418                                         i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
1419                                 }
1420                         }
1421                         else
1422                         {
1423                                 if (chan->bprot != BPROT_NONE)
1424                                         cmd |= HSCX_CMDR_XME;
1425                                 i4b_Bfreembuf(chan->out_mbuf_head);
1426                                 chan->out_mbuf_head = NULL;
1427                         }
1428                 }
1429         }
1430         /* write what we have from the scratch buf to the HSCX fifo */
1431         if (len != 0)
1432                 HSCX_WRFIFO(chan->channel, scrbuf, len);
1433         return(cmd);
1434 }
1435
1436 /*---------------------------------------------------------------------------*
1437  *      ifpi - ISAC interrupt routine
1438  *---------------------------------------------------------------------------*/
1439 static void
1440 ifpi_isac_intr(struct l1_softc *sc)
1441 {
1442         register u_char isac_irq_stat;
1443
1444         for(;;)
1445         {
1446                 /* get isac irq status */
1447                 isac_irq_stat = ISAC_READ(I_ISTA);
1448
1449                 if(isac_irq_stat)
1450                         ifpi_isac_irq(sc, isac_irq_stat); /* isac handler */
1451                 else
1452                         break;
1453         }
1454
1455         ISAC_WRITE(I_MASK, 0xff);
1456
1457         DELAY(100);
1458
1459         ISAC_WRITE(I_MASK, ISAC_IMASK);
1460 }
1461
1462 /*---------------------------------------------------------------------------*
1463  *      ifpi_recover - try to recover from irq lockup
1464  *---------------------------------------------------------------------------*/
1465 void
1466 ifpi_recover(struct l1_softc *sc)
1467 {
1468         u_char byte;
1469         
1470         /* get isac irq status */
1471
1472         byte = ISAC_READ(I_ISTA);
1473
1474         NDBGL1(L1_ERROR, "  ISAC: ISTA = 0x%x", byte);
1475         
1476         if(byte & ISAC_ISTA_EXI)
1477                 NDBGL1(L1_ERROR, "  ISAC: EXIR = 0x%x", (u_char)ISAC_READ(I_EXIR));
1478
1479         if(byte & ISAC_ISTA_CISQ)
1480         {
1481                 byte = ISAC_READ(I_CIRR);
1482         
1483                 NDBGL1(L1_ERROR, "  ISAC: CISQ = 0x%x", byte);
1484                 
1485                 if(byte & ISAC_CIRR_SQC)
1486                         NDBGL1(L1_ERROR, "  ISAC: SQRR = 0x%x", (u_char)ISAC_READ(I_SQRR));
1487         }
1488
1489         NDBGL1(L1_ERROR, "  ISAC: IMASK = 0x%x", ISAC_IMASK);
1490
1491         ISAC_WRITE(I_MASK, 0xff);       
1492         DELAY(100);
1493         ISAC_WRITE(I_MASK, ISAC_IMASK);
1494 }