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