1 /* $NetBSD: if_ntwoc_isa.c,v 1.24 2012/10/27 17:18:24 chs 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.24 2012/10/27 17:18:24 chs Exp $ 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: if_ntwoc_isa.c,v 1.24 2012/10/27 17:18:24 chs 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 <sys/cpu.h> 47 #include <sys/bus.h> 48 #include <sys/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(device_t); 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 device_t 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(device_t, cfdata_t, void *); 88 static void ntwoc_isa_attach(device_t, device_t, void *); 89 90 static void ntwoc_isa_clock_callback(void *, int, int); 91 static void ntwoc_isa_dtr_callback(void *, int, int); 92 static int ntwoc_isa_intr(void *); 93 static void ntwoc_isa_get_clock(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(void *sc); 97 98 CFATTACH_DECL_NEW(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 const 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(device_t parent, cfdata_t 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 == ISA_UNKNOWN_PORT) { 218 printf("ntwoc_isa_probe: must specify port address\n"); 219 return (0); 220 } 221 222 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) { 223 printf("ntwoc_isa_probe: must specify irq\n"); 224 return (0); 225 } 226 227 if (ia->ia_iomem[0].ir_addr == ISA_UNKNOWN_IOMEM) { 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(device_t parent, device_t 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 = device_private(self); 397 sc->sc_dev = self; 398 sca = &sc->sc_sca; 399 dbg = 0; 400 401 printf(": N2 Serial Interface\n"); 402 flags = device_cfdata(sc->sc_dev)->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 aprint_error_dev(sc->sc_dev, "can't map io 0x%x sz %d, %d\n", 424 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 aprint_error_dev(sc->sc_dev, "mapping sca 0x%x sz %d failed: %d\n", 436 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 aprint_error_dev(sc->sc_dev, "can't map mem 0x%x sz %ld, %d\n", 468 ia->ia_iomem[0].ir_addr, 469 (u_long)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 device_xname(sc->sc_dev), 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 device_xname(sc->sc_dev), (u_long)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 aprint_error_dev(sc->sc_dev, "can't establish interrupt\n"); 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 device_xname(sc->sc_dev), 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 /* turn off the card */ 711 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_PCR, 0); 712 } 713 714 static void 715 ntwoc_isa_dtr_callback(void *aux, int port, int state) 716 { 717 struct ntwoc_isa_softc *sc = aux; 718 u_int8_t mcr; 719 720 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 721 722 NTWO_DPRINTF(("port == %d, state == %d, old mcr: 0x%02x\n", 723 port, state, mcr)); 724 725 if (port == 0) { 726 if (state == 0) 727 mcr |= NTWOC_MCR_DTR0; 728 else 729 mcr &= ~NTWOC_MCR_DTR0; 730 } else { 731 if (state == 0) 732 mcr |= NTWOC_MCR_DTR1; 733 else 734 mcr &= ~NTWOC_MCR_DTR1; 735 } 736 737 NTWO_DPRINTF(("new mcr: 0x%02x\n", mcr)); 738 739 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 740 } 741 742 static void 743 ntwoc_isa_clock_callback(void *aux, int port, int enable) 744 { 745 struct ntwoc_isa_softc *sc = aux; 746 u_int8_t mcr; 747 748 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 749 750 NTWO_DPRINTF(("clock: port == %d, enable == %d, old mcr: 0x%02x\n", 751 port, enable, mcr)); 752 753 if (port == 0) { 754 if (enable == 0) 755 mcr &= ~NTWOC_MCR_ETC0; 756 else 757 mcr |= NTWOC_MCR_ETC0; 758 } else { 759 if (enable == 0) 760 mcr &= ~NTWOC_MCR_ETC1; 761 else 762 mcr |= NTWOC_MCR_ETC1; 763 } 764 765 NTWO_DPRINTF(("clock: new mcr: 0x%02x\n", mcr)); 766 767 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 768 } 769 770 static void 771 ntwoc_isa_setup_memory(struct sca_softc *sc) 772 { 773 struct sca_port *scp; 774 u_int i, j; 775 776 /* allocate enough descriptors for a full page */ 777 778 sc->sc_ports[0].sp_ntxdesc = (sc->scu_pagesize / SCA_BSIZE) - 1; 779 sc->sc_ports[0].sp_nrxdesc = (sc->scu_pagesize / SCA_BSIZE) - 1; 780 if (sc->sc_numports == 2) { 781 sc->sc_ports[1].sp_ntxdesc = sc->sc_ports[0].sp_ntxdesc; 782 sc->sc_ports[1].sp_nrxdesc = sc->sc_ports[0].sp_nrxdesc; 783 } 784 785 j = 0; 786 for (i = 0; i < sc->sc_numports; i++) { 787 scp = &sc->sc_ports[i]; 788 scp->sp_txdesc_p = (bus_addr_t)(j * sc->scu_pagesize); 789 scp->sp_txdesc = (void *)(uintptr_t)scp->sp_txdesc_p; 790 scp->sp_txbuf_p = scp->sp_txdesc_p; 791 scp->sp_txbuf_p += SCA_BSIZE; 792 scp->sp_txbuf = (void *)(uintptr_t)scp->sp_txbuf_p; 793 j++; 794 795 scp->sp_rxdesc_p = (bus_addr_t)(j * sc->scu_pagesize); 796 scp->sp_rxdesc = (void *)(uintptr_t)scp->sp_txdesc_p; 797 scp->sp_rxbuf_p = scp->sp_rxdesc_p; 798 scp->sp_rxbuf_p += SCA_BSIZE; 799 scp->sp_rxbuf = (void *)(uintptr_t)scp->sp_rxbuf_p; 800 j++; 801 } 802 } 803 804 #if __NetBSD_Version__ >= 104160000 805 /* 806 * get the base clock frequency 807 */ 808 static void 809 ntwoc_isa_config_interrupts(device_t self) 810 { 811 struct ntwoc_isa_softc *sc; 812 813 sc = device_private(self); 814 sca_get_base_clock(&sc->sc_sca); 815 sca_print_clock_info(&sc->sc_sca); 816 } 817 #endif 818