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