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