lance.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /* $OpenBSD: lance.c,v 1.2 2013/10/29 21:49:07 miod Exp $ */
  2. /* $NetBSD: lance.c,v 1.1 2013/01/13 14:10:55 tsutsui Exp $ */
  3. /*
  4. * Copyright (c) 2013 Izumi Tsutsui. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. /*-
  27. * Copyright (c) 2004 The NetBSD Foundation, Inc.
  28. * All rights reserved.
  29. *
  30. * This code is derived from software contributed to The NetBSD Foundation
  31. * by UCHIYAMA Yasushi.
  32. *
  33. * Redistribution and use in source and binary forms, with or without
  34. * modification, are permitted provided that the following conditions
  35. * are met:
  36. * 1. Redistributions of source code must retain the above copyright
  37. * notice, this list of conditions and the following disclaimer.
  38. * 2. Redistributions in binary form must reproduce the above copyright
  39. * notice, this list of conditions and the following disclaimer in the
  40. * documentation and/or other materials provided with the distribution.
  41. *
  42. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  43. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  44. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  45. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  46. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  47. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  48. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  49. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  50. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  51. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  52. * POSSIBILITY OF SUCH DAMAGE.
  53. */
  54. /*
  55. * LANCE driver for LUNA
  56. * based on sys/arch/ews4800mips/stand/common/lance.c
  57. */
  58. #include <luna88k/stand/boot/samachdep.h>
  59. #include <dev/ic/am7990reg.h>
  60. #include <dev/ic/lancereg.h>
  61. #include <luna88k/stand/boot/lance.h>
  62. static void lance_setup(struct le_softc *);
  63. static int lance_set_initblock(struct le_softc *);
  64. static int lance_do_initialize(struct le_softc *);
  65. #define NLE 1 /* XXX for now */
  66. static struct le_softc lesc[NLE];
  67. void *
  68. lance_attach(uint unit, void *reg, void *mem, uint8_t *eaddr)
  69. {
  70. struct le_softc *sc;
  71. if (unit >= NLE) {
  72. printf("%s: invalid unit number\n", __func__);
  73. return NULL;
  74. }
  75. sc = &lesc[unit];
  76. if (sc->sc_reg != NULL) {
  77. printf("%s: unit %d is already attached\n", __func__, unit);
  78. return NULL;
  79. }
  80. sc->sc_reg = reg;
  81. sc->sc_mem = mem;
  82. memcpy(sc->sc_enaddr, eaddr, 6);
  83. return sc;
  84. }
  85. void *
  86. lance_cookie(uint unit)
  87. {
  88. struct le_softc *sc;
  89. if (unit >= NLE)
  90. return NULL;
  91. sc = &lesc[unit];
  92. if (sc->sc_reg == NULL)
  93. return NULL;
  94. return sc;
  95. }
  96. uint8_t *
  97. lance_eaddr(void *cookie)
  98. {
  99. struct le_softc *sc = cookie;
  100. if (sc == NULL || sc->sc_reg == NULL)
  101. return NULL;
  102. return sc->sc_enaddr;
  103. }
  104. int
  105. lance_init(void *cookie)
  106. {
  107. struct le_softc *sc = cookie;
  108. lance_setup(sc);
  109. if (!lance_set_initblock(sc))
  110. return 0;
  111. if (!lance_do_initialize(sc))
  112. return 0;
  113. return 1;
  114. }
  115. int
  116. lance_get(void *cookie, void *data, size_t maxlen)
  117. {
  118. struct le_softc *sc = cookie;
  119. struct lereg *lereg = sc->sc_reg;
  120. struct lemem *lemem = sc->sc_mem;
  121. struct lermd_v *rmd;
  122. uint16_t csr;
  123. int len = -1;
  124. lereg->ler_rap = LE_CSR0;
  125. if ((lereg->ler_rdp & LE_C0_RINT) != 0)
  126. lereg->ler_rdp = LE_C0_RINT;
  127. rmd = &lemem->lem_rmd[sc->sc_currmd];
  128. if ((rmd->rmd1_bits & LE_R1_OWN) != 0)
  129. return -1;
  130. csr = lereg->ler_rdp;
  131. #if 0
  132. if ((csr & LE_C0_ERR) != 0)
  133. printf("%s: RX poll error (CSR=0x%x)\n", __func__, csr);
  134. #endif
  135. if ((rmd->rmd1_bits & LE_R1_ERR) != 0) {
  136. printf("%s: RX error (rmd status=0x%x)\n", __func__,
  137. rmd->rmd1_bits);
  138. goto out;
  139. }
  140. len = rmd->rmd3;
  141. if (len < LEMINSIZE + 4 || len > LEMTU) {
  142. printf("%s: RX error (bad length %d)\n", __func__, len);
  143. goto out;
  144. }
  145. len -= 4;
  146. memcpy(data, (void *)lemem->lem_rbuf[sc->sc_currmd], min(len, maxlen));
  147. out:
  148. rmd->rmd2 = -LEMTU;
  149. rmd->rmd1_bits = LE_R1_OWN; /* return to LANCE */
  150. sc->sc_currmd = LE_NEXTRMD(sc->sc_currmd);
  151. return len;
  152. }
  153. int
  154. lance_put(void *cookie, void *data, size_t len)
  155. {
  156. struct le_softc *sc = cookie;
  157. struct lereg *lereg = sc->sc_reg;
  158. struct lemem *lemem = sc->sc_mem;
  159. struct letmd_v *tmd;
  160. uint16_t stat;
  161. int timeout;
  162. lereg->ler_rap = LE_CSR0;
  163. stat = lereg->ler_rdp;
  164. lereg->ler_rdp =
  165. stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_TINT);
  166. #if 0
  167. if (stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR))
  168. printf("%s: TX error before xmit csr0=0x%x\n",
  169. __func__, stat);
  170. #endif
  171. /* setup TX descriptor */
  172. tmd = &lemem->lem_tmd[sc->sc_curtmd];
  173. while (tmd->tmd1_bits & LE_T1_OWN)
  174. continue;
  175. tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP;
  176. memcpy((void *)lemem->lem_tbuf[sc->sc_curtmd], data, len);
  177. tmd->tmd2 = -max(len, LEMINSIZE);
  178. tmd->tmd3 = 0;
  179. /* start TX */
  180. tmd->tmd1_bits |= LE_T1_OWN;
  181. lereg->ler_rap = LE_CSR0;
  182. lereg->ler_rdp = LE_C0_TDMD;
  183. /* check TX complete */
  184. timeout = 0;
  185. do {
  186. lereg->ler_rap = LE_CSR0;
  187. stat = lereg->ler_rdp;
  188. #if 0
  189. if (stat & LE_C0_ERR) {
  190. printf("%s: TX error (CSR0=%x)\n", __func__, stat);
  191. if (stat & LE_C0_CERR) {
  192. lereg->ler_rdp = LE_C0_CERR;
  193. }
  194. }
  195. #endif
  196. if (timeout++ > 1000) {
  197. printf("%s: TX timeout (CSR0=%x)\n", __func__, stat);
  198. return 0;
  199. }
  200. } while ((stat & LE_C0_TINT) == 0);
  201. lereg->ler_rdp = LE_C0_TINT;
  202. sc->sc_curtmd = LE_NEXTTMD(sc->sc_curtmd);
  203. return 1;
  204. }
  205. int
  206. lance_end(void *cookie)
  207. {
  208. struct le_softc *sc = cookie;
  209. struct lereg *lereg = sc->sc_reg;
  210. lereg->ler_rap = LE_CSR0;
  211. lereg->ler_rdp = LE_C0_STOP;
  212. return 1;
  213. }
  214. static int
  215. lance_set_initblock(struct le_softc *sc)
  216. {
  217. struct lereg *lereg = sc->sc_reg;
  218. uint32_t addr = (uint32_t)sc->sc_mem;
  219. lereg->ler_rap = LE_CSR0;
  220. lereg->ler_rdp = LE_C0_STOP; /* disable all external activity */
  221. DELAY(100);
  222. /* Set the correct byte swapping mode */
  223. lereg->ler_rap = LE_CSR3;
  224. lereg->ler_rdp = LE_C3_BSWP;
  225. /* Low address of init block */
  226. lereg->ler_rap = LE_CSR1;
  227. lereg->ler_rdp = addr & 0xfffe;
  228. /* High address of init block */
  229. lereg->ler_rap = LE_CSR2;
  230. lereg->ler_rdp = (addr >> 16) & 0x00ff;
  231. DELAY(100);
  232. return 1;
  233. }
  234. static int
  235. lance_do_initialize(struct le_softc *sc)
  236. {
  237. struct lereg *lereg = sc->sc_reg;
  238. uint16_t reg;
  239. int timeout;
  240. sc->sc_curtmd = 0;
  241. sc->sc_currmd = 0;
  242. /* Initialze LANCE */
  243. lereg->ler_rap = LE_CSR0;
  244. lereg->ler_rdp = LE_C0_INIT;
  245. /* Wait interrupt */
  246. timeout = 1000000;
  247. do {
  248. lereg->ler_rap = LE_CSR0;
  249. reg = lereg->ler_rdp;
  250. if (--timeout == 0) {
  251. printf("le: init timeout (CSR=0x%x)\n", reg);
  252. return 0;
  253. }
  254. DELAY(1);
  255. } while ((reg & LE_C0_IDON) == 0);
  256. lereg->ler_rap = LE_CSR0;
  257. lereg->ler_rdp = LE_C0_STRT | LE_C0_IDON;
  258. return 1;
  259. }
  260. static void
  261. lance_setup(struct le_softc *sc)
  262. {
  263. struct lereg *lereg = sc->sc_reg;
  264. struct lemem *lemem = sc->sc_mem;
  265. uint32_t addr;
  266. int i;
  267. /* make sure to stop LANCE chip before setup memory */
  268. lereg->ler_rap = LE_CSR0;
  269. lereg->ler_rdp = LE_C0_STOP;
  270. memset(lemem, 0, sizeof *lemem);
  271. /* Init block */
  272. lemem->lem_mode = LE_MODE_NORMAL;
  273. lemem->lem_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0];
  274. lemem->lem_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2];
  275. lemem->lem_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4];
  276. /* Logical address filter */
  277. for (i = 0; i < 4; i++)
  278. lemem->lem_ladrf[i] = 0x0000;
  279. /* Location of Rx descriptor ring */
  280. addr = (uint32_t)lemem->lem_rmd;
  281. lemem->lem_rdra = addr & 0xffff;
  282. lemem->lem_rlen = LE_RLEN | ((addr >> 16) & 0xff);
  283. /* Location of Tx descriptor ring */
  284. addr = (uint32_t)lemem->lem_tmd;
  285. lemem->lem_tdra = addr & 0xffff;
  286. lemem->lem_tlen = LE_TLEN | ((addr >> 16) & 0xff);
  287. /* Rx descriptor */
  288. for (i = 0; i < LERBUF; i++) {
  289. addr = (uint32_t)lemem->lem_rbuf[i];
  290. lemem->lem_rmd[i].rmd0 = addr & 0xffff;
  291. lemem->lem_rmd[i].rmd1_hadr = (addr >> 16) & 0xff;
  292. lemem->lem_rmd[i].rmd1_bits = LE_R1_OWN;
  293. lemem->lem_rmd[i].rmd2 = LE_XMD2_ONES | -LEMTU;
  294. lemem->lem_rmd[i].rmd3 = 0;
  295. }
  296. /* Tx descriptor */
  297. for (i = 0; i < LETBUF; i++) {
  298. addr = (uint32_t)lemem->lem_tbuf[i];
  299. lemem->lem_tmd[i].tmd0 = addr & 0xffff;
  300. lemem->lem_tmd[i].tmd1_hadr = (addr >> 16) & 0xff;
  301. lemem->lem_tmd[i].tmd1_bits = 0;
  302. lemem->lem_tmd[i].tmd2 = LE_XMD2_ONES | 0;
  303. lemem->lem_tmd[i].tmd3 = 0;
  304. }
  305. }