2 * Copyright (c) 1998 German Tischler. 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 *---------------------------------------------------------------------------
35 * iobase + 0 : reset on (0x03)
36 * iobase + 1 : reset off (0x0)
37 * iobase + 2 : isac read/write
38 * iobase + 3 : hscx read/write ( offset 0-0x3f hscx0 ,
39 * offset 0x40-0x7f hscx1 )
40 * iobase + 4 : offset for indirect addressing
42 *---------------------------------------------------------------------------
44 * isic - I4B Siemens ISDN Chipset Driver for SWS cards
45 * ====================================================
50 * $Id: isic_isapnp_sws.c,v 1.13 2008/04/08 20:09:27 cegger Exp $
52 * last edit-date: [Fri Jan 5 11:38:29 2001]
54 * -hm adding driver to i4b
55 * -hm adjustments for FreeBSD < 2.2.6, no PnP support yet
57 *---------------------------------------------------------------------------*/
59 #include <sys/cdefs.h>
60 __KERNEL_RCSID(0, "$NetBSD: isic_isapnp_sws.c,v 1.12 2007/10/19 12:00:32 ad Exp $");
62 #include "opt_isicpnp.h"
63 #ifdef ISICPNP_SEDLBAUER
65 #define SWS_RESON 0 /* reset on */
66 #define SWS_RESOFF 1 /* reset off */
67 #define SWS_ISAC 2 /* ISAC */
68 #define SWS_HSCX0 3 /* HSCX0 */
69 #define SWS_RW 4 /* indirect access register */
70 #define SWS_HSCX1 5 /* this is for fakeing that we mean hscx1, though */
71 /* access is done through hscx0 */
73 #define SWS_REGS 8 /* we use an area of 8 bytes for io */
75 #define SWS_BASE(X) ((unsigned int)X&~(SWS_REGS-1))
76 #define SWS_PART(X) ((unsigned int)X& (SWS_REGS-1))
77 #define SWS_ADDR(X) ((SWS_PART(X) == SWS_ISAC) ? (SWS_BASE(X)+SWS_ISAC) : (SWS_BASE(X)+SWS_HSCX0) )
78 #define SWS_REG(X,Y) ((SWS_PART(X) != SWS_HSCX1) ? Y : (Y+0x40) )
79 #define SWS_IDO(X) (SWS_BASE(X)+SWS_RW)
81 #include <sys/param.h>
82 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
83 #include <sys/ioccom.h>
85 #include <sys/ioctl.h>
87 #include <sys/kernel.h>
88 #include <sys/systm.h>
91 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
92 #include <sys/callout.h>
96 #include <machine/clock.h>
97 #include <i386/isa/isa_device.h>
100 #include <sys/device.h>
103 #include <sys/socket.h>
107 #include <machine/i4b_debug.h>
108 #include <machine/i4b_ioctl.h>
110 #include <netisdn/i4b_debug.h>
111 #include <netisdn/i4b_ioctl.h>
112 #include <netisdn/i4b_l2.h>
115 #include <dev/ic/isic_l1.h>
116 #include <dev/ic/isac.h>
117 #include <dev/ic/hscx.h>
119 #include <netisdn/i4b_global.h>
120 #include <netisdn/i4b_l1l2.h>
121 #include <netisdn/i4b_mbuf.h>
124 static u_int8_t
sws_read_reg (struct isic_softc
*sc
, int what
, bus_size_t offs
);
125 static void sws_write_reg (struct isic_softc
*sc
, int what
, bus_size_t offs
, u_int8_t data
);
126 static void sws_read_fifo (struct isic_softc
*sc
, int what
, void *buf
, size_t size
);
127 static void sws_write_fifo(struct isic_softc
*sc
, int what
, const void *data
, size_t size
);
128 void isic_attach_sws(struct isic_softc
*sc
);
131 /*---------------------------------------------------------------------------*
132 * SWS P&P ISAC get fifo routine
133 *---------------------------------------------------------------------------*/
138 sws_read_fifo(void *buf
, const void *base
, size_t len
)
140 outb(SWS_IDO(base
),SWS_REG(base
,0));
141 insb(SWS_ADDR(base
),buf
,len
);
147 sws_read_fifo(struct isic_softc
*sc
, int what
, void *buf
, size_t size
)
149 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
150 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
153 bus_space_write_1(t
, h
, SWS_RW
, 0);
154 bus_space_read_multi_1(t
, h
, SWS_ISAC
, buf
, size
);
156 case ISIC_WHAT_HSCXA
:
157 bus_space_write_1(t
, h
, SWS_RW
, 0);
158 bus_space_read_multi_1(t
, h
, SWS_HSCX0
, buf
, size
);
160 case ISIC_WHAT_HSCXB
:
161 bus_space_write_1(t
, h
, SWS_RW
, 0x40);
162 bus_space_read_multi_1(t
, h
, SWS_HSCX0
, buf
, size
);
169 /*---------------------------------------------------------------------------*
170 * SWS P&P ISAC put fifo routine
171 *---------------------------------------------------------------------------*/
176 sws_write_fifo(void *base
, const void *buf
, size_t len
)
178 outb (SWS_IDO(base
),SWS_REG(base
,0));
179 outsb(SWS_ADDR(base
),buf
,len
);
185 sws_write_fifo(struct isic_softc
*sc
, int what
, const void *buf
, size_t size
)
187 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
188 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
191 bus_space_write_1(t
, h
, SWS_RW
, 0);
192 bus_space_write_multi_1(t
, h
, SWS_ISAC
, buf
, size
);
194 case ISIC_WHAT_HSCXA
:
195 bus_space_write_1(t
, h
, SWS_RW
, 0);
196 bus_space_write_multi_1(t
, h
, SWS_HSCX0
, buf
, size
);
198 case ISIC_WHAT_HSCXB
:
199 bus_space_write_1(t
, h
, SWS_RW
, 0x40);
200 bus_space_write_multi_1(t
, h
, SWS_HSCX0
, buf
, size
);
207 /*---------------------------------------------------------------------------*
208 * SWS P&P ISAC put register routine
209 *---------------------------------------------------------------------------*/
214 sws_write_reg(u_char
*base
, u_int offset
, u_int v
)
216 outb(SWS_IDO(base
),SWS_REG(base
,offset
));
217 outb(SWS_ADDR(base
),v
);
223 sws_write_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
, u_int8_t data
)
225 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
226 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
229 bus_space_write_1(t
, h
, SWS_RW
, offs
);
230 bus_space_write_1(t
, h
, SWS_ISAC
, data
);
232 case ISIC_WHAT_HSCXA
:
233 bus_space_write_1(t
, h
, SWS_RW
, offs
);
234 bus_space_write_1(t
, h
, SWS_HSCX0
, data
);
236 case ISIC_WHAT_HSCXB
:
237 bus_space_write_1(t
, h
, SWS_RW
, 0x40+offs
);
238 bus_space_write_1(t
, h
, SWS_HSCX0
, data
);
245 /*---------------------------------------------------------------------------*
246 * SWS P&P ISAC get register routine
247 *---------------------------------------------------------------------------*/
251 sws_read_reg(u_char
*base
, u_int offset
)
253 outb(SWS_IDO(base
),SWS_REG(base
,offset
));
254 return inb(SWS_ADDR(base
));
260 sws_read_reg(struct isic_softc
*sc
, int what
, bus_size_t offs
)
262 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
263 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
266 bus_space_write_1(t
, h
, SWS_RW
, offs
);
267 return bus_space_read_1(t
, h
, SWS_ISAC
);
268 case ISIC_WHAT_HSCXA
:
269 bus_space_write_1(t
, h
, SWS_RW
, offs
);
270 return bus_space_read_1(t
, h
, SWS_HSCX0
);
271 case ISIC_WHAT_HSCXB
:
272 bus_space_write_1(t
, h
, SWS_RW
, 0x40+offs
);
273 return bus_space_read_1(t
, h
, SWS_HSCX0
);
282 /* attach callback routine */
285 isic_attach_sws(struct isa_device
*dev
)
287 struct isic_softc
*sc
= &l1_sc
[dev
->id_unit
];
289 /* fill in isic_softc structure */
291 sc
->readreg
= sws_read_reg
;
292 sc
->writereg
= sws_write_reg
;
293 sc
->readfifo
= sws_read_fifo
;
294 sc
->writefifo
= sws_write_fifo
;
296 sc
->sc_unit
= dev
->id_unit
;
297 sc
->sc_irq
= dev
->id_irq
;
298 sc
->sc_port
= dev
->id_iobase
;
299 sc
->sc_cardtyp
= CARD_TYPEP_SWS
;
300 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
302 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
305 ISAC_BASE
= (void *) (((u_int
) sc
->sc_port
) + SWS_ISAC
);
306 HSCX_A_BASE
= (void *) (((u_int
) sc
->sc_port
) + SWS_HSCX0
);
307 HSCX_B_BASE
= (void *) (((u_int
) sc
->sc_port
) + SWS_HSCX1
);
310 * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
311 * 0x05 ( = version 2.1 ) in the least significant bits.
314 if( ((HSCX_READ(0, H_VSTR
) & 0xf) != 0x5) ||
315 ((HSCX_READ(1, H_VSTR
) & 0xf) != 0x5) )
317 printf("isic%d: HSCX VSTR test failed for SWS PnP\n",
319 printf("isic%d: HSC0: VSTR: %#x\n",
320 dev
->id_unit
, HSCX_READ(0, H_VSTR
));
321 printf("isic%d: HSC1: VSTR: %#x\n",
322 dev
->id_unit
, HSCX_READ(1, H_VSTR
));
328 outb( ((u_int
) sc
->sc_port
) + SWS_RESON
, 0x3);
329 DELAY(SEC_DELAY
/ 5);
330 outb( ((u_int
) sc
->sc_port
) + SWS_RESOFF
, 0);
331 DELAY(SEC_DELAY
/ 5);
336 #else /* !__FreeBSD__ */
339 isic_attach_sws(struct isic_softc
*sc
)
341 /* setup access routines */
343 sc
->readreg
= sws_read_reg
;
344 sc
->writereg
= sws_write_reg
;
346 sc
->readfifo
= sws_read_fifo
;
347 sc
->writefifo
= sws_write_fifo
;
349 /* setup card type */
351 sc
->sc_cardtyp
= CARD_TYPEP_SWS
;
353 /* setup IOM bus type */
355 sc
->sc_bustyp
= BUS_TYPE_IOM2
;
358 sc
->sc_bfifolen
= HSCX_FIFO_LEN
;
361 * Read HSCX A/B VSTR. Expected value for the SWS PnP card is
362 * 0x05 ( = version 2.1 ) in the least significant bits.
365 if( ((HSCX_READ(0, H_VSTR
) & 0xf) != 0x5) ||
366 ((HSCX_READ(1, H_VSTR
) & 0xf) != 0x5) )
368 printf("%s: HSCX VSTR test failed for SWS PnP\n",
369 device_xname(&sc
->sc_dev
));
370 printf("%s: HSC0: VSTR: %#x\n",
371 device_xname(&sc
->sc_dev
), HSCX_READ(0, H_VSTR
));
372 printf("%s: HSC1: VSTR: %#x\n",
373 device_xname(&sc
->sc_dev
), HSCX_READ(1, H_VSTR
));
379 bus_space_tag_t t
= sc
->sc_maps
[0].t
;
380 bus_space_handle_t h
= sc
->sc_maps
[0].h
;
381 bus_space_write_1(t
, h
, SWS_RESON
, 0x3);
382 DELAY(SEC_DELAY
/ 5);
383 bus_space_write_1(t
, h
, SWS_RESOFF
, 0);
384 DELAY(SEC_DELAY
/ 5);
388 #endif /* !__FreeBSD__ */
390 #endif /* ISICPNP_SEDLBAUER */