2 * Copyright (c) 1999 Udo Schweigert. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
31 *---------------------------------------------------------------------------
32 * Based on ELSA Quickstep 1000pro PCI driver (i4b_elsa_qs1p.c)
33 *---------------------------------------------------------------------------
34 * In case of trouble please contact Udo Schweigert <ust@cert.siemens.de>
35 *---------------------------------------------------------------------------
37 * Siemens I-Surf 2.0 PnP specific routines for isic driver
38 * --------------------------------------------------------
40 * $Id: isic_isapnp_siemens_isurf.c,v 1.11 2007/10/19 12:00:32 ad Exp $
42 * last edit-date: [Fri Jan 5 11:38:29 2001]
44 *---------------------------------------------------------------------------*/
46 #include <sys/cdefs.h>
47 __KERNEL_RCSID(0, "$NetBSD: isic_isapnp_siemens_isurf.c,v 1.10 2007/03/04 06:02:13 christos Exp $");
49 #include <sys/param.h>
50 #include <sys/kernel.h>
51 #include <sys/systm.h>
54 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
55 #include <sys/callout.h>
58 #if defined(__FreeBSD__)
60 #include <sys/ioccom.h>
62 #include <sys/ioctl.h>
65 #include <machine/clock.h>
66 #include <i386/isa/isa_device.h>
70 #include <sys/device.h>
73 #include <sys/socket.h>
76 #if defined(__FreeBSD__)
77 #include <machine/i4b_ioctl.h>
79 #include <netisdn/i4b_ioctl.h>
82 #include <netisdn/i4b_global.h>
83 #include <netisdn/i4b_debug.h>
84 #include <netisdn/i4b_l2.h>
85 #include <netisdn/i4b_l1l2.h>
86 #include <netisdn/i4b_mbuf.h>
88 #include <dev/ic/isic_l1.h>
89 #include <dev/ic/ipac.h>
90 #include <dev/ic/isac.h>
91 #include <dev/ic/hscx.h>
93 #if !defined(__FreeBSD__)
94 void isic_attach_siemens_isurf(struct isic_softc
*sc
);
97 /* masks for register encoded in base addr */
99 #define SIE_ISURF_BASE_MASK 0x0ffff
100 #define SIE_ISURF_OFF_MASK 0xf0000
102 /* register id's to be encoded in base addr */
104 #define SIE_ISURF_IDISAC 0x00000
105 #define SIE_ISURF_IDHSCXA 0x10000
106 #define SIE_ISURF_IDHSCXB 0x20000
107 #define SIE_ISURF_IDIPAC 0x40000
109 /* offsets from base address */
111 #define SIE_ISURF_OFF_ALE 0x00
112 #define SIE_ISURF_OFF_RW 0x01
114 /*---------------------------------------------------------------------------*
115 * Siemens I-Surf 2.0 PnP ISAC get fifo routine
116 *---------------------------------------------------------------------------*/
117 #if defined(__FreeBSD__)
120 siemens_isurf_read_fifo(void *buf
, const void *base
, size_t len
)
122 if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXB
)
124 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, IPAC_HSCXB_OFF
);
125 insb((((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
), (u_char
*)buf
, (u_int
)len
);
127 else if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXA
)
129 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, IPAC_HSCXA_OFF
);
130 insb((((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
), (u_char
*)buf
, (u_int
)len
);
132 else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */
134 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, IPAC_ISAC_OFF
);
135 insb((((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
), (u_char
*)buf
, (u_int
)len
);
142 siemens_isurf_read_fifo(struct isic_softc
*sc
, int what
, void *buf
, size_t size
)
144 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
145 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
148 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_ISAC_OFF
);
149 bus_space_read_multi_1(t
, h
, SIE_ISURF_OFF_RW
, buf
, size
);
151 case ISIC_WHAT_HSCXA
:
152 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXA_OFF
);
153 bus_space_read_multi_1(t
, h
, SIE_ISURF_OFF_RW
, buf
, size
);
155 case ISIC_WHAT_HSCXB
:
156 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXB_OFF
);
157 bus_space_read_multi_1(t
, h
, SIE_ISURF_OFF_RW
, buf
, size
);
164 /*---------------------------------------------------------------------------*
165 * Siemens I-Surf 2.0 PnP ISAC put fifo routine
166 *---------------------------------------------------------------------------*/
167 #if defined(__FreeBSD__)
170 siemens_isurf_write_fifo(void *base
, const void *buf
, size_t len
)
172 if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXB
)
174 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, IPAC_HSCXB_OFF
);
175 outsb((((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
), (const u_char
*)buf
, (u_int
)len
);
177 else if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXA
)
179 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, IPAC_HSCXA_OFF
);
180 outsb((((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
), (const u_char
*)buf
, (u_int
)len
);
182 else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */
184 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, IPAC_ISAC_OFF
);
185 outsb((((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
), (const u_char
*)buf
, (u_int
)len
);
192 siemens_isurf_write_fifo(struct isic_softc
*sc
, int what
, const void *buf
, size_t size
)
194 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
195 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
198 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_ISAC_OFF
);
199 bus_space_write_multi_1(t
, h
, SIE_ISURF_OFF_RW
, buf
, size
);
201 case ISIC_WHAT_HSCXA
:
202 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXA_OFF
);
203 bus_space_write_multi_1(t
, h
, SIE_ISURF_OFF_RW
, buf
, size
);
205 case ISIC_WHAT_HSCXB
:
206 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXB_OFF
);
207 bus_space_write_multi_1(t
, h
, SIE_ISURF_OFF_RW
, buf
, size
);
214 /*---------------------------------------------------------------------------*
215 * Siemens I-Surf 2.0 PnP ISAC put register routine
216 *---------------------------------------------------------------------------*/
217 #if defined(__FreeBSD__)
220 siemens_isurf_write_reg(u_char
*base
, u_int offset
, u_int v
)
222 if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXB
)
224 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_HSCXB_OFF
));
225 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
, (u_char
)v
);
227 else if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXA
)
229 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_HSCXA_OFF
));
230 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
, (u_char
)v
);
232 else if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDISAC
)
234 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_ISAC_OFF
));
235 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
, (u_char
)v
);
239 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_IPAC_OFF
));
240 outb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
, (u_char
)v
);
247 siemens_isurf_write_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
, u_int8_t data
)
249 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
250 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
253 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_ISAC_OFF
+offs
);
254 bus_space_write_1(t
, h
, SIE_ISURF_OFF_RW
, data
);
256 case ISIC_WHAT_HSCXA
:
257 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXA_OFF
+offs
);
258 bus_space_write_1(t
, h
, SIE_ISURF_OFF_RW
, data
);
260 case ISIC_WHAT_HSCXB
:
261 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXB_OFF
+offs
);
262 bus_space_write_1(t
, h
, SIE_ISURF_OFF_RW
, data
);
265 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_IPAC_OFF
+offs
);
266 bus_space_write_1(t
, h
, SIE_ISURF_OFF_RW
, data
);
273 /*---------------------------------------------------------------------------*
274 * Siemens I-Surf 2.0 PnP ISAC get register routine
275 *---------------------------------------------------------------------------*/
276 #if defined(__FreeBSD__)
279 siemens_isurf_read_reg(u_char
*base
, u_int offset
)
281 if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXB
)
283 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_HSCXB_OFF
));
284 return(inb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
));
286 else if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDHSCXA
)
288 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_HSCXA_OFF
));
289 return(inb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
));
291 else if(((u_int
)base
& SIE_ISURF_OFF_MASK
) == SIE_ISURF_IDISAC
)
293 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_ISAC_OFF
));
294 return(inb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
));
298 outb((u_int
)((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_ALE
, (u_char
)(offset
+IPAC_IPAC_OFF
));
299 return(inb(((u_int
)base
& SIE_ISURF_BASE_MASK
) + SIE_ISURF_OFF_RW
));
306 siemens_isurf_read_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
)
308 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
309 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
312 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_ISAC_OFF
+offs
);
313 return bus_space_read_1(t
, h
, SIE_ISURF_OFF_RW
);
314 case ISIC_WHAT_HSCXA
:
315 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXA_OFF
+offs
);
316 return bus_space_read_1(t
, h
, SIE_ISURF_OFF_RW
);
317 case ISIC_WHAT_HSCXB
:
318 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_HSCXB_OFF
+offs
);
319 return bus_space_read_1(t
, h
, SIE_ISURF_OFF_RW
);
321 bus_space_write_1(t
, h
, SIE_ISURF_OFF_ALE
, IPAC_IPAC_OFF
+offs
);
322 return bus_space_read_1(t
, h
, SIE_ISURF_OFF_RW
);
329 /*---------------------------------------------------------------------------*
330 * isic_probe_siemens_isurf - probe for Siemens I-Surf 2.0 PnP
331 *---------------------------------------------------------------------------*/
332 #if defined(__FreeBSD__)
335 isic_probe_siemens_isurf(struct isa_device
*dev
, unsigned int iobase2
)
337 struct isic_softc
*sc
= &l1_sc
[dev
->id_unit
];
339 /* check max unit range */
341 if(dev
->id_unit
>= ISIC_MAXUNIT
)
343 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Siemens I-Surf 2.0 PnP\n",
344 dev
->id_unit
, dev
->id_unit
);
347 sc
->sc_unit
= dev
->id_unit
;
349 /* check IRQ validity */
351 switch(ffs(dev
->id_irq
) - 1)
364 printf("isic%d: Error, invalid IRQ [%d] specified for Siemens I-Surf 2.0 PnP!\n",
365 dev
->id_unit
, ffs(dev
->id_irq
)-1);
369 sc
->sc_irq
= dev
->id_irq
;
371 /* check if memory addr specified */
375 printf("isic%d: Error, mem addr 0x%lx specified for Siemens I-Surf 2.0 PnP!\n",
376 dev
->id_unit
, (u_long
)dev
->id_maddr
);
381 /* check if we got an iobase */
383 if(!((dev
->id_iobase
>= 0x100) && (dev
->id_iobase
<= 0xfffc)))
385 printf("isic%d: Error, invalid iobase 0x%x specified for Siemens I-Surf 2.0 PnP!\n",
386 dev
->id_unit
, dev
->id_iobase
);
389 sc
->sc_port
= dev
->id_iobase
;
392 /* setup access routines */
395 sc
->readreg
= siemens_isurf_read_reg
;
396 sc
->writereg
= siemens_isurf_write_reg
;
398 sc
->readfifo
= siemens_isurf_read_fifo
;
399 sc
->writefifo
= siemens_isurf_write_fifo
;
401 /* setup card type */
403 sc
->sc_cardtyp
= CARD_TYPEP_SIE_ISURF2
;
405 /* setup IOM bus type */
407 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
409 /* setup chip type = IPAC ! */
412 sc
->sc_bfifolen
= IPAC_BFIFO_LEN
;
418 /*---------------------------------------------------------------------------*
419 * isic_attach_siemens_isurf - attach for Siemens I-Surf 2.0 PnP
420 *---------------------------------------------------------------------------*/
422 isic_attach_siemens_isurf(struct isa_device
*dev
, unsigned int iobase2
)
424 struct isic_softc
*sc
= &l1_sc
[dev
->id_unit
];
426 /* setup ISAC and HSCX base addr */
428 ISAC_BASE
= (void *) ((u_int
)sc
->sc_port
| SIE_ISURF_IDISAC
);
429 HSCX_A_BASE
= (void *) ((u_int
)sc
->sc_port
| SIE_ISURF_IDHSCXA
);
430 HSCX_B_BASE
= (void *) ((u_int
)sc
->sc_port
| SIE_ISURF_IDHSCXB
);
431 IPAC_BASE
= (void *) ((u_int
)sc
->sc_port
| SIE_ISURF_IDIPAC
);
433 /* enable hscx/isac irq's */
434 IPAC_WRITE(IPAC_MASK
, (IPAC_MASK_INT1
| IPAC_MASK_INT0
));
436 IPAC_WRITE(IPAC_ACFG
, 0); /* outputs are open drain */
437 IPAC_WRITE(IPAC_AOE
, /* aux 5..2 are inputs, 7, 6 outputs */
438 (IPAC_AOE_OE5
| IPAC_AOE_OE4
| IPAC_AOE_OE3
| IPAC_AOE_OE2
));
439 IPAC_WRITE(IPAC_ATX
, 0xff); /* set all output lines high */
447 isic_attach_siemens_isurf(struct isic_softc
*sc
)
449 /* setup access routines */
452 sc
->readreg
= siemens_isurf_read_reg
;
453 sc
->writereg
= siemens_isurf_write_reg
;
455 sc
->readfifo
= siemens_isurf_read_fifo
;
456 sc
->writefifo
= siemens_isurf_write_fifo
;
458 /* setup card type */
460 sc
->sc_cardtyp
= CARD_TYPEP_SIE_ISURF2
;
462 /* setup IOM bus type */
464 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
466 /* setup chip type = IPAC ! */
469 sc
->sc_bfifolen
= IPAC_BFIFO_LEN
;
471 /* enable hscx/isac irq's */
473 IPAC_WRITE(IPAC_MASK
, (IPAC_MASK_INT1
| IPAC_MASK_INT0
));
475 IPAC_WRITE(IPAC_ACFG
, 0); /* outputs are open drain */
476 IPAC_WRITE(IPAC_AOE
, /* aux 5..2 are inputs, 7, 6 outputs */
477 (IPAC_AOE_OE5
| IPAC_AOE_OE4
| IPAC_AOE_OE3
| IPAC_AOE_OE2
));
478 IPAC_WRITE(IPAC_ATX
, 0xff); /* set all output lines high */