1/* 2 * Copyright (c) 1998 German Tischler. 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 * 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. 18 * 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 29 * SUCH DAMAGE. 30 * 31 *--------------------------------------------------------------------------- 32 * 33 * Card format: 34 * 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 41 * 42 *--------------------------------------------------------------------------- 43 * 44 * isic - I4B Siemens ISDN Chipset Driver for SWS cards 45 * ==================================================== 46 * 47 * EXPERIMENTAL !!!! 48 * ================= 49 * 50 * $Id: isic_isapnp_sws.c,v 1.13 2008/04/08 20:09:27 cegger Exp $ 51 * 52 * last edit-date: [Fri Jan 5 11:38:29 2001] 53 * 54 * -hm adding driver to i4b 55 * -hm adjustments for FreeBSD < 2.2.6, no PnP support yet 56 * 57 *---------------------------------------------------------------------------*/ 58 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 $"); 61 62#include "opt_isicpnp.h" 63#ifdef ISICPNP_SEDLBAUER 64 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 */ 72 73#define SWS_REGS 8 /* we use an area of 8 bytes for io */ 74 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) 80 81#include <sys/param.h> 82#if defined(__FreeBSD__) && __FreeBSD__ >= 3 83#include <sys/ioccom.h> 84#else 85#include <sys/ioctl.h> 86#endif 87#include <sys/kernel.h> 88#include <sys/systm.h> 89#include <sys/mbuf.h> 90 91#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000 92#include <sys/callout.h> 93#endif 94 95#ifdef __FreeBSD__ 96#include <machine/clock.h> 97#include <i386/isa/isa_device.h> 98#else 99#include <sys/bus.h> 100#include <sys/device.h> 101#endif 102 103#include <sys/socket.h> 104#include <net/if.h> 105 106#ifdef __FreeBSD__ 107#include <machine/i4b_debug.h> 108#include <machine/i4b_ioctl.h> 109#else 110#include <netisdn/i4b_debug.h> 111#include <netisdn/i4b_ioctl.h> 112#include <netisdn/i4b_l2.h> 113#endif 114 115#include <dev/ic/isic_l1.h> 116#include <dev/ic/isac.h> 117#include <dev/ic/hscx.h> 118 119#include <netisdn/i4b_global.h> 120#include <netisdn/i4b_l1l2.h> 121#include <netisdn/i4b_mbuf.h> 122 123#ifndef __FreeBSD__ 124static u_int8_t sws_read_reg (struct isic_softc *sc, int what, bus_size_t offs); 125static void sws_write_reg (struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data); 126static void sws_read_fifo (struct isic_softc *sc, int what, void *buf, size_t size); 127static void sws_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size); 128void isic_attach_sws(struct isic_softc *sc); 129#endif 130 131/*---------------------------------------------------------------------------* 132 * SWS P&P ISAC get fifo routine 133 *---------------------------------------------------------------------------*/ 134 135#ifdef __FreeBSD__ 136 137static void 138sws_read_fifo(void *buf, const void *base, size_t len) 139{ 140 outb(SWS_IDO(base),SWS_REG(base,0)); 141 insb(SWS_ADDR(base),buf,len); 142} 143 144#else 145 146static void 147sws_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) 148{ 149 bus_space_tag_t t = sc->sc_maps[0].t; 150 bus_space_handle_t h = sc->sc_maps[0].h; 151 switch (what) { 152 case ISIC_WHAT_ISAC: 153 bus_space_write_1(t, h, SWS_RW, 0); 154 bus_space_read_multi_1(t, h, SWS_ISAC, buf, size); 155 break; 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); 159 break; 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); 163 break; 164 } 165} 166 167#endif 168 169/*---------------------------------------------------------------------------* 170 * SWS P&P ISAC put fifo routine 171 *---------------------------------------------------------------------------*/ 172 173#ifdef __FreeBSD__ 174 175static void 176sws_write_fifo(void *base, const void *buf, size_t len) 177{ 178 outb (SWS_IDO(base),SWS_REG(base,0)); 179 outsb(SWS_ADDR(base),buf,len); 180} 181 182#else 183 184static void 185sws_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) 186{ 187 bus_space_tag_t t = sc->sc_maps[0].t; 188 bus_space_handle_t h = sc->sc_maps[0].h; 189 switch (what) { 190 case ISIC_WHAT_ISAC: 191 bus_space_write_1(t, h, SWS_RW, 0); 192 bus_space_write_multi_1(t, h, SWS_ISAC, buf, size); 193 break; 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); 197 break; 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); 201 break; 202 } 203} 204 205#endif 206 207/*---------------------------------------------------------------------------* 208 * SWS P&P ISAC put register routine 209 *---------------------------------------------------------------------------*/ 210 211#ifdef __FreeBSD__ 212 213static void 214sws_write_reg(u_char *base, u_int offset, u_int v) 215{ 216 outb(SWS_IDO(base),SWS_REG(base,offset)); 217 outb(SWS_ADDR(base),v); 218} 219 220#else 221 222static void 223sws_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) 224{ 225 bus_space_tag_t t = sc->sc_maps[0].t; 226 bus_space_handle_t h = sc->sc_maps[0].h; 227 switch (what) { 228 case ISIC_WHAT_ISAC: 229 bus_space_write_1(t, h, SWS_RW, offs); 230 bus_space_write_1(t, h, SWS_ISAC, data); 231 break; 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); 235 break; 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); 239 break; 240 } 241} 242 243#endif 244 245/*---------------------------------------------------------------------------* 246 * SWS P&P ISAC get register routine 247 *---------------------------------------------------------------------------*/ 248#ifdef __FreeBSD__ 249 250static u_char 251sws_read_reg(u_char *base, u_int offset) 252{ 253 outb(SWS_IDO(base),SWS_REG(base,offset)); 254 return inb(SWS_ADDR(base)); 255} 256 257#else 258 259static u_int8_t 260sws_read_reg(struct isic_softc *sc, int what, bus_size_t offs) 261{ 262 bus_space_tag_t t = sc->sc_maps[0].t; 263 bus_space_handle_t h = sc->sc_maps[0].h; 264 switch (what) { 265 case ISIC_WHAT_ISAC: 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); 274 } 275 return 0; 276} 277 278#endif 279 280#ifdef __FreeBSD__ 281 282/* attach callback routine */ 283 284int 285isic_attach_sws(struct isa_device *dev) 286{ 287 struct isic_softc *sc = &l1_sc[dev->id_unit]; 288 289 /* fill in isic_softc structure */ 290 291 sc->readreg = sws_read_reg; 292 sc->writereg = sws_write_reg; 293 sc->readfifo = sws_read_fifo; 294 sc->writefifo = sws_write_fifo; 295 sc->clearirq = NULL; 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; 301 sc->sc_ipac = 0; 302 sc->sc_bfifolen = HSCX_FIFO_LEN; 303 dev->id_msize = 0; 304 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); 308 309 /* 310 * Read HSCX A/B VSTR. Expected value for the SWS PnP card is 311 * 0x05 ( = version 2.1 ) in the least significant bits. 312 */ 313 314 if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || 315 ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) 316 { 317 printf("isic%d: HSCX VSTR test failed for SWS PnP\n", 318 dev->id_unit); 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)); 323 return (0); 324 } 325 326 /* reset card */ 327 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); 332 333 return(1); 334} 335 336#else /* !__FreeBSD__ */ 337 338void 339isic_attach_sws(struct isic_softc *sc) 340{ 341 /* setup access routines */ 342 343 sc->readreg = sws_read_reg; 344 sc->writereg = sws_write_reg; 345 346 sc->readfifo = sws_read_fifo; 347 sc->writefifo = sws_write_fifo; 348 349 /* setup card type */ 350 351 sc->sc_cardtyp = CARD_TYPEP_SWS; 352 353 /* setup IOM bus type */ 354 355 sc->sc_bustyp = BUS_TYPE_IOM2; 356 357 sc->sc_ipac = 0; 358 sc->sc_bfifolen = HSCX_FIFO_LEN; 359 360 /* 361 * Read HSCX A/B VSTR. Expected value for the SWS PnP card is 362 * 0x05 ( = version 2.1 ) in the least significant bits. 363 */ 364 365 if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || 366 ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) 367 { 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)); 374 return; 375 } 376 377 /* reset card */ 378 { 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); 385 } 386} 387 388#endif /* !__FreeBSD__ */ 389 390#endif /* ISICPNP_SEDLBAUER */ 391