qec.c 11 KB

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