1 /* $NetBSD: if_ntwoc_isa.c,v 1.3 2002/01/07 21:47:09 thorpej Exp $ */ 2 /* 3 * Copyright (c) 1999 Christian E. Hopps 4 * Copyright (c) 1996 John Hay. 5 * Copyright (c) 1996 SDL Communications, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: if_ntwoc_isa.c,v 1.3 2002/01/07 21:47:09 thorpej Exp $ 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: if_ntwoc_isa.c,v 1.3 2002/01/07 21:47:09 thorpej Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/device.h> 41 #include <sys/mbuf.h> 42 #include <sys/socket.h> 43 44 #include <net/if.h> 45 46 #include <machine/cpu.h> 47 #include <machine/bus.h> 48 #include <machine/intr.h> 49 50 #include <dev/isa/isavar.h> 51 52 #include <dev/ic/hd64570reg.h> 53 #include <dev/ic/hd64570var.h> 54 55 #include <dev/isa/if_ntwoc_isareg.h> 56 57 #if 1 58 #define NTWO_DEBUG 59 #endif 60 61 #ifdef NTWO_DEBUG 62 #define NTWO_DPRINTF(x) printf x 63 #else 64 #define NTWO_DPRINTF(x) 65 #endif 66 67 #if __NetBSD_Version__ >= 104160000 68 static void ntwoc_isa_config_interrupts __P((struct device *)); 69 #else 70 #define SCA_BASECLOCK 9830400 71 #endif 72 73 /* hard core 16k for now */ 74 #define NTWOC_WIN_SIZE 0x4000 75 76 struct ntwoc_isa_softc { 77 /* Generic device stuff */ 78 struct device sc_dev; /* Common to all devices */ 79 80 /* PCI chipset glue */ 81 void *sc_ih; /* Interrupt handler */ 82 isa_chipset_tag_t sc_ic; /* ISA chipset handle */ 83 84 struct sca_softc sc_sca; /* the SCA itself */ 85 }; 86 87 static int ntwoc_isa_probe __P((struct device *, struct cfdata *, void *)); 88 static void ntwoc_isa_attach __P((struct device *, struct device *, void *)); 89 90 static void ntwoc_isa_clock_callback __P((void *, int, int)); 91 static void ntwoc_isa_dtr_callback __P((void *, int, int)); 92 static int ntwoc_isa_intr __P((void *)); 93 static void ntwoc_isa_get_clock __P((struct sca_port *, u_int8_t, u_int8_t, 94 u_int8_t, u_int8_t)); 95 static void ntwoc_isa_setup_memory(struct sca_softc *sc); 96 static void ntwoc_isa_shutdown __P((void *sc)); 97 98 struct cfattach ntwoc_isa_ca = { 99 sizeof(struct ntwoc_isa_softc), ntwoc_isa_probe, ntwoc_isa_attach, 100 }; 101 102 /* 103 * Names for daughter card types. These match the NTWOC_DB_* defines. 104 */ 105 char *ntwoc_db_names[] = { 106 "V.35", "Unknown 0x01", "Test", "Unknown 0x03", 107 "RS232", "Unknown 0x05", "RS422", "None" 108 }; 109 110 /* some weird offset XXX */ 111 #define SCA_REG(r) (((r) & 0xf) + (((r) & 0xf0) << 6)) 112 113 /* 114 * functions that read and write to the sca registers 115 */ 116 static void 117 ntwoc_isa_sca_write_1(struct sca_softc *sc, u_int reg, u_int8_t val) 118 { 119 bus_space_write_1(sc->sc_iot, sc->scu_sca_ioh[(reg & 0xf0) >> 4], 120 (reg & 0xf), val); 121 } 122 123 static void 124 ntwoc_isa_sca_write_2(struct sca_softc *sc, u_int reg, u_int16_t val) 125 { 126 bus_space_write_2(sc->sc_iot, sc->scu_sca_ioh[(reg & 0xf0) >> 4], 127 (reg & 0xf), val); 128 } 129 130 static u_int8_t 131 ntwoc_isa_sca_read_1(struct sca_softc *sc, u_int reg) 132 { 133 return 134 bus_space_read_1(sc->sc_iot, sc->scu_sca_ioh[(reg & 0xf0) >> 4], 135 (reg & 0xf)); 136 } 137 138 static u_int16_t 139 ntwoc_isa_sca_read_2(struct sca_softc *sc, u_int reg) 140 { 141 return 142 bus_space_read_2(sc->sc_iot, sc->scu_sca_ioh[(reg & 0xf0) >> 4], 143 (reg & 0xf)); 144 } 145 146 /* 147 * set the correct window/page 148 */ 149 static void 150 ntwoc_isa_set_page(struct sca_softc *sca, bus_addr_t addr) 151 { 152 u_int8_t psr; 153 154 /* get old psr value replace old window with new */ 155 psr = bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PSR); 156 psr &= ~NTWOC_PG_MSK; 157 psr |= ((addr >> sca->scu_pageshift) & NTWOC_PG_MSK); 158 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PSR, psr); 159 } 160 161 /* 162 * enable the memory window 163 */ 164 static void 165 ntwoc_isa_set_on(struct sca_softc *sca) 166 { 167 u_int8_t pcr; 168 169 /* get old value and add window enable */ 170 pcr = bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR); 171 pcr |= NTWOC_PCR_MEM_WIN; 172 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR, pcr); 173 } 174 175 /* 176 * turn off memory window 177 */ 178 static void 179 ntwoc_isa_set_off(struct sca_softc *sca) 180 { 181 u_int8_t pcr; 182 183 /* get old value and remove window enable */ 184 pcr = bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR); 185 pcr &= ~NTWOC_PCR_MEM_WIN; 186 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR, pcr); 187 } 188 189 static int 190 ntwoc_isa_probe(struct device *parent, struct cfdata *match, void *aux) 191 { 192 struct isa_attach_args *ia; 193 bus_space_tag_t iot, memt; 194 bus_space_handle_t ioh, memh, sca_ioh[16]; 195 int i, tmp, dbg, rv; 196 int gotmem, gotsca[16]; 197 u_int32_t ioport; 198 199 ia = (struct isa_attach_args *)aux; 200 iot = ia->ia_iot; 201 memt = ia->ia_memt; 202 203 if (ia->ia_nio < 1) 204 return (0); 205 if (ia->ia_niomem < 1) 206 return (0); 207 if (ia->ia_nirq < 1) 208 return (0); 209 210 if (ISA_DIRECT_CONFIG(ia)) 211 return (0); 212 213 memset(gotsca, 0, sizeof(gotsca)); 214 gotmem = rv = 0; 215 dbg = 0; 216 217 /* disallow wildcarded I/O base */ 218 if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT) { 219 printf("ntwoc_isa_probe: must specify port address\n"); 220 return (0); 221 } 222 223 if (ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT) { 224 printf("ntwoc_isa_probe: must specify irq\n"); 225 return (0); 226 } 227 228 if (ia->ia_iomem[0].ir_addr == ISACF_IOMEM_DEFAULT) { 229 printf("ntwoc_isa_probe: must specify iomem\n"); 230 return (0); 231 } 232 233 tmp = (match->cf_flags & NTWOC_FLAGS_NPORT_MASK) + 1; 234 if (tmp < 1 || tmp > 2) { 235 printf("ntwoc_isa_probe: only 1 or 2 ports allowed\n"); 236 return (0); 237 } 238 239 /* map the isa io addresses */ 240 if ((tmp = bus_space_map(iot, ia->ia_io[0].ir_addr, 241 NTWOC_SRC_IOPORT_SIZE, 0, &ioh))) { 242 printf("ntwoc_isa_probe: mapping port 0x%x sz %d failed: %d\n", 243 ia->ia_io[0].ir_addr, NTWOC_SRC_IOPORT_SIZE, tmp); 244 return (0); 245 } 246 247 ioport = ia->ia_io[0].ir_addr + 0x8000; 248 for (i = 0; i < 16; ioport += (0x10 << 6), i++) { 249 /* map the isa io addresses */ 250 if ((tmp = bus_space_map(iot, ioport, 16, 0, &sca_ioh[i]))) { 251 printf( 252 "ntwoc_isa_probe: mapping sca 0x%x sz %d failed: %d\n", 253 ioport, 16, tmp); 254 goto out; 255 } 256 gotsca[i] = 1; 257 } 258 259 /* map the isa memory addresses */ 260 /* XXX we really want the user to select this */ 261 if ((tmp = bus_space_map(ia->ia_memt, ia->ia_iomem[0].ir_addr, 262 NTWOC_WIN_SIZE, 0, &memh))) { 263 printf("ntwoc_isa_probe: mapping mem 0x%x sz %d failed: %d\n", 264 ia->ia_iomem[0].ir_addr, NTWOC_WIN_SIZE, tmp); 265 goto out; 266 } 267 gotmem = 1; 268 269 /* turn off the card */ 270 bus_space_write_1(iot, ioh, NTWOC_PCR, 0); 271 272 /* 273 * Next, we'll test the Base Address Register to retension of 274 * data... ... seeing if we're *really* talking to an N2. 275 */ 276 for (i = 0; i < 0x100; i++) { 277 bus_space_write_1(iot, ioh, NTWOC_BAR, i); 278 (void)bus_space_read_1(iot, ioh, NTWOC_PCR); 279 if (bus_space_read_1(iot, ioh, NTWOC_BAR) != i) { 280 printf("ntwoc_isa_probe failed (BAR %x, %x)\n", i, tmp); 281 goto out; 282 } 283 } 284 285 /* XXX XXX update the calls to SCA_REG to use our mapping */ 286 287 /* 288 * Now see if we can see the SCA. 289 */ 290 bus_space_write_1(iot, ioh, NTWOC_PCR, 291 NTWOC_PCR_SCARUN | bus_space_read_1(iot, ioh, NTWOC_PCR)); 292 bus_space_write_1(iot, sca_ioh[0], SCA_REG(SCA_WCRL), 0); 293 bus_space_write_1(iot, sca_ioh[0], SCA_REG(SCA_WCRM), 0); 294 bus_space_write_1(iot, sca_ioh[0], SCA_REG(SCA_WCRH), 0); 295 bus_space_write_1(iot, sca_ioh[0], SCA_REG(SCA_PCR), 0); 296 297 bus_space_write_1(iot, sca_ioh[0], SCA_REG(SCA_TMC0), 0); 298 (void)bus_space_read_1(iot, ioh, 0); 299 if ((tmp = bus_space_read_1(iot, sca_ioh[0], SCA_REG(SCA_TMC0))) != 0) { 300 printf("ntwoc_isa_probe: Error reading SCA (TMC0 0, %x)\n", 301 tmp); 302 goto out; 303 } 304 305 bus_space_write_1(iot, sca_ioh[0], SCA_REG(SCA_TMC0), 0x5A); 306 (void)bus_space_read_1(iot, ioh, 0); 307 308 tmp = bus_space_read_1(iot, sca_ioh[0], SCA_REG(SCA_TMC0)); 309 if (tmp != 0x5A) { 310 printf("ntwoc_isa_probe: Error reading SCA (TMC0 5A, %x)\n", 311 tmp); 312 goto out; 313 } 314 315 bus_space_write_2(iot, sca_ioh[0], SCA_REG(SCA_CDAL0), 0); 316 (void)bus_space_read_1(iot, ioh, 0); 317 tmp = bus_space_read_2(iot, sca_ioh[0], SCA_REG(SCA_CDAL0)); 318 if (tmp != 0) { 319 printf("ntwoc_isa_probe: Error reading SCA (CDAL0 0, %x)\n", 320 tmp); 321 goto out; 322 } 323 324 bus_space_write_2(iot, sca_ioh[0], SCA_REG(SCA_CDAL0), 0x55AA); 325 (void)bus_space_read_1(iot, ioh, 0); 326 tmp = bus_space_read_2(iot, sca_ioh[0], SCA_REG(SCA_CDAL0)); 327 if (tmp != 0x55AA) { 328 printf("ntwoc_isa_probe: Error reading SCA (CDAL0 55AA, %x)\n", 329 tmp); 330 goto out; 331 } 332 333 /* 334 * I had a weird card that didn't function correctly on a certain 335 * newer MB. I suspect it was the whacky port addresses. 336 * The following correctly failed it. 337 */ 338 bus_space_write_2(iot, sca_ioh[0], SCA_REG(SCA_TCNTL0), 0x0); 339 (void)bus_space_read_1(iot, ioh, 0); 340 tmp = bus_space_read_2(iot, sca_ioh[0], SCA_REG(SCA_TCNTL0)); 341 if (tmp != 0) { 342 printf("ntwoc_isa_probe: Error reading SCA (TCNTL0 0, %x)\n", 343 tmp); 344 goto out; 345 } 346 347 bus_space_write_2(iot, sca_ioh[0], SCA_REG(SCA_TCNTL0), 0x55AA); 348 (void)bus_space_read_1(iot, ioh, 0); 349 tmp = bus_space_read_2(iot, sca_ioh[0], SCA_REG(SCA_TCNTL0)); 350 if (tmp != 0x55AA) { 351 printf("ntwoc_isa_probe: Error reading SCA (TCNTL0 55AA, %x)\n", 352 tmp); 353 goto out; 354 } 355 356 ia->ia_nio = 1; 357 ia->ia_io[0].ir_size = NTWOC_SRC_IOPORT_SIZE; 358 359 ia->ia_niomem = 1; 360 ia->ia_iomem[0].ir_size = NTWOC_WIN_SIZE; 361 362 ia->ia_nirq = 1; 363 364 ia->ia_ndrq = 0; 365 366 rv = 1; 367 out: 368 /* turn off the card */ 369 bus_space_write_1(iot, ioh, NTWOC_PCR, 0); 370 371 if (gotmem) 372 bus_space_unmap(memt, memh, NTWOC_WIN_SIZE); 373 for (i = 0; i < 16; i++) { 374 if (gotsca[i]) 375 bus_space_unmap(iot, sca_ioh[i], 16); 376 } 377 bus_space_unmap(iot, ioh, NTWOC_SRC_IOPORT_SIZE); 378 return (rv); 379 } 380 381 /* 382 * we win! attach the card 383 */ 384 static void 385 ntwoc_isa_attach(struct device *parent, struct device *self, void *aux) 386 { 387 struct ntwoc_isa_softc *sc; 388 struct isa_attach_args *ia; 389 struct sca_softc *sca; 390 bus_addr_t addr; 391 u_int8_t rdiv, tdiv, tmc; 392 u_int32_t flags, ioport; 393 u_int16_t tmp; 394 int i, dbg, pgs, rv; 395 396 ia = (struct isa_attach_args *)aux; 397 sc = (struct ntwoc_isa_softc *)self; 398 sca = &sc->sc_sca; 399 dbg = 0; 400 401 printf(": N2 Serial Interface\n"); 402 flags = sc->sc_dev.dv_cfdata->cf_flags; 403 404 sc->sc_ic = ia->ia_ic; 405 sca->sc_parent = &sc->sc_dev; 406 sca->sc_numports = (flags & NTWOC_FLAGS_NPORT_MASK) + 1; 407 sca->sc_usedma = 0; 408 sca->sc_aux = sc; 409 sca->sc_dtr_callback = ntwoc_isa_dtr_callback; 410 sca->sc_clock_callback = ntwoc_isa_clock_callback; 411 sca->sc_read_1 = ntwoc_isa_sca_read_1; 412 sca->sc_read_2 = ntwoc_isa_sca_read_2; 413 sca->sc_write_1 = ntwoc_isa_sca_write_1; 414 sca->sc_write_2 = ntwoc_isa_sca_write_2; 415 sca->scu_set_page = ntwoc_isa_set_page; 416 sca->scu_page_on = ntwoc_isa_set_on; 417 sca->scu_page_off = ntwoc_isa_set_off; 418 419 /* map the io */ 420 sca->sc_iot = ia->ia_iot; 421 if ((rv = bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, 422 NTWOC_SRC_IOPORT_SIZE, 0, &sca->sc_ioh))) { 423 printf("%s: can't map io 0x%x sz %d, %d\n", 424 sc->sc_dev.dv_xname, ia->ia_io[0].ir_addr, 425 NTWOC_SRC_IOPORT_SIZE, rv); 426 return; 427 } 428 429 /* support weird mapping (they used this to avoid 10-bit aliasing) */ 430 ioport = ia->ia_io[0].ir_addr + 0x8000; 431 for (i = 0; i < 16; ioport += (0x10 << 6), i++) { 432 /* map the isa io addresses */ 433 if ((tmp = bus_space_map(ia->ia_iot, ioport, 16, 0, 434 &sca->scu_sca_ioh[i]))) { 435 printf("%s: mapping sca 0x%x sz %d failed: %d\n", 436 sc->sc_dev.dv_xname, ioport, 16, tmp); 437 return; 438 } 439 } 440 441 /* map the isa memory */ 442 sca->scu_memt = ia->ia_memt; 443 sca->scu_pagesize = 0x4000; /* force 16k for now */ 444 if (sca->scu_pagesize < 0x8000) { 445 /* round down to 16k */ 446 sca->scu_pagesize = 0x4000; 447 sca->scu_pageshift = 14; 448 tmp = NTWOC_PSR_WIN_16K; 449 } else if (sca->scu_pagesize < 0x10000) { 450 /* round down to 32k */ 451 sca->scu_pagesize = 0x8000; 452 sca->scu_pageshift = 15; 453 tmp = NTWOC_PSR_WIN_32K; 454 } else if (sca->scu_pagesize < 0x20000) { 455 /* round down to 64k */ 456 sca->scu_pagesize = 0x10000; 457 sca->scu_pageshift = 16; 458 tmp = NTWOC_PSR_WIN_64K; 459 } else { 460 sca->scu_pagesize = 0x20000; 461 sca->scu_pageshift = 17; 462 tmp = NTWOC_PSR_WIN_128K; 463 } 464 sca->scu_pagemask = sca->scu_pagesize - 1; 465 if ((rv = bus_space_map(ia->ia_memt, ia->ia_iomem[0].ir_addr, 466 sca->scu_pagesize, 0, &sca->scu_memh))) { 467 printf("%s: can't map mem 0x%x sz %ld, %d\n", 468 sc->sc_dev.dv_xname, ia->ia_iomem[0].ir_addr, 469 sca->scu_pagesize, rv); 470 return; 471 } 472 473 /* turn the card on!! */ 474 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR, 475 bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR) 476 | NTWOC_PCR_SCARUN); 477 478 /* set the window size to 16k */ 479 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PSR, tmp); 480 481 /* reset mcr */ 482 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_MCR, 483 NTWOC_MCR_DTR0 | NTWOC_MCR_DTR1 | NTWOC_MCR_TE0 | NTWOC_MCR_TE1); 484 485 486 /* allow for address above 1M and 16 bit i/o */ 487 #if 0 488 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR, 489 bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR) 490 | NTWOC_PCR_EN_VPM | NTWOC_PCR_ISA16); 491 #endif 492 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR, 493 bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR) 494 | NTWOC_PCR_ISA16); 495 496 /* program the card with the io address */ 497 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR, 498 ((ia->ia_iomem[0].ir_addr >> 16) & NTWOC_PCR_16M_SEL) 499 | 500 (bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PCR) 501 & ~NTWOC_PCR_16M_SEL)); 502 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_BAR, 503 (ia->ia_iomem[0].ir_addr >> 12)); 504 505 /* enable the memory window */ 506 ntwoc_isa_set_on(sca); 507 508 /* 509 * write a magic value into each possible page of memory 510 * incrementing by our window size 511 */ 512 addr = 0; 513 for (i = 0; i <= NTWOC_PSR_PG_SEL; addr += sca->scu_pagesize, i++) { 514 /* select the page */ 515 ntwoc_isa_set_page(sca, addr); 516 bus_space_write_2(sca->scu_memt, sca->scu_memh, 0, 0xAA55); 517 } 518 519 /* 520 * go back through pages and verify that value is different 521 * after writing to previous page 522 */ 523 addr = 0; 524 for (i = 0; i <= NTWOC_PSR_PG_SEL; addr += sca->scu_pagesize, i++) { 525 ntwoc_isa_set_page(sca, addr); 526 527 tmp = bus_space_read_2(sca->scu_memt, sca->scu_memh, 0); 528 if (tmp != 0xAA55) 529 break; 530 531 /* write a different value into this page now */ 532 bus_space_write_2(sca->scu_memt, sca->scu_memh, 0, i); 533 } 534 sca->scu_npages = pgs = i; /* final count of 16K pages */ 535 536 /* erase the pages */ 537 addr = 0; 538 for (i = 0; i <= pgs; addr += sca->scu_pagesize, i++) { 539 ntwoc_isa_set_page(sca, addr); 540 bus_space_set_region_1(sca->scu_memt, sca->scu_memh, 0, 0, 541 sca->scu_pagesize); 542 } 543 544 #if 0 545 printf("%s: sca port 0x%x-0x%x dpram %ldk %d serial port%s\n", 546 sc->sc_dev.dv_xname, ia->ia_io[0].ir_addr | 0x8000, 547 (ia->ia_io[0].ir_addr | 0x8000) + NTWOC_SRC_ASIC_SIZE - 1, 548 pgs * (sca->scu_pagesize / 1024), sca->sc_numports, 549 (sca->sc_numports > 1 ? "s" : "")); 550 #else 551 printf("%s: dpram %ldk %d serial port%s\n", 552 sc->sc_dev.dv_xname, pgs * (sca->scu_pagesize / 1024), 553 sca->sc_numports, (sca->sc_numports > 1 ? "s" : "")); 554 #endif 555 556 /* disable the memory window */ 557 ntwoc_isa_set_off(sca); 558 559 /* enabled sca dma */ 560 bus_space_write_1(sca->sc_iot, sca->sc_ioh, NTWOC_PSR, 561 bus_space_read_1(sca->sc_iot, sca->sc_ioh, NTWOC_PSR) 562 | NTWOC_PSR_EN_SCA_DMA); 563 564 /* now establish our irq -- perhaps sanity check the value */ 565 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 566 IST_EDGE, IPL_NET, ntwoc_isa_intr, sc); 567 if (sc->sc_ih == NULL) { 568 printf("%s: can't establish interrupt\n", 569 sc->sc_dev.dv_xname); 570 return; 571 } 572 573 /* make sure we have 2 pages for each port */ 574 if (pgs < 2 * sca->sc_numports) { 575 printf("%s: %d less than required pages of memory of %d\n", 576 sc->sc_dev.dv_xname, pgs, 2 * sca->sc_numports); 577 return; 578 } 579 580 /* sca_get_base_clock(sca); */ 581 582 /* 583 * get clock information from user 584 */ 585 rdiv = (flags & NTWOC_FLAGS_RXDIV_MASK) >> NTWOC_FLAGS_RXDIV_SHIFT; 586 if (rdiv > 9) 587 panic("bad rx divisor in flags"); 588 589 tdiv = (flags & NTWOC_FLAGS_TXDIV_MASK) >> NTWOC_FLAGS_TXDIV_SHIFT; 590 if (tdiv > 9) 591 panic("bad tx divisor in flags"); 592 tmc = (flags & NTWOC_FLAGS_TMC_MASK) >> NTWOC_FLAGS_TMC_SHIFT; 593 594 ntwoc_isa_get_clock(&sca->sc_ports[0], 595 flags & NTWOC_FLAGS_CLK0_MASK, tmc, rdiv, tdiv); 596 if (sca->sc_numports > 1) 597 ntwoc_isa_get_clock(&sca->sc_ports[1], 598 (flags & NTWOC_FLAGS_CLK1_MASK) >> NTWOC_FLAGS_CLK1_SHIFT, 599 tmc, rdiv, tdiv); 600 601 ntwoc_isa_setup_memory(sca); 602 603 sca_init(sca); 604 605 /* attach configured ports */ 606 sca_port_attach(sca, 0); 607 if (sca->sc_numports == 2) 608 sca_port_attach(sca, 1); 609 610 /* 611 * Add shutdown hook so that DMA is disabled prior to reboot. Not 612 * doing do could allow DMA to corrupt kernel memory during the 613 * reboot before the driver initializes. 614 */ 615 shutdownhook_establish(ntwoc_isa_shutdown, sc); 616 617 #if __NetBSD_Version__ >= 104160000 618 /* 619 * defer getting the base clock until interrupts are enabled 620 * (and thus we have microtime()) 621 */ 622 config_interrupts(self, ntwoc_isa_config_interrupts); 623 #else 624 /* no callback pre 1.4-mumble */ 625 sca->sc_baseclock = SCA_BASECLOCK; 626 sca_print_clock_info(&sc->sc_sca); 627 #endif 628 } 629 630 /* 631 * extract the clock information for a port from the flags field 632 */ 633 static void 634 ntwoc_isa_get_clock(struct sca_port *scp, u_int8_t flags, u_int8_t tmc, 635 u_int8_t rdiv, u_int8_t tdiv) 636 { 637 scp->sp_eclock = 638 (flags & NTWOC_FLAGS_ECLOCK_MASK) >> NTWOC_FLAGS_ECLOCK_SHIFT; 639 scp->sp_rxs = rdiv; 640 scp->sp_txs = tdiv; 641 scp->sp_tmc = tmc; 642 643 /* get rx source */ 644 switch ((flags & NTWOC_FLAGS_RXS_MASK) >> NTWOC_FLAGS_RXS_SHIFT) { 645 case NTWOC_FLAGS_RXS_LINE: 646 scp->sp_rxs = 0; 647 break; 648 case NTWOC_FLAGS_RXS_LINE_SN: 649 scp->sp_rxs |= SCA_RXS_CLK_LINE_SN; 650 break; 651 case NTWOC_FLAGS_RXS_INTERNAL: 652 scp->sp_rxs |= SCA_RXS_CLK_INTERNAL; 653 break; 654 case NTWOC_FLAGS_RXS_ADPLL_OUT: 655 scp->sp_rxs |= SCA_RXS_CLK_ADPLL_OUT; 656 break; 657 case NTWOC_FLAGS_RXS_ADPLL_IN: 658 scp->sp_rxs |= SCA_RXS_CLK_ADPLL_IN; 659 break; 660 default: 661 panic("bad rx source in flags"); 662 } 663 664 /* get tx source */ 665 switch ((flags & NTWOC_FLAGS_TXS_MASK) >> NTWOC_FLAGS_TXS_SHIFT) { 666 case NTWOC_FLAGS_TXS_LINE: 667 scp->sp_txs = 0; 668 break; 669 case NTWOC_FLAGS_TXS_INTERNAL: 670 scp->sp_txs |= SCA_TXS_CLK_INTERNAL; 671 break; 672 case NTWOC_FLAGS_TXS_RXCLOCK: 673 scp->sp_txs |= SCA_TXS_CLK_RXCLK; 674 break; 675 default: 676 panic("bad rx source in flags"); 677 } 678 } 679 680 681 static int 682 ntwoc_isa_intr(void *arg) 683 { 684 struct ntwoc_isa_softc *sc = (struct ntwoc_isa_softc *)arg; 685 686 return sca_hardintr(&sc->sc_sca); 687 } 688 689 /* 690 * shut down interrupts and DMA, so we don't trash the kernel on warm 691 * boot. Also, lower DTR on each port and disable card interrupts. 692 */ 693 static void 694 ntwoc_isa_shutdown(void *aux) 695 { 696 struct ntwoc_isa_softc *sc = aux; 697 u_int16_t mcr; 698 699 /* 700 * shut down the SCA ports 701 */ 702 sca_shutdown(&sc->sc_sca); 703 704 /* 705 * lower DTR on both ports 706 */ 707 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 708 mcr |= (NTWOC_MCR_DTR0 | NTWOC_MCR_DTR1); 709 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 710 } 711 712 static void 713 ntwoc_isa_dtr_callback(void *aux, int port, int state) 714 { 715 struct ntwoc_isa_softc *sc = aux; 716 u_int8_t mcr; 717 718 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 719 720 NTWO_DPRINTF(("port == %d, state == %d, old mcr: 0x%02x\n", 721 port, state, mcr)); 722 723 if (port == 0) { 724 if (state == 0) 725 mcr |= NTWOC_MCR_DTR0; 726 else 727 mcr &= ~NTWOC_MCR_DTR0; 728 } else { 729 if (state == 0) 730 mcr |= NTWOC_MCR_DTR1; 731 else 732 mcr &= ~NTWOC_MCR_DTR1; 733 } 734 735 NTWO_DPRINTF(("new mcr: 0x%02x\n", mcr)); 736 737 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 738 } 739 740 static void 741 ntwoc_isa_clock_callback(void *aux, int port, int enable) 742 { 743 struct ntwoc_isa_softc *sc = aux; 744 u_int8_t mcr; 745 746 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 747 748 NTWO_DPRINTF(("clock: port == %d, enable == %d, old mcr: 0x%02x\n", 749 port, enable, mcr)); 750 751 if (port == 0) { 752 if (enable == 0) 753 mcr &= ~NTWOC_MCR_ETC0; 754 else 755 mcr |= NTWOC_MCR_ETC0; 756 } else { 757 if (enable == 0) 758 mcr &= ~NTWOC_MCR_ETC1; 759 else 760 mcr |= NTWOC_MCR_ETC1; 761 } 762 763 NTWO_DPRINTF(("clock: new mcr: 0x%02x\n", mcr)); 764 765 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 766 } 767 768 static void 769 ntwoc_isa_setup_memory(struct sca_softc *sc) 770 { 771 struct sca_port *scp; 772 u_int i, j; 773 774 /* allocate enough descriptors for a full page */ 775 776 sc->sc_ports[0].sp_ntxdesc = (sc->scu_pagesize / SCA_BSIZE) - 1; 777 sc->sc_ports[0].sp_nrxdesc = (sc->scu_pagesize / SCA_BSIZE) - 1; 778 if (sc->sc_numports == 2) { 779 sc->sc_ports[1].sp_ntxdesc = sc->sc_ports[0].sp_ntxdesc; 780 sc->sc_ports[1].sp_nrxdesc = sc->sc_ports[0].sp_nrxdesc; 781 } 782 783 j = 0; 784 for (i = 0; i < sc->sc_numports; i++) { 785 scp = &sc->sc_ports[i]; 786 scp->sp_txdesc_p = (bus_addr_t)(j * sc->scu_pagesize); 787 scp->sp_txdesc = (void *)scp->sp_txdesc_p; 788 scp->sp_txbuf_p = scp->sp_txdesc_p; 789 scp->sp_txbuf_p += SCA_BSIZE; 790 scp->sp_txbuf = (void *)scp->sp_txbuf_p; 791 j++; 792 793 scp->sp_rxdesc_p = (bus_addr_t)(j * sc->scu_pagesize); 794 scp->sp_rxdesc = (void *)scp->sp_txdesc_p; 795 scp->sp_rxbuf_p = scp->sp_rxdesc_p; 796 scp->sp_rxbuf_p += SCA_BSIZE; 797 scp->sp_rxbuf = (void *)scp->sp_rxbuf_p; 798 j++; 799 } 800 } 801 802 #if __NetBSD_Version__ >= 104160000 803 /* 804 * get the base clock frequency 805 */ 806 static void 807 ntwoc_isa_config_interrupts(self) 808 struct device *self; 809 { 810 struct ntwoc_isa_softc *sc; 811 812 sc = (void *)self; 813 sca_get_base_clock(&sc->sc_sca); 814 sca_print_clock_info(&sc->sc_sca); 815 } 816 #endif 817