2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
25 *---------------------------------------------------------------------------
27 * i4b_drn_ngo.c - Dr. Neuhaus Niccy GO@ and SAGEM Cybermod
28 * --------------------------------------------------------
30 * $Id: isic_isapnp_drn_ngo.c,v 1.10 2007/10/19 12:00:32 ad Exp $
32 * last edit-date: [Fri Jan 5 11:38:29 2001]
34 *---------------------------------------------------------------------------*/
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: isic_isapnp_drn_ngo.c,v 1.9 2007/03/04 06:02:13 christos Exp $");
39 #include "opt_isicpnp.h"
40 #ifdef ISICPNP_DRN_NGO
42 #include <sys/param.h>
43 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
44 #include <sys/ioccom.h>
46 #include <sys/ioctl.h>
48 #include <sys/kernel.h>
49 #include <sys/systm.h>
52 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
53 #include <sys/callout.h>
57 #include <machine/clock.h>
58 #include <i386/isa/isa_device.h>
61 #include <sys/device.h>
64 #include <sys/socket.h>
68 #include <machine/i4b_debug.h>
69 #include <machine/i4b_ioctl.h>
71 #include <netisdn/i4b_debug.h>
72 #include <netisdn/i4b_ioctl.h>
75 #include <netisdn/i4b_global.h>
76 #include <netisdn/i4b_l2.h>
77 #include <netisdn/i4b_l1l2.h>
79 #include <dev/ic/isic_l1.h>
80 #include <dev/ic/isac.h>
81 #include <dev/ic/hscx.h>
83 /*---------------------------------------------------------------------------*
84 * Niccy GO@ definitions
86 * the card uses 2 i/o addressranges each using 2 bytes
89 * offset 0 - ISAC dataregister
90 * offset 1 - HSCX dataregister
92 * offset 0 - ISAC addressregister
93 * offset 1 - HSCX addressregister
95 * to access an ISAC/HSCX register, you have to write the register
96 * number into the ISAC or HSCX addressregister and then read/write
97 * data for the ISAC/HSCX register into/from the corresponding
100 * Thanks to Klaus Muehle of Dr. Neuhaus Telekommunikation for giving
101 * out this information!
103 *---------------------------------------------------------------------------*/
104 #define NICCY_PORT_MIN 0x200
105 #define NICCY_PORT_MAX 0x3e0
107 #define HSCX_ABIT 0x1000 /* flag, HSCX A is meant */
108 #define HSCX_BBIT 0x2000 /* flag, HSCX B is meant */
110 #define HSCX_BOFF 0x40
112 #define ADDR_OFF 2 /* address register range offset XXX */
132 /*---------------------------------------------------------------------------*
133 * Dr. Neuhaus Niccy GO@ read fifo routine
134 *---------------------------------------------------------------------------*/
136 drnngo_read_fifo(void *buf
, const void *base
, size_t len
)
143 if((u_int
)base
& HSCX_ABIT
)
145 (u_int
)base
&= ~HSCX_ABIT
;
146 (u_int
)data
= ((u_int
)base
+ HSCX_DATA
);
147 (u_int
)base
+= (ADDR_OFF
+ HSCX_ADDR
);
150 printf("GO/A/frd: base=0x%x, data=0x%x, len=%d\n", base
, data
, len
);
153 else if((u_int
)base
& HSCX_BBIT
)
155 (u_int
)base
&= ~HSCX_BBIT
;
156 (u_int
)data
= ((u_int
)base
+ HSCX_DATA
);
157 (u_int
)base
+= (ADDR_OFF
+ HSCX_ADDR
);
160 printf("GO/B/frd: base=0x%x, data=0x%x, len=%d\n", base
, data
, len
);
165 (u_int
)data
= ((u_int
)base
+ ISAC_DATA
);
166 (u_int
)base
+= (ADDR_OFF
+ ISAC_ADDR
);
169 printf("GO/I/frd: base=0x%x, data=0x%x, len=%d\n", base
, data
, len
);
173 for(;len
> 0; len
--, offset
++)
175 outb((int)base
, (u_char
)offset
);
176 *((u_char
*)buf
+ offset
) = inb((int)data
);
182 /*---------------------------------------------------------------------------*
183 * Dr. Neuhaus Niccy GO@ write fifo routine
184 *---------------------------------------------------------------------------*/
186 drnngo_write_fifo(void *base
, const void *buf
, size_t len
)
193 if((u_int
)base
& HSCX_ABIT
)
195 (u_int
)base
&= ~HSCX_ABIT
;
196 (u_int
)data
= ((u_int
)base
+ HSCX_DATA
);
197 (u_int
)base
+= (ADDR_OFF
+ HSCX_ADDR
);
200 printf("GO/A/fwr: base=0x%x, data=0x%x, len=%d\n", base
, data
, len
);
203 else if((u_int
)base
& HSCX_BBIT
)
205 (u_int
)base
&= ~HSCX_BBIT
;
206 (u_int
)data
= ((u_int
)base
+ HSCX_DATA
);
207 (u_int
)base
+= (ADDR_OFF
+ HSCX_ADDR
);
210 printf("GO/B/fwr: base=0x%x, data=0x%x, len=%d\n", base
, data
, len
);
215 (u_int
)data
= ((u_int
)base
+ ISAC_DATA
);
216 (u_int
)base
+= (ADDR_OFF
+ ISAC_ADDR
);
219 printf("GO/I/fwr: base=0x%x, data=0x%x, len=%d\n", base
, data
, len
);
223 for(;len
> 0; len
--, offset
++)
225 outb((int)base
, (u_char
)offset
);
226 outb((int)data
, *((u_char
*)buf
+ offset
));
232 /*---------------------------------------------------------------------------*
233 * Dr. Neuhaus Niccy GO@ write register routine
234 *---------------------------------------------------------------------------*/
236 drnngo_write_reg(u_char
*base
, u_int offset
, u_int v
)
239 if((u_int
)base
& HSCX_ABIT
)
241 (u_int
)base
&= ~HSCX_ABIT
;
242 outb((int)base
+ ADDR_OFF
+ HSCX_ADDR
, (u_char
)offset
);
243 outb((int)base
+ HSCX_DATA
, (u_char
)v
);
245 printf("GO/A/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
246 (int)base
+ ADDR_OFF
+ HSCX_ADDR
, (int)base
+ HSCX_DATA
,
247 (u_char
)offset
, (u_char
)v
);
250 else if((u_int
)base
& HSCX_BBIT
)
252 (u_int
)base
&= ~HSCX_BBIT
;
253 outb((int)base
+ ADDR_OFF
+ HSCX_ADDR
, (u_char
)(offset
+ HSCX_BOFF
));
254 outb((int)base
+ HSCX_DATA
, (u_char
)v
);
256 printf("GO/B/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
257 (int)base
+ ADDR_OFF
+ HSCX_ADDR
, (int)base
+ HSCX_DATA
,
258 (u_char
)(offset
+ HSCX_BOFF
), (u_char
)v
);
263 outb((int)base
+ ADDR_OFF
+ ISAC_ADDR
, (u_char
)offset
);
264 outb((int)base
+ ISAC_DATA
, (u_char
)v
);
266 printf("GO/I/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
267 (int)base
+ ADDR_OFF
+ ISAC_ADDR
, (int)base
+ ISAC_DATA
,
268 (u_char
)offset
, (u_char
)v
);
274 /*---------------------------------------------------------------------------*
275 * Dr. Neuhaus Niccy GO@ read register routine
276 *---------------------------------------------------------------------------*/
278 drnngo_read_reg(u_char
*base
, u_int offset
)
283 if((u_int
)base
& HSCX_ABIT
)
285 (u_int
)base
&= ~HSCX_ABIT
;
286 outb((int)base
+ ADDR_OFF
+ HSCX_ADDR
, (u_char
)offset
);
287 val
= inb((int)base
+ HSCX_DATA
);
289 printf("GO/A/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
290 (int)base
+ ADDR_OFF
+ HSCX_ADDR
, (int)base
+ HSCX_DATA
,
291 (u_char
)offset
, (u_char
)val
);
294 else if((u_int
)base
& HSCX_BBIT
)
296 (u_int
)base
&= ~HSCX_BBIT
;
297 outb((int)base
+ ADDR_OFF
+ HSCX_ADDR
, (u_char
)(offset
+ HSCX_BOFF
));
298 val
= inb((int)base
+ HSCX_DATA
);
300 printf("GO/B/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
301 (int)base
+ ADDR_OFF
+ HSCX_ADDR
, (int)base
+ HSCX_DATA
,
302 (u_char
)(offset
+ HSCX_BOFF
), (u_char
)val
);
307 outb((int)base
+ ADDR_OFF
+ ISAC_ADDR
, (u_char
)offset
);
308 val
= inb((int)base
+ ISAC_DATA
);
310 printf("GO/I/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n",
311 (int)base
+ ADDR_OFF
+ ISAC_ADDR
, (int)base
+ ISAC_DATA
,
312 (u_char
)offset
, (u_char
)val
);
319 /*---------------------------------------------------------------------------*
320 * isic_probe_drnngo - probe for Dr. Neuhaus Niccy GO@
321 *---------------------------------------------------------------------------*/
323 isic_probe_drnngo(struct isa_device
*dev
, unsigned int iobase2
)
325 struct isic_softc
*sc
= &l1_sc
[dev
->id_unit
];
327 /* check max unit range */
329 if(dev
->id_unit
>= ISIC_MAXUNIT
)
331 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dr. Neuhaus Niccy GO@!\n",
332 dev
->id_unit
, dev
->id_unit
);
335 sc
->sc_unit
= dev
->id_unit
;
337 /* check IRQ validity */
339 switch(ffs(dev
->id_irq
)-1)
352 printf("isic%d: Error, invalid IRQ [%d] specified for Dr. Neuhaus Niccy GO@!\n",
353 dev
->id_unit
, ffs(dev
->id_irq
)-1);
357 sc
->sc_irq
= dev
->id_irq
;
359 /* check if memory addr specified */
363 printf("isic%d: Error, mem addr 0x%lx specified for Dr. Neuhaus Niccy GO@!\n",
364 dev
->id_unit
, (u_long
)dev
->id_maddr
);
369 /* check if we got an iobase */
371 if(dev
->id_iobase
< NICCY_PORT_MIN
|| dev
->id_iobase
> NICCY_PORT_MAX
)
373 printf("isic%d: Error, invalid iobase 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
374 dev
->id_unit
, dev
->id_iobase
);
377 sc
->sc_port
= dev
->id_iobase
;
381 printf("isic%d: Error, iobase2 is 0 for Dr. Neuhaus Niccy GO@!\n",
386 if(iobase2
< NICCY_PORT_MIN
|| iobase2
> NICCY_PORT_MAX
)
388 printf("isic%d: Error, invalid port1 0x%x specified for Dr. Neuhaus Niccy GO@!\n",
389 dev
->id_unit
, iobase2
);
393 /*XXX*/ if((dev
->id_iobase
+ 2) != iobase2
)
395 printf("isic%d: Error, port1 must be (port0+2) for Dr.Neuhaus Niccy GO@!\n",
400 /* setup ISAC access routines */
403 sc
->readreg
= drnngo_read_reg
;
404 sc
->writereg
= drnngo_write_reg
;
406 sc
->readfifo
= drnngo_read_fifo
;
407 sc
->writefifo
= drnngo_write_fifo
;
409 /* setup card type */
411 sc
->sc_cardtyp
= CARD_TYPEP_DRNNGO
;
413 /* setup IOM bus type */
415 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
418 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
420 /* setup ISAC and HSCX base addr */
422 ISAC_BASE
= (void *)dev
->id_iobase
;
423 HSCX_A_BASE
= (void *)(((u_int
)dev
->id_iobase
) | HSCX_ABIT
);
424 HSCX_B_BASE
= (void *)(((u_int
)dev
->id_iobase
) | HSCX_BBIT
);
427 * Read HSCX A/B VSTR. Expected value for Dr. Neuhaus Niccy GO@ based
428 * boards is 0x05 in the least significant bits.
431 if( ((HSCX_READ(0, H_VSTR
) & 0xf) != 0x5) ||
432 ((HSCX_READ(1, H_VSTR
) & 0xf) != 0x5) )
434 printf("isic%d: HSCX VSTR test failed for Dr. Neuhaus Niccy GO@\n",
436 printf("isic%d: HSC0: VSTR: %#x\n",
437 dev
->id_unit
, HSCX_READ(0, H_VSTR
));
438 printf("isic%d: HSC1: VSTR: %#x\n",
439 dev
->id_unit
, HSCX_READ(1, H_VSTR
));
446 /*---------------------------------------------------------------------------*
447 * isic_attach_drnngo - attach Dr. Neuhaus Niccy GO@
448 *---------------------------------------------------------------------------*/
450 isic_attach_drnngo(struct isa_device
*dev
, unsigned int iobase2
)
457 static u_int8_t
drnngo_read_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
);
458 static void drnngo_write_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
, u_int8_t data
);
459 static void drnngo_read_fifo(struct isic_softc
*sc
, int what
, void *buf
, size_t size
);
460 static void drnngo_write_fifo(struct isic_softc
*sc
, int what
, const void *data
, size_t size
);
461 void isic_attach_drnngo(struct isic_softc
*sc
);
464 * Mapping from "what" parameter to offsets into the io map
467 bus_size_t oa
, /* address register offset */
468 od
, /* data register offset */
469 or; /* additional chip register offset */
472 { ISAC_ADDR
, ISAC_DATA
, 0 }, /* ISAC access */
473 { HSCX_ADDR
, HSCX_DATA
, 0 }, /* HSCX A access */
474 { HSCX_ADDR
, HSCX_DATA
, HSCX_BOFF
} /* HSCX B access */
478 drnngo_read_fifo(struct isic_softc
*sc
, int what
, void *buf
, size_t size
)
480 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
481 bus_space_handle_t hd
= sc
->sc_maps
[0].h
, ha
= sc
->sc_maps
[1].h
;
482 bus_space_write_1(t
, ha
, offset
[what
].oa
, offset
[what
].or);
483 bus_space_read_multi_1(t
, hd
, offset
[what
].od
, buf
, size
);
487 drnngo_write_fifo(struct isic_softc
*sc
, int what
, const void *buf
, size_t size
)
489 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
490 bus_space_handle_t hd
= sc
->sc_maps
[0].h
, ha
= sc
->sc_maps
[1].h
;
491 bus_space_write_1(t
, ha
, offset
[what
].oa
, offset
[what
].or);
492 bus_space_write_multi_1(t
, hd
, offset
[what
].od
, buf
, size
);
496 drnngo_write_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
, u_int8_t data
)
498 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
499 bus_space_handle_t hd
= sc
->sc_maps
[0].h
, ha
= sc
->sc_maps
[1].h
;
500 bus_space_write_1(t
, ha
, offset
[what
].oa
, offs
+offset
[what
].or);
501 bus_space_write_1(t
, hd
, offset
[what
].od
, data
);
505 drnngo_read_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
)
507 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
508 bus_space_handle_t hd
= sc
->sc_maps
[0].h
, ha
= sc
->sc_maps
[1].h
;
509 bus_space_write_1(t
, ha
, offset
[what
].oa
, offs
+offset
[what
].or);
510 return bus_space_read_1(t
, hd
, offset
[what
].od
);
514 isic_attach_drnngo(struct isic_softc
*sc
)
516 /* setup access routines */
519 sc
->readreg
= drnngo_read_reg
;
520 sc
->writereg
= drnngo_write_reg
;
522 sc
->readfifo
= drnngo_read_fifo
;
523 sc
->writefifo
= drnngo_write_fifo
;
525 /* setup card type */
527 sc
->sc_cardtyp
= CARD_TYPEP_DRNNGO
;
529 /* setup IOM bus type */
531 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
534 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
539 #endif /* ISICPNP_DRN_NGO */