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