1/* 2 * Copyright (c) 1999 Udo Schweigert. 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 * 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 *--------------------------------------------------------------------------- 36 * 37 * Siemens I-Surf 2.0 PnP specific routines for isic driver 38 * -------------------------------------------------------- 39 * 40 * $Id: isic_isapnp_siemens_isurf.c,v 1.11 2007/10/19 12:00:32 ad Exp $ 41 * 42 * last edit-date: [Fri Jan 5 11:38:29 2001] 43 * 44 *---------------------------------------------------------------------------*/ 45 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 $"); 48 49#include <sys/param.h> 50#include <sys/kernel.h> 51#include <sys/systm.h> 52#include <sys/mbuf.h> 53 54#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000 55#include <sys/callout.h> 56#endif 57 58#if defined(__FreeBSD__) 59#if __FreeBSD__ >= 3 60#include <sys/ioccom.h> 61#else 62#include <sys/ioctl.h> 63#endif 64 65#include <machine/clock.h> 66#include <i386/isa/isa_device.h> 67 68#else 69#include <sys/bus.h> 70#include <sys/device.h> 71#endif 72 73#include <sys/socket.h> 74#include <net/if.h> 75 76#if defined(__FreeBSD__) 77#include <machine/i4b_ioctl.h> 78#else 79#include <netisdn/i4b_ioctl.h> 80#endif 81 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> 87 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> 92 93#if !defined(__FreeBSD__) 94void isic_attach_siemens_isurf(struct isic_softc *sc); 95#endif 96 97/* masks for register encoded in base addr */ 98 99#define SIE_ISURF_BASE_MASK 0x0ffff 100#define SIE_ISURF_OFF_MASK 0xf0000 101 102/* register id's to be encoded in base addr */ 103 104#define SIE_ISURF_IDISAC 0x00000 105#define SIE_ISURF_IDHSCXA 0x10000 106#define SIE_ISURF_IDHSCXB 0x20000 107#define SIE_ISURF_IDIPAC 0x40000 108 109/* offsets from base address */ 110 111#define SIE_ISURF_OFF_ALE 0x00 112#define SIE_ISURF_OFF_RW 0x01 113 114/*---------------------------------------------------------------------------* 115 * Siemens I-Surf 2.0 PnP ISAC get fifo routine 116 *---------------------------------------------------------------------------*/ 117#if defined(__FreeBSD__) 118 119static void 120siemens_isurf_read_fifo(void *buf, const void *base, size_t len) 121{ 122 if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) 123 { 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); 126 } 127 else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) 128 { 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); 131 } 132 else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */ 133 { 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); 136 } 137} 138 139#else 140 141static void 142siemens_isurf_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) 143{ 144 bus_space_tag_t t = sc->sc_maps[0].t; 145 bus_space_handle_t h = sc->sc_maps[0].h; 146 switch (what) { 147 case ISIC_WHAT_ISAC: 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); 150 break; 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); 154 break; 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); 158 break; 159 } 160} 161 162#endif 163 164/*---------------------------------------------------------------------------* 165 * Siemens I-Surf 2.0 PnP ISAC put fifo routine 166 *---------------------------------------------------------------------------*/ 167#if defined(__FreeBSD__) 168 169static void 170siemens_isurf_write_fifo(void *base, const void *buf, size_t len) 171{ 172 if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) 173 { 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); 176 } 177 else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) 178 { 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); 181 } 182 else /* if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) */ 183 { 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); 186 } 187} 188 189#else 190 191static void 192siemens_isurf_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) 193{ 194 bus_space_tag_t t = sc->sc_maps[0].t; 195 bus_space_handle_t h = sc->sc_maps[0].h; 196 switch (what) { 197 case ISIC_WHAT_ISAC: 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); 200 break; 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); 204 break; 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); 208 break; 209 } 210} 211 212#endif 213 214/*---------------------------------------------------------------------------* 215 * Siemens I-Surf 2.0 PnP ISAC put register routine 216 *---------------------------------------------------------------------------*/ 217#if defined(__FreeBSD__) 218 219static void 220siemens_isurf_write_reg(u_char *base, u_int offset, u_int v) 221{ 222 if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) 223 { 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); 226 } 227 else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) 228 { 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); 231 } 232 else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) 233 { 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); 236 } 237 else /* IPAC */ 238 { 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); 241 } 242} 243 244#else 245 246static void 247siemens_isurf_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) 248{ 249 bus_space_tag_t t = sc->sc_maps[0].t; 250 bus_space_handle_t h = sc->sc_maps[0].h; 251 switch (what) { 252 case ISIC_WHAT_ISAC: 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); 255 break; 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); 259 break; 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); 263 break; 264 case ISIC_WHAT_IPAC: 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); 267 break; 268 } 269} 270 271#endif 272 273/*---------------------------------------------------------------------------* 274 * Siemens I-Surf 2.0 PnP ISAC get register routine 275 *---------------------------------------------------------------------------*/ 276#if defined(__FreeBSD__) 277 278static u_char 279siemens_isurf_read_reg(u_char *base, u_int offset) 280{ 281 if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXB) 282 { 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)); 285 } 286 else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDHSCXA) 287 { 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)); 290 } 291 else if(((u_int)base & SIE_ISURF_OFF_MASK) == SIE_ISURF_IDISAC) 292 { 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)); 295 } 296 else /* IPAC */ 297 { 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)); 300 } 301} 302 303#else 304 305static u_int8_t 306siemens_isurf_read_reg(struct isic_softc *sc, int what, bus_size_t offs) 307{ 308 bus_space_tag_t t = sc->sc_maps[0].t; 309 bus_space_handle_t h = sc->sc_maps[0].h; 310 switch (what) { 311 case ISIC_WHAT_ISAC: 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); 320 case ISIC_WHAT_IPAC: 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); 323 } 324 return 0; 325} 326 327#endif 328 329/*---------------------------------------------------------------------------* 330 * isic_probe_siemens_isurf - probe for Siemens I-Surf 2.0 PnP 331 *---------------------------------------------------------------------------*/ 332#if defined(__FreeBSD__) 333 334int 335isic_probe_siemens_isurf(struct isa_device *dev, unsigned int iobase2) 336{ 337 struct isic_softc *sc = &l1_sc[dev->id_unit]; 338 339 /* check max unit range */ 340 341 if(dev->id_unit >= ISIC_MAXUNIT) 342 { 343 printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Siemens I-Surf 2.0 PnP\n", 344 dev->id_unit, dev->id_unit); 345 return(0); 346 } 347 sc->sc_unit = dev->id_unit; 348 349 /* check IRQ validity */ 350 351 switch(ffs(dev->id_irq) - 1) 352 { 353 case 3: 354 case 4: 355 case 5: 356 case 7: 357 case 10: 358 case 11: 359 case 12: 360 case 15: 361 break; 362 363 default: 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); 366 return(0); 367 break; 368 } 369 sc->sc_irq = dev->id_irq; 370 371 /* check if memory addr specified */ 372 373 if(dev->id_maddr) 374 { 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); 377 return(0); 378 } 379 dev->id_msize = 0; 380 381 /* check if we got an iobase */ 382 383 if(!((dev->id_iobase >= 0x100) && (dev->id_iobase <= 0xfffc))) 384 { 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); 387 return(0); 388 } 389 sc->sc_port = dev->id_iobase; 390 391 392 /* setup access routines */ 393 394 sc->clearirq = NULL; 395 sc->readreg = siemens_isurf_read_reg; 396 sc->writereg = siemens_isurf_write_reg; 397 398 sc->readfifo = siemens_isurf_read_fifo; 399 sc->writefifo = siemens_isurf_write_fifo; 400 401 /* setup card type */ 402 403 sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2; 404 405 /* setup IOM bus type */ 406 407 sc->sc_bustyp = BUS_TYPE_IOM2; 408 409 /* setup chip type = IPAC ! */ 410 411 sc->sc_ipac = 1; 412 sc->sc_bfifolen = IPAC_BFIFO_LEN; 413 414 415 return (1); 416} 417 418/*---------------------------------------------------------------------------* 419 * isic_attach_siemens_isurf - attach for Siemens I-Surf 2.0 PnP 420 *---------------------------------------------------------------------------*/ 421int 422isic_attach_siemens_isurf(struct isa_device *dev, unsigned int iobase2) 423{ 424 struct isic_softc *sc = &l1_sc[dev->id_unit]; 425 426 /* setup ISAC and HSCX base addr */ 427 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); 432 433 /* enable hscx/isac irq's */ 434 IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); 435 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 */ 440 441 return(1); 442} 443 444#else 445 446void 447isic_attach_siemens_isurf(struct isic_softc *sc) 448{ 449 /* setup access routines */ 450 451 sc->clearirq = NULL; 452 sc->readreg = siemens_isurf_read_reg; 453 sc->writereg = siemens_isurf_write_reg; 454 455 sc->readfifo = siemens_isurf_read_fifo; 456 sc->writefifo = siemens_isurf_write_fifo; 457 458 /* setup card type */ 459 460 sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2; 461 462 /* setup IOM bus type */ 463 464 sc->sc_bustyp = BUS_TYPE_IOM2; 465 466 /* setup chip type = IPAC ! */ 467 468 sc->sc_ipac = 1; 469 sc->sc_bfifolen = IPAC_BFIFO_LEN; 470 471 /* enable hscx/isac irq's */ 472 473 IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); 474 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 */ 479} 480 481#endif 482