1 /* $NetBSD: if_ntwoc_isa.c,v 1.23 2010/08/03 14:06:10 jakllsch 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.23 2010/08/03 14:06:10 jakllsch Exp $ 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: if_ntwoc_isa.c,v 1.23 2010/08/03 14:06:10 jakllsch 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 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(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(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 = (struct ntwoc_isa_softc *)self; 397 sca = &sc->sc_sca; 398 dbg = 0; 399 400 printf(": N2 Serial Interface\n"); 401 flags = device_cfdata(&sc->sc_dev)->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 aprint_error_dev(&sc->sc_dev, "can't map io 0x%x sz %d, %d\n", 423 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 aprint_error_dev(&sc->sc_dev, "mapping sca 0x%x sz %d failed: %d\n", 435 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 aprint_error_dev(&sc->sc_dev, "can't map mem 0x%x sz %ld, %d\n", 467 ia->ia_iomem[0].ir_addr, 468 (u_long)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 device_xname(&sc->sc_dev), 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 device_xname(&sc->sc_dev), (u_long)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 aprint_error_dev(&sc->sc_dev, "can't establish interrupt\n"); 568 return; 569 } 570 571 /* make sure we have 2 pages for each port */ 572 if (pgs < 2 * sca->sc_numports) { 573 printf("%s: %d less than required pages of memory of %d\n", 574 device_xname(&sc->sc_dev), pgs, 2 * sca->sc_numports); 575 return; 576 } 577 578 /* sca_get_base_clock(sca); */ 579 580 /* 581 * get clock information from user 582 */ 583 rdiv = (flags & NTWOC_FLAGS_RXDIV_MASK) >> NTWOC_FLAGS_RXDIV_SHIFT; 584 if (rdiv > 9) 585 panic("bad rx divisor in flags"); 586 587 tdiv = (flags & NTWOC_FLAGS_TXDIV_MASK) >> NTWOC_FLAGS_TXDIV_SHIFT; 588 if (tdiv > 9) 589 panic("bad tx divisor in flags"); 590 tmc = (flags & NTWOC_FLAGS_TMC_MASK) >> NTWOC_FLAGS_TMC_SHIFT; 591 592 ntwoc_isa_get_clock(&sca->sc_ports[0], 593 flags & NTWOC_FLAGS_CLK0_MASK, tmc, rdiv, tdiv); 594 if (sca->sc_numports > 1) 595 ntwoc_isa_get_clock(&sca->sc_ports[1], 596 (flags & NTWOC_FLAGS_CLK1_MASK) >> NTWOC_FLAGS_CLK1_SHIFT, 597 tmc, rdiv, tdiv); 598 599 ntwoc_isa_setup_memory(sca); 600 601 sca_init(sca); 602 603 /* attach configured ports */ 604 sca_port_attach(sca, 0); 605 if (sca->sc_numports == 2) 606 sca_port_attach(sca, 1); 607 608 /* 609 * Add shutdown hook so that DMA is disabled prior to reboot. Not 610 * doing do could allow DMA to corrupt kernel memory during the 611 * reboot before the driver initializes. 612 */ 613 shutdownhook_establish(ntwoc_isa_shutdown, sc); 614 615 #if __NetBSD_Version__ >= 104160000 616 /* 617 * defer getting the base clock until interrupts are enabled 618 * (and thus we have microtime()) 619 */ 620 config_interrupts(self, ntwoc_isa_config_interrupts); 621 #else 622 /* no callback pre 1.4-mumble */ 623 sca->sc_baseclock = SCA_BASECLOCK; 624 sca_print_clock_info(&sc->sc_sca); 625 #endif 626 } 627 628 /* 629 * extract the clock information for a port from the flags field 630 */ 631 static void 632 ntwoc_isa_get_clock(struct sca_port *scp, u_int8_t flags, u_int8_t tmc, 633 u_int8_t rdiv, u_int8_t tdiv) 634 { 635 scp->sp_eclock = 636 (flags & NTWOC_FLAGS_ECLOCK_MASK) >> NTWOC_FLAGS_ECLOCK_SHIFT; 637 scp->sp_rxs = rdiv; 638 scp->sp_txs = tdiv; 639 scp->sp_tmc = tmc; 640 641 /* get rx source */ 642 switch ((flags & NTWOC_FLAGS_RXS_MASK) >> NTWOC_FLAGS_RXS_SHIFT) { 643 case NTWOC_FLAGS_RXS_LINE: 644 scp->sp_rxs = 0; 645 break; 646 case NTWOC_FLAGS_RXS_LINE_SN: 647 scp->sp_rxs |= SCA_RXS_CLK_LINE_SN; 648 break; 649 case NTWOC_FLAGS_RXS_INTERNAL: 650 scp->sp_rxs |= SCA_RXS_CLK_INTERNAL; 651 break; 652 case NTWOC_FLAGS_RXS_ADPLL_OUT: 653 scp->sp_rxs |= SCA_RXS_CLK_ADPLL_OUT; 654 break; 655 case NTWOC_FLAGS_RXS_ADPLL_IN: 656 scp->sp_rxs |= SCA_RXS_CLK_ADPLL_IN; 657 break; 658 default: 659 panic("bad rx source in flags"); 660 } 661 662 /* get tx source */ 663 switch ((flags & NTWOC_FLAGS_TXS_MASK) >> NTWOC_FLAGS_TXS_SHIFT) { 664 case NTWOC_FLAGS_TXS_LINE: 665 scp->sp_txs = 0; 666 break; 667 case NTWOC_FLAGS_TXS_INTERNAL: 668 scp->sp_txs |= SCA_TXS_CLK_INTERNAL; 669 break; 670 case NTWOC_FLAGS_TXS_RXCLOCK: 671 scp->sp_txs |= SCA_TXS_CLK_RXCLK; 672 break; 673 default: 674 panic("bad rx source in flags"); 675 } 676 } 677 678 679 static int 680 ntwoc_isa_intr(void *arg) 681 { 682 struct ntwoc_isa_softc *sc = (struct ntwoc_isa_softc *)arg; 683 684 return sca_hardintr(&sc->sc_sca); 685 } 686 687 /* 688 * shut down interrupts and DMA, so we don't trash the kernel on warm 689 * boot. Also, lower DTR on each port and disable card interrupts. 690 */ 691 static void 692 ntwoc_isa_shutdown(void *aux) 693 { 694 struct ntwoc_isa_softc *sc = aux; 695 u_int16_t mcr; 696 697 /* 698 * shut down the SCA ports 699 */ 700 sca_shutdown(&sc->sc_sca); 701 702 /* 703 * lower DTR on both ports 704 */ 705 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 706 mcr |= (NTWOC_MCR_DTR0 | NTWOC_MCR_DTR1); 707 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 708 709 /* turn off the card */ 710 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_PCR, 0); 711 } 712 713 static void 714 ntwoc_isa_dtr_callback(void *aux, int port, int state) 715 { 716 struct ntwoc_isa_softc *sc = aux; 717 u_int8_t mcr; 718 719 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 720 721 NTWO_DPRINTF(("port == %d, state == %d, old mcr: 0x%02x\n", 722 port, state, mcr)); 723 724 if (port == 0) { 725 if (state == 0) 726 mcr |= NTWOC_MCR_DTR0; 727 else 728 mcr &= ~NTWOC_MCR_DTR0; 729 } else { 730 if (state == 0) 731 mcr |= NTWOC_MCR_DTR1; 732 else 733 mcr &= ~NTWOC_MCR_DTR1; 734 } 735 736 NTWO_DPRINTF(("new mcr: 0x%02x\n", mcr)); 737 738 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 739 } 740 741 static void 742 ntwoc_isa_clock_callback(void *aux, int port, int enable) 743 { 744 struct ntwoc_isa_softc *sc = aux; 745 u_int8_t mcr; 746 747 mcr = bus_space_read_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR); 748 749 NTWO_DPRINTF(("clock: port == %d, enable == %d, old mcr: 0x%02x\n", 750 port, enable, mcr)); 751 752 if (port == 0) { 753 if (enable == 0) 754 mcr &= ~NTWOC_MCR_ETC0; 755 else 756 mcr |= NTWOC_MCR_ETC0; 757 } else { 758 if (enable == 0) 759 mcr &= ~NTWOC_MCR_ETC1; 760 else 761 mcr |= NTWOC_MCR_ETC1; 762 } 763 764 NTWO_DPRINTF(("clock: new mcr: 0x%02x\n", mcr)); 765 766 bus_space_write_1(sc->sc_sca.sc_iot, sc->sc_sca.sc_ioh, NTWOC_MCR, mcr); 767 } 768 769 static void 770 ntwoc_isa_setup_memory(struct sca_softc *sc) 771 { 772 struct sca_port *scp; 773 u_int i, j; 774 775 /* allocate enough descriptors for a full page */ 776 777 sc->sc_ports[0].sp_ntxdesc = (sc->scu_pagesize / SCA_BSIZE) - 1; 778 sc->sc_ports[0].sp_nrxdesc = (sc->scu_pagesize / SCA_BSIZE) - 1; 779 if (sc->sc_numports == 2) { 780 sc->sc_ports[1].sp_ntxdesc = sc->sc_ports[0].sp_ntxdesc; 781 sc->sc_ports[1].sp_nrxdesc = sc->sc_ports[0].sp_nrxdesc; 782 } 783 784 j = 0; 785 for (i = 0; i < sc->sc_numports; i++) { 786 scp = &sc->sc_ports[i]; 787 scp->sp_txdesc_p = (bus_addr_t)(j * sc->scu_pagesize); 788 scp->sp_txdesc = (void *)(uintptr_t)scp->sp_txdesc_p; 789 scp->sp_txbuf_p = scp->sp_txdesc_p; 790 scp->sp_txbuf_p += SCA_BSIZE; 791 scp->sp_txbuf = (void *)(uintptr_t)scp->sp_txbuf_p; 792 j++; 793 794 scp->sp_rxdesc_p = (bus_addr_t)(j * sc->scu_pagesize); 795 scp->sp_rxdesc = (void *)(uintptr_t)scp->sp_txdesc_p; 796 scp->sp_rxbuf_p = scp->sp_rxdesc_p; 797 scp->sp_rxbuf_p += SCA_BSIZE; 798 scp->sp_rxbuf = (void *)(uintptr_t)scp->sp_rxbuf_p; 799 j++; 800 } 801 } 802 803 #if __NetBSD_Version__ >= 104160000 804 /* 805 * get the base clock frequency 806 */ 807 static void 808 ntwoc_isa_config_interrupts(device_t 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