]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer1/ihfc/i4b_ihfc_pnp.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer1 / ihfc / i4b_ihfc_pnp.c
1 /*-
2  * Copyright (c) 2000 Hans Petter Selasky. 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /*---------------------------------------------------------------------------
27  *
28  *      i4b_ihfc_pnp.c - common hfc ISA PnP-bus interface
29  *      -------------------------------------------------
30  *      - Everything which has got anything to to with "PnP" bus setup has
31  *        been put here, except the chip spesific "PnP" setup.
32  *
33  *      last edit-date: [Tue Jan 23 16:03:33 2001]
34  *      $Id: i4b_ihfc_pnp.c,v 1.9 2000/09/19 13:50:36 hm Exp $
35  *     
36  *---------------------------------------------------------------------------*/
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/socket.h>
45 #include <net/if.h>
46
47 #include <i4b/include/i4b_global.h>
48
49 #include <i4b/include/i4b_ioctl.h>
50 #include <i4b/include/i4b_trace.h>
51
52 #include <i4b/layer1/i4b_l1.h>
53 #include <i4b/layer1/ihfc/i4b_ihfc.h>
54 #include <i4b/layer1/ihfc/i4b_ihfc_ext.h>
55
56 #include <machine/bus.h>
57 #include <machine/resource.h>
58 #include <sys/bus.h>
59 #include <sys/rman.h>
60
61 #include <isa/isavar.h>
62
63 /*---------------------------------------------------------------------------*
64  *      Softc
65  *---------------------------------------------------------------------------*/
66 ihfc_sc_t               ihfc_softc[IHFC_MAXUNIT];
67
68 /*---------------------------------------------------------------------------*
69  *      Prototypes
70  *---------------------------------------------------------------------------*/
71 static int ihfc_isa_probe       (device_t dev);
72 static int ihfc_pnp_probe       (device_t dev);
73 static int ihfc_pnp_attach      (device_t dev);
74 static int ihfc_pnp_detach      (device_t dev, u_int flag);
75 static int ihfc_pnp_shutdown    (device_t dev);
76
77 const struct ihfc_pnp_ids
78 {
79         u_long  vid;            /* vendor id                    */
80         int     flag;           /*                              */
81         u_char  hfc;            /* chip type                    */
82         u_char  iirq;           /* internal irq                 */
83         u_short iio;            /* internal io-address          */
84         u_char  stdel;          /* S/T delay compensation       */
85 }
86         ihfc_pnp_ids[] =
87 {
88         { 0x10262750, CARD_TYPEP_16_3C,   HFC_S,  2, 0x200, 0x2d},
89         { 0x20262750, CARD_TYPEP_16_3C,   HFC_SP, 0, 0x000, 0x0f},
90         { 0x1411d805, CARD_TYPEP_ACERP10, HFC_S,  1, 0x300, 0x0e},
91         { 0 }
92 };
93
94 typedef const struct ihfc_pnp_ids ihfc_id_t;
95
96 /*---------------------------------------------------------------------------*
97  *      PCB layout
98  *
99  *      IIRQx: Internal IRQ cross reference for a card
100  *      IRQx : Supported IRQ's for a card
101  *      IOx  : Supported IO-bases for a card
102  *
103  *      IO0, IRQ0, IIRQ0: TELEINT ISDN SPEED No. 1
104  *                 IIRQ3: Teles 16.3c PnP (B version)
105  *---------------------------------------------------------------------------*/
106                       /* IRQ  ->  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
107 #define IIRQ0 ((const u_char []){ 0, 0, 0, 1, 2, 3, 0, 4, 0, 0, 5, 6, 0, 0, 0, 0 })
108 #define IRQ0  ((const u_char []){          3, 4, 5,    7,     0xa, 0xb, 0 })
109
110 #define IO0   ((const u_long []){ 0x300, 0x330, 0x278, 0x2e8, 0 })
111
112 #define IIRQ3 ((const u_char []){ 0, 0, 0, 7, 0, 1, 0, 0, 0, 2, 3, 4, 5, 0, 0, 6 })
113
114 /*---------------------------------------------------------------------------*
115  *      ISA PnP setup
116  *---------------------------------------------------------------------------*/
117 static device_method_t ihfc_pnp_methods[] = 
118 {
119         DEVMETHOD(device_probe,         ihfc_pnp_probe),
120         DEVMETHOD(device_attach,        ihfc_pnp_attach),
121         DEVMETHOD(device_shutdown,      ihfc_pnp_shutdown),
122         { 0, 0 }
123 };                              
124
125 static driver_t ihfc_pnp_driver = 
126 {
127         "ihfc",
128         ihfc_pnp_methods,
129         0,
130 };
131
132 static devclass_t ihfc_devclass;
133
134 DRIVER_MODULE(ihfcpnp, isa, ihfc_pnp_driver, ihfc_devclass, 0, 0);
135
136 /*---------------------------------------------------------------------------*
137  *      probe for ISA "PnP" card
138  *---------------------------------------------------------------------------*/
139 static int
140 ihfc_pnp_probe(device_t dev)
141 {
142         u_int          unit = device_get_unit(dev);     /* get unit       */
143         u_int32_t       vid = isa_get_vendorid(dev);    /* vendor id      */
144         ihfc_id_t      *ids = &ihfc_pnp_ids[0];         /* ids ptr        */
145         ihfc_sc_t       *sc = &ihfc_softc[unit];        /* softc          */
146         u_char         flag = 0;                        /* flag           */
147         void         *dummy = 0;                        /* a dummy        */
148
149         HFC_VAR;
150
151         if (unit >= IHFC_MAXUNIT)
152         {
153                 printf("ihfc%d: Error, unit %d >= IHFC_MAXUNIT", unit, unit);
154                 return ENXIO;
155         }
156
157         if (!vid) return ihfc_isa_probe(dev);
158
159         HFC_BEG;
160
161         for ( ;(ids->vid); ids++)
162         {
163                 if (ids->vid == vid)
164                 {
165                         flag = 0;
166
167                         bzero(sc, sizeof(ihfc_sc_t));           /* reset data structure.*
168                                                                  * Zero is default for  *
169                                                                  * most, so calling the *
170                                                                  * int. handler now will*
171                                                                  * not be a problem.    */
172
173                         S_IOBASE[0] = bus_alloc_resource(
174                                 dev, SYS_RES_IOPORT, &S_IORID[0],
175                                 0UL, ~0UL, 2, RF_ACTIVE
176                                 );
177
178                         S_IRQ = bus_alloc_resource_any(
179                                 dev, SYS_RES_IRQ, &S_IRQRID,
180                                 RF_ACTIVE
181                                 );
182
183                         S_DLP     = IHFC_DLP;           /* set D-priority       */
184                         S_HFC     = ids->hfc;           /* set chip type        */
185                         S_I4BFLAG = ids->flag;          /* set flag             */
186                         S_NTMODE  = IHFC_NTMODE;        /* set mode             */
187                         S_STDEL   = ids->stdel;         /* set delay            */
188
189                         S_I4BUNIT = L0IHFCUNIT(unit);   /* set "i4b" unit       */
190                         S_TRACE   = TRACE_OFF;          /* set trace mask       */
191                         S_UNIT    = unit;               /* set up unit numbers  */
192
193                         if (S_IOBASE[0] && S_IRQ)
194                         {
195                                 if (ids->iio)
196                                 {
197                                         S_IIO  = ids->iio;
198                                         S_IIRQ = ids->iirq;
199                                 }
200                                 else
201                                 {
202                                         S_IIO  = rman_get_start(S_IOBASE[0]) & 0x3ff;
203                                         S_IIRQ = IIRQ3[rman_get_start(S_IRQ) & 0xf];
204                                 }
205
206                                 /* setup interrupt routine now to avvoid stray  *
207                                  * interrupts.                                  */
208
209                                 if (bus_setup_intr(dev, S_IRQ, INTR_TYPE_NET,
210                                         NULL, (void(*)(void*)) HFC_INTR, sc,
211                                         &dummy) != 0)
212                                 {
213                                         printf("ihfc%d: failed to setup irq.\n",
214                                                 unit);
215                                         HFC_END;
216                                         return ENXIO;
217                                 }
218
219                                 flag = 1;
220
221                                 if (!HFC_CONTROL(sc, 1))
222                                 {
223                                         HFC_END;
224                                         return 0;       /* success */
225                                 }
226                                 else
227                                 {
228                                         printf("ihfc%d: Chip seems corrupted. "
229                                         "Please hard reboot your computer!\n",
230                                         unit);                                  
231                                 }
232                         }
233
234                         ihfc_pnp_detach(dev, flag);
235                 }
236         }
237
238         HFC_END;
239         return ENXIO;   /* failure */
240 }
241
242 /*---------------------------------------------------------------------------*
243  *      probe for "ISA" cards
244  *---------------------------------------------------------------------------*/
245 static int
246 ihfc_isa_probe(device_t dev)
247 {
248         u_int           unit = device_get_unit(dev);    /* get unit       */
249         ihfc_sc_t        *sc = &ihfc_softc[unit];       /* softc          */
250         const u_char    *irq = &IRQ0[0];                /* irq's to try   */
251         const u_long *iobase = &IO0[0];                 /* iobases to try */
252         u_char          flag = 0;                       /* flag           */
253         void          *dummy = 0;                       /* a dummy        */
254
255         HFC_VAR;
256
257         bzero(sc, sizeof(ihfc_sc_t));           /* reset data structure  *
258                                                  * We must reset the     *
259                                                  * datastructure here,   *
260                                                  * else we risk zero-out *
261                                                  * our gotten resources. */
262         HFC_BEG;
263
264   j0:   while(*irq)     /* get supported IRQ */
265         {
266                 if ((S_IRQ = bus_alloc_resource(
267                         dev, SYS_RES_IRQ, &S_IRQRID,
268                         *irq, *irq, 1, RF_ACTIVE
269                         )
270                    ))
271                                 break;
272                 else
273                                 irq++;
274         }
275
276         while(*iobase)  /* get supported IO-PORT */
277         {
278                 if ((S_IOBASE[0] = bus_alloc_resource(
279                         dev, SYS_RES_IOPORT, &S_IORID[0],
280                         *iobase, *iobase, 2, RF_ACTIVE
281                         )
282                    ))
283                                 break;
284                 else
285                                 iobase++;
286         }
287
288         flag = 0;
289
290         if (*irq && *iobase)    /* we got our resources, now test chip */
291         {
292                 S_DLP     = IHFC_DLP;           /* set D-priority       */
293                 S_HFC     = HFC_1;              /* set chip type        */
294                 S_I4BFLAG = CARD_TYPEP_TELEINT_NO_1; /* set flag        */
295                 S_NTMODE  = IHFC_NTMODE;        /* set mode             */
296                 S_STDEL   = 0x00;               /* set delay (not used) */
297
298                 S_I4BUNIT = L0IHFCUNIT(unit);   /* set "i4b" unit       */
299                 S_TRACE   = TRACE_OFF;          /* set trace mask       */
300                 S_UNIT    = unit;               /* set up unit numbers  */
301
302                 S_IIRQ    = IIRQ0[*irq];        /* set internal irq     */
303                 S_IIO     = *iobase;            /* set internal iobase  */
304
305                 /* setup interrupt routine now to avvoid stray  *
306                  * interrupts.                                  */
307
308                 if (bus_setup_intr(dev, S_IRQ, INTR_TYPE_NET, NULL,
309                         (void(*)(void*)) HFC_INTR, sc, &dummy) != 0)
310                 {
311                         printf("ihfc%d: failed to setup irq.\n", unit);
312                         HFC_END;
313                         return ENXIO;
314                 }
315
316                 flag = 1;
317
318                 if (!HFC_CONTROL(sc, 1))
319                 {
320                         device_set_desc(dev, "TELEINT ISDN SPEED No. 1");
321
322                         HFC_END;
323                         return 0;       /* success */
324                 }
325         }
326
327         ihfc_pnp_detach(dev, flag);
328
329         if (*irq && *++iobase) goto j0; /* try again */
330
331         HFC_END;
332
333         printf("ihfc%d: Chip not found. "
334         "A hard reboot may help!\n", unit);
335
336         return ENXIO;   /* failure */
337 }
338
339 /*---------------------------------------------------------------------------*
340  *      attach ISA "PnP" card
341  *---------------------------------------------------------------------------*/
342 static int
343 ihfc_pnp_attach(device_t dev)
344 {
345         u_int      unit = device_get_unit(dev);         /* get unit     */
346         ihfc_sc_t   *sc = &ihfc_softc[unit];            /* softc        */
347         HFC_VAR;
348  
349         HFC_BEG;
350
351         ihfc_B_linkinit(sc);    /* Setup B-Channel linktabs */
352
353         i4b_l1_mph_status_ind(S_I4BUNIT, STI_ATTACH, S_I4BFLAG, &ihfc_l1mux_func);
354         
355         HFC_INIT(sc, 0, 0, 1);  /* Setup D - Channel */
356
357         HFC_INIT(sc, 2, 0, 0);  /* Init B1 - Channel */
358         HFC_INIT(sc, 4, 0, 0);  /* Init B2 - Channel */
359
360         HFC_END;
361         return 0;       /* success */
362
363         HFC_END;
364         return ENXIO;   /* failure */
365 }
366
367 /*---------------------------------------------------------------------------*
368  *      shutdown for our ISA PnP card
369  *---------------------------------------------------------------------------*/
370 static int
371 ihfc_pnp_shutdown(device_t dev)
372 {
373         u_int      unit = device_get_unit(dev);         /* get unit     */
374         ihfc_sc_t   *sc = &ihfc_softc[unit];            /* softc        */
375         HFC_VAR;
376
377         HFC_BEG;
378
379         if (unit >= IHFC_MAXUNIT)
380         {
381                 printf("ihfc%d: Error, unit %d >= IHFC_MAXUNIT", unit, unit);
382                 goto f0;
383         }
384
385         HFC_CONTROL(sc, 2);     /* shutdown chip */
386
387         HFC_END;
388         return 0;
389   f0:
390         HFC_END;
391         return ENXIO;
392
393 }
394
395 /*---------------------------------------------------------------------------*
396  *      detach for our ISA PnP card
397  *
398  *      flag:   bit[0] set: teardown interrupt handler too
399  *---------------------------------------------------------------------------*/
400 static int
401 ihfc_pnp_detach (device_t dev, u_int flag)
402 {
403         u_int      unit = device_get_unit(dev);         /* get unit     */
404         ihfc_sc_t   *sc = &ihfc_softc[unit];            /* softc        */
405         u_char        i;
406
407         if (unit >= IHFC_MAXUNIT)
408         {
409                 printf("ihfc%d: Error, unit %d >= IHFC_MAXUNIT", unit, unit);
410                 return 0;
411         }
412
413         /* free interrupt resources */
414
415         if(S_IRQ)
416         {
417                 if (flag & 1)
418                 {
419                         /* tear down interrupt handler */
420                         bus_teardown_intr(dev, S_IRQ, (void(*)(void *))HFC_INTR);
421                 }
422
423                 /* free irq */
424                 bus_release_resource(dev, SYS_RES_IRQ, S_IRQRID, S_IRQ);
425
426                 S_IRQRID = 0;
427                 S_IRQ = 0;
428         }
429
430
431         /* free iobases */
432
433         for (i = IHFC_IO_BASES; i--;)
434         {
435                 if(S_IOBASE[i])
436                 {
437                         bus_release_resource(dev, SYS_RES_IOPORT,
438                                         S_IORID[i], S_IOBASE[i]);
439                         S_IORID[i] = 0;
440                         S_IOBASE[i] = 0;                        
441                 }
442         }
443
444         return 0;
445 }