1 /* $OpenBSD: qec.c,v 1.13 2008/06/26 05:42:18 ray Exp $ */ 2 /* $NetBSD: qec.c,v 1.12 2000/12/04 20:12:55 fvdl Exp $ */ 3 4 /*- 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Paul Kranenburg. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/errno.h> 38 #include <sys/device.h> 39 #include <sys/malloc.h> 40 41 #include <machine/bus.h> 42 #include <machine/intr.h> 43 #include <machine/autoconf.h> 44 45 #include <dev/sbus/sbusvar.h> 46 #include <dev/sbus/qecreg.h> 47 #include <dev/sbus/qecvar.h> 48 49 int qecprint(void *, const char *); 50 int qecmatch(struct device *, void *, void *); 51 void qecattach(struct device *, struct device *, void *); 52 void qec_init(struct qec_softc *); 53 54 int qec_bus_map( 55 bus_space_tag_t, 56 bus_space_tag_t, 57 bus_addr_t, /*offset*/ 58 bus_size_t, /*size*/ 59 int, /*flags*/ 60 bus_space_handle_t *); 61 void * qec_intr_establish( 62 bus_space_tag_t, 63 bus_space_tag_t, 64 int, /*bus interrupt priority*/ 65 int, /*`device class' interrupt level*/ 66 int, /*flags*/ 67 int (*)(void *), /*handler*/ 68 void *, /*arg*/ 69 const char *); /*what*/ 70 71 struct cfattach qec_ca = { 72 sizeof(struct qec_softc), qecmatch, qecattach 73 }; 74 75 struct cfdriver qec_cd = { 76 NULL, "qec", DV_DULL 77 }; 78 79 int 80 qecprint(aux, busname) 81 void *aux; 82 const char *busname; 83 { 84 struct sbus_attach_args *sa = aux; 85 bus_space_tag_t t = sa->sa_bustag; 86 struct qec_softc *sc = t->cookie; 87 88 sa->sa_bustag = sc->sc_bustag; /* XXX */ 89 sbus_print(aux, busname); /* XXX */ 90 sa->sa_bustag = t; /* XXX */ 91 return (UNCONF); 92 } 93 94 int 95 qecmatch(parent, vcf, aux) 96 struct device *parent; 97 void *vcf; 98 void *aux; 99 { 100 struct cfdata *cf = vcf; 101 struct sbus_attach_args *sa = aux; 102 103 return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0); 104 } 105 106 /* 107 * Attach all the sub-devices we can find 108 */ 109 void 110 qecattach(parent, self, aux) 111 struct device *parent, *self; 112 void *aux; 113 { 114 struct sbus_attach_args *sa = aux; 115 struct qec_softc *sc = (void *)self; 116 int node; 117 int sbusburst; 118 struct sparc_bus_space_tag *sbt; 119 bus_space_handle_t bh; 120 int error; 121 122 sc->sc_bustag = sa->sa_bustag; 123 sc->sc_dmatag = sa->sa_dmatag; 124 node = sa->sa_node; 125 126 if (sa->sa_nreg < 2) { 127 printf("%s: only %d register sets\n", 128 self->dv_xname, sa->sa_nreg); 129 return; 130 } 131 132 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, 133 sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 134 0, 0, &sc->sc_regs) != 0) { 135 printf("%s: attach: cannot map registers\n", self->dv_xname); 136 return; 137 } 138 139 /* 140 * This device's "register space 1" is just a buffer where the 141 * Lance ring-buffers can be stored. Note the buffer's location 142 * and size, so the child driver can pick them up. 143 */ 144 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot, 145 sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size, 0, 0, &bh) != 0) { 146 printf("%s: attach: cannot map registers\n", self->dv_xname); 147 return; 148 } 149 sc->sc_buffer = (caddr_t)bus_space_vaddr(sc->sc_bustag, bh); 150 sc->sc_bufsiz = (bus_size_t)sa->sa_reg[1].sbr_size; 151 152 /* Get number of on-board channels */ 153 sc->sc_nchannels = getpropint(node, "#channels", -1); 154 if (sc->sc_nchannels == -1) { 155 printf(": no channels\n"); 156 return; 157 } 158 159 /* 160 * Get transfer burst size from PROM 161 */ 162 sbusburst = ((struct sbus_softc *)parent)->sc_burst; 163 if (sbusburst == 0) 164 sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ 165 166 sc->sc_burst = getpropint(node, "burst-sizes", -1); 167 if (sc->sc_burst == -1) 168 /* take SBus burst sizes */ 169 sc->sc_burst = sbusburst; 170 171 /* Clamp at parent's burst sizes */ 172 sc->sc_burst &= sbusburst; 173 174 /* 175 * Collect address translations from the OBP. 176 */ 177 error = getprop(node, "ranges", sizeof(struct sbus_range), 178 &sc->sc_nrange, (void **)&sc->sc_range); 179 switch (error) { 180 case 0: 181 break; 182 case ENOENT: 183 default: 184 panic("%s: error getting ranges property", self->dv_xname); 185 } 186 187 /* Allocate a bus tag */ 188 sbt = malloc(sizeof(*sbt), M_DEVBUF, M_NOWAIT | M_ZERO); 189 if (sbt == NULL) { 190 printf("%s: attach: out of memory\n", self->dv_xname); 191 return; 192 } 193 194 strlcpy(sbt->name, sc->sc_dev.dv_xname, sizeof(sbt->name)); 195 sbt->cookie = sc; 196 sbt->parent = sc->sc_bustag; 197 sbt->asi = sbt->parent->asi; 198 sbt->sasi = sbt->parent->sasi; 199 sbt->sparc_bus_map = qec_bus_map; 200 sbt->sparc_intr_establish = qec_intr_establish; 201 202 /* 203 * Save interrupt information for use in our qec_intr_establish() 204 * function below. Apparently, the intr level for the quad 205 * ethernet board (qe) is stored in the QEC node rather than 206 * separately in each of the QE nodes. 207 * 208 * XXX - qe.c should call bus_intr_establish() with `level = 0'.. 209 * XXX - maybe we should have our own attach args for all that. 210 */ 211 sc->sc_intr = sa->sa_intr; 212 213 printf(": %dK memory\n", sc->sc_bufsiz / 1024); 214 215 qec_init(sc); 216 217 /* search through children */ 218 for (node = firstchild(node); node; node = nextsibling(node)) { 219 struct sbus_attach_args sa; 220 221 sbus_setup_attach_args((struct sbus_softc *)parent, 222 sbt, sc->sc_dmatag, node, &sa); 223 (void)config_found(&sc->sc_dev, (void *)&sa, qecprint); 224 sbus_destroy_attach_args(&sa); 225 } 226 } 227 228 int 229 qec_bus_map(t, t0, addr, size, flags, hp) 230 bus_space_tag_t t; 231 bus_space_tag_t t0; 232 bus_addr_t addr; 233 bus_size_t size; 234 int flags; 235 bus_space_handle_t *hp; 236 { 237 struct qec_softc *sc = t->cookie; 238 int slot = BUS_ADDR_IOSPACE(addr); 239 bus_addr_t offset = BUS_ADDR_PADDR(addr); 240 int i; 241 242 for (t = t->parent; t; t = t->parent) { 243 if (t->sparc_bus_map != NULL) 244 break; 245 } 246 247 if (t == NULL) { 248 printf("\nqec_bus_map: invalid parent"); 249 return (EINVAL); 250 } 251 252 if (flags & BUS_SPACE_MAP_PROMADDRESS) { 253 return ((*t->sparc_bus_map) 254 (t, t0, offset, size, flags, hp)); 255 } 256 257 for (i = 0; i < sc->sc_nrange; i++) { 258 bus_addr_t paddr; 259 int iospace; 260 261 if (sc->sc_range[i].cspace != slot) 262 continue; 263 264 /* We've found the connection to the parent bus */ 265 paddr = sc->sc_range[i].poffset + offset; 266 iospace = sc->sc_range[i].pspace; 267 return ((*t->sparc_bus_map) 268 (t, t0, BUS_ADDR(iospace, paddr), size, flags, hp)); 269 } 270 271 return (EINVAL); 272 } 273 274 void * 275 qec_intr_establish(t, t0, pri, level, flags, handler, arg, what) 276 bus_space_tag_t t; 277 bus_space_tag_t t0; 278 int pri; 279 int level; 280 int flags; 281 int (*handler)(void *); 282 void *arg; 283 const char *what; 284 { 285 struct qec_softc *sc = t->cookie; 286 287 if (pri == 0) { 288 /* 289 * qe.c calls bus_intr_establish() with `pri == 0' 290 * XXX - see also comment in qec_attach(). 291 */ 292 if (sc->sc_intr == NULL) { 293 printf("%s: warning: no interrupts\n", 294 sc->sc_dev.dv_xname); 295 return (NULL); 296 } 297 pri = sc->sc_intr->sbi_pri; 298 } 299 300 for (t = t->parent; t; t = t->parent) { 301 if (t->sparc_intr_establish != NULL) 302 return ((*t->sparc_intr_establish) 303 (t, t0, pri, level, flags, handler, arg, what)); 304 } 305 306 panic("qec_intr_extablish): no handler found"); 307 308 return (NULL); 309 } 310 311 void 312 qec_init(sc) 313 struct qec_softc *sc; 314 { 315 bus_space_tag_t t = sc->sc_bustag; 316 bus_space_handle_t qr = sc->sc_regs; 317 u_int32_t v, burst = 0, psize; 318 int i; 319 320 /* First, reset the controller */ 321 bus_space_write_4(t, qr, QEC_QRI_CTRL, QEC_CTRL_RESET); 322 for (i = 0; i < 1000; i++) { 323 DELAY(100); 324 v = bus_space_read_4(t, qr, QEC_QRI_CTRL); 325 if ((v & QEC_CTRL_RESET) == 0) 326 break; 327 } 328 329 /* 330 * Cut available buffer size into receive and transmit buffers. 331 * XXX - should probably be done in be & qe driver... 332 */ 333 v = sc->sc_msize = sc->sc_bufsiz / sc->sc_nchannels; 334 bus_space_write_4(t, qr, QEC_QRI_MSIZE, v); 335 336 v = sc->sc_rsize = sc->sc_bufsiz / (sc->sc_nchannels * 2); 337 bus_space_write_4(t, qr, QEC_QRI_RSIZE, v); 338 bus_space_write_4(t, qr, QEC_QRI_TSIZE, v); 339 340 psize = sc->sc_nchannels == 1 ? QEC_PSIZE_2048 : 0; 341 bus_space_write_4(t, qr, QEC_QRI_PSIZE, psize); 342 343 if (sc->sc_burst & SBUS_BURST_64) 344 burst = QEC_CTRL_B64; 345 else if (sc->sc_burst & SBUS_BURST_32) 346 burst = QEC_CTRL_B32; 347 else 348 burst = QEC_CTRL_B16; 349 350 v = bus_space_read_4(t, qr, QEC_QRI_CTRL); 351 v = (v & QEC_CTRL_MODEMASK) | burst; 352 bus_space_write_4(t, qr, QEC_QRI_CTRL, v); 353 } 354 355 /* 356 * Common routine to initialize the QEC packet ring buffer. 357 * Called from be & qe drivers. 358 */ 359 void 360 qec_meminit(qr, pktbufsz) 361 struct qec_ring *qr; 362 unsigned int pktbufsz; 363 { 364 bus_addr_t txbufdma, rxbufdma; 365 bus_addr_t dma; 366 caddr_t p; 367 unsigned int ntbuf, nrbuf, i; 368 369 p = qr->rb_membase; 370 dma = qr->rb_dmabase; 371 372 ntbuf = qr->rb_ntbuf; 373 nrbuf = qr->rb_nrbuf; 374 375 /* 376 * Allocate transmit descriptors 377 */ 378 qr->rb_txd = (struct qec_xd *)p; 379 qr->rb_txddma = dma; 380 p += QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd); 381 dma += QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd); 382 383 /* 384 * Allocate receive descriptors 385 */ 386 qr->rb_rxd = (struct qec_xd *)p; 387 qr->rb_rxddma = dma; 388 p += QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd); 389 dma += QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd); 390 391 392 /* 393 * Allocate transmit buffers 394 */ 395 qr->rb_txbuf = p; 396 txbufdma = dma; 397 p += ntbuf * pktbufsz; 398 dma += ntbuf * pktbufsz; 399 400 /* 401 * Allocate receive buffers 402 */ 403 qr->rb_rxbuf = p; 404 rxbufdma = dma; 405 p += nrbuf * pktbufsz; 406 dma += nrbuf * pktbufsz; 407 408 /* 409 * Initialize transmit buffer descriptors 410 */ 411 for (i = 0; i < QEC_XD_RING_MAXSIZE; i++) { 412 qr->rb_txd[i].xd_addr = (u_int32_t) 413 (txbufdma + (i % ntbuf) * pktbufsz); 414 qr->rb_txd[i].xd_flags = 0; 415 } 416 417 /* 418 * Initialize receive buffer descriptors 419 */ 420 for (i = 0; i < QEC_XD_RING_MAXSIZE; i++) { 421 qr->rb_rxd[i].xd_addr = (u_int32_t) 422 (rxbufdma + (i % nrbuf) * pktbufsz); 423 qr->rb_rxd[i].xd_flags = (i < nrbuf) 424 ? QEC_XD_OWN | (pktbufsz & QEC_XD_LENGTH) 425 : 0; 426 } 427 428 qr->rb_tdhead = qr->rb_tdtail = 0; 429 qr->rb_td_nbusy = 0; 430 qr->rb_rdtail = 0; 431 } 432