Home | History | Annotate | Line # | Download | only in boot
      1 /*	$NetBSD: lance.c,v 1.5 2021/12/05 03:04:41 msaitoh Exp $	*/
      2 
      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 /*
     56  * LANCE driver for LUNA
     57  * based on sys/arch/ews4800mips/stand/common/lance.c
     58  */
     59 
     60 #include <lib/libsa/stand.h>
     61 #include <lib/libkern/libkern.h>
     62 
     63 #include <dev/ic/am7990reg.h>
     64 #include <dev/ic/lancereg.h>
     65 
     66 #include <luna68k/stand/boot/samachdep.h>
     67 #include <luna68k/stand/boot/lance.h>
     68 
     69 static void lance_setup(struct le_softc *);
     70 static bool lance_set_initblock(struct le_softc *);
     71 static bool lance_do_initialize(struct le_softc *);
     72 
     73 #define NLE	1	/* XXX for now */
     74 static struct le_softc lesc[NLE];
     75 
     76 void *
     77 lance_attach(int unit, void *reg, void *mem, uint8_t *eaddr)
     78 {
     79 	struct le_softc *sc;
     80 
     81 	if (unit >= NLE) {
     82 		printf("%s: invalid unit number\n", __func__);
     83 		return NULL;
     84 	}
     85 	sc = &lesc[unit];
     86 
     87 	if (sc->sc_reg != NULL) {
     88 		printf("%s: unit %d is already attached\n", __func__, unit);
     89 		return NULL;
     90 	}
     91 	sc->sc_reg = reg;
     92 	sc->sc_mem = mem;
     93 	memcpy(sc->sc_enaddr, eaddr, 6);
     94 
     95 	return sc;
     96 }
     97 
     98 void *
     99 lance_cookie(int unit)
    100 {
    101 	struct le_softc *sc;
    102 
    103 	if (unit >= NLE)
    104 		return NULL;
    105 
    106 	sc = &lesc[unit];
    107 
    108 	if (sc->sc_reg == NULL)
    109 		return NULL;
    110 
    111 	return sc;
    112 }
    113 
    114 uint8_t *
    115 lance_eaddr(void *cookie)
    116 {
    117 	struct le_softc *sc = cookie;
    118 
    119 	if (sc == NULL || sc->sc_reg == NULL)
    120 		return NULL;
    121 
    122 	return sc->sc_enaddr;
    123 }
    124 
    125 bool
    126 lance_init(void *cookie)
    127 {
    128 	struct le_softc *sc = cookie;
    129 
    130 	lance_setup(sc);
    131 
    132 	if (!lance_set_initblock(sc))
    133 		return false;
    134 
    135 	if (!lance_do_initialize(sc))
    136 		return false;
    137 
    138 	return true;
    139 }
    140 
    141 int
    142 lance_get(void *cookie, void *data, size_t maxlen)
    143 {
    144 	struct le_softc *sc = cookie;
    145 	struct lereg *lereg = sc->sc_reg;
    146 	struct lemem *lemem = sc->sc_mem;
    147 	struct lermd_v *rmd;
    148 	uint16_t csr __unused;
    149 	int len = -1;
    150 
    151 	lereg->ler_rap = LE_CSR0;
    152 	if ((lereg->ler_rdp & LE_C0_RINT) != 0)
    153 		lereg->ler_rdp = LE_C0_RINT;
    154 	rmd = &lemem->lem_rmd[sc->sc_currmd];
    155 	if ((rmd->rmd1_bits & LE_R1_OWN) != 0)
    156 		return -1;
    157 
    158 	csr = lereg->ler_rdp;
    159 #if 0
    160 	if ((csr & LE_C0_ERR) != 0)
    161 		printf("%s: RX poll error (CSR=0x%x)\n", __func__, csr);
    162 #endif
    163 	if ((rmd->rmd1_bits & LE_R1_ERR) != 0) {
    164 		printf("%s: RX error (rmd status=0x%x)\n", __func__,
    165 		    rmd->rmd1_bits);
    166 		goto out;
    167 	}
    168 
    169 	len = rmd->rmd3;
    170 	if (len < LEMINSIZE + 4 || len > LEMTU) {
    171 		printf("%s: RX error (bad length %d)\n", __func__, len);
    172 		goto out;
    173 	}
    174 	len -= 4;
    175 	memcpy(data, (void *)lemem->lem_rbuf[sc->sc_currmd], uimin(len, maxlen));
    176 
    177  out:
    178 	rmd->rmd2 = -LEMTU;
    179 	rmd->rmd1_bits = LE_R1_OWN;	/* return to LANCE */
    180 	sc->sc_currmd = LE_NEXTRMD(sc->sc_currmd);
    181 
    182 	return len;
    183 }
    184 
    185 bool
    186 lance_put(void *cookie, void *data, size_t len)
    187 {
    188 	struct le_softc *sc = cookie;
    189 	struct lereg *lereg = sc->sc_reg;
    190 	struct lemem *lemem = sc->sc_mem;
    191 	struct letmd_v *tmd;
    192 	uint16_t stat;
    193 	int timeout;
    194 
    195 	lereg->ler_rap = LE_CSR0;
    196 	stat = lereg->ler_rdp;
    197 	lereg->ler_rdp =
    198 	    stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_TINT);
    199 #if 0
    200 	if (stat & (LE_C0_BABL | LE_C0_CERR | LE_C0_MISS | LE_C0_MERR))
    201 		printf("%s: TX error before xmit csr0=0x%x\n",
    202 		    __func__, stat);
    203 #endif
    204 
    205 	/* setup TX descriptor */
    206 	tmd = &lemem->lem_tmd[sc->sc_curtmd];
    207 	while (tmd->tmd1_bits & LE_T1_OWN)
    208 		continue;
    209 	tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP;
    210 	memcpy((void *)lemem->lem_tbuf[sc->sc_curtmd], data, len);
    211 	tmd->tmd2 = -uimax(len, LEMINSIZE);
    212 	tmd->tmd3 = 0;
    213 
    214 	/* start TX */
    215 	tmd->tmd1_bits |= LE_T1_OWN;
    216 	lereg->ler_rap = LE_CSR0;
    217 	lereg->ler_rdp = LE_C0_TDMD;
    218 
    219 	/* check TX complete */
    220 	timeout = 0;
    221 	do {
    222 		lereg->ler_rap = LE_CSR0;
    223 		stat = lereg->ler_rdp;
    224 #if 0
    225 		if (stat & LE_C0_ERR) {
    226 			printf("%s: TX error (CSR0=%x)\n", __func__, stat);
    227 			if (stat & LE_C0_CERR) {
    228 				lereg->ler_rdp = LE_C0_CERR;
    229 			}
    230 		}
    231 #endif
    232 		if (timeout++ > 1000) {
    233 			printf("%s: TX timeout (CSR0=%x)\n", __func__, stat);
    234 			return false;
    235 		}
    236 	} while ((stat & LE_C0_TINT) == 0);
    237 
    238 	lereg->ler_rdp = LE_C0_TINT;
    239 
    240 	sc->sc_curtmd = LE_NEXTTMD(sc->sc_curtmd);
    241 
    242 	return true;
    243 }
    244 
    245 bool
    246 lance_end(void *cookie)
    247 {
    248 	struct le_softc *sc = cookie;
    249 	struct lereg *lereg = sc->sc_reg;
    250 
    251 	lereg->ler_rap = LE_CSR0;
    252 	lereg->ler_rdp = LE_C0_STOP;
    253 
    254 	return true;
    255 }
    256 
    257 /* XXX */
    258 int
    259 lance_intr(void)
    260 {
    261 
    262 	return 1;
    263 }
    264 
    265 static bool
    266 lance_set_initblock(struct le_softc *sc)
    267 {
    268 	struct lereg *lereg = sc->sc_reg;
    269 	uint32_t addr = (uint32_t)sc->sc_mem;
    270 
    271 	lereg->ler_rap = LE_CSR0;
    272 	lereg->ler_rdp = LE_C0_STOP;	/* disable all external activity */
    273 	DELAY(100);
    274 
    275 	/* Set the correct byte swapping mode */
    276 	lereg->ler_rap = LE_CSR3;
    277 	lereg->ler_rdp = LE_C3_BSWP;
    278 
    279 	/* Low address of init block */
    280 	lereg->ler_rap = LE_CSR1;
    281 	lereg->ler_rdp = addr & 0xfffe;
    282 
    283 	/* High address of init block */
    284 	lereg->ler_rap = LE_CSR2;
    285 	lereg->ler_rdp = (addr >> 16) & 0x00ff;
    286 	DELAY(100);
    287 
    288 	return true;
    289 }
    290 
    291 static bool
    292 lance_do_initialize(struct le_softc *sc)
    293 {
    294 	struct lereg *lereg = sc->sc_reg;
    295 	uint16_t reg;
    296 	int timeout;
    297 
    298 	sc->sc_curtmd = 0;
    299 	sc->sc_currmd = 0;
    300 
    301 	/* Initialize LANCE */
    302 	lereg->ler_rap = LE_CSR0;
    303 	lereg->ler_rdp = LE_C0_INIT;
    304 
    305 	/* Wait interrupt */
    306 	timeout = 1000000;
    307 	do {
    308 		lereg->ler_rap = LE_CSR0;
    309 		reg = lereg->ler_rdp;
    310 		if (--timeout == 0) {
    311 			printf("le: init timeout (CSR=0x%x)\n", reg);
    312 			return false;
    313 		}
    314 		DELAY(1);
    315 	} while ((reg & LE_C0_IDON) == 0);
    316 
    317 	lereg->ler_rap = LE_CSR0;
    318 	lereg->ler_rdp = LE_C0_STRT | LE_C0_IDON;
    319 
    320 	return true;
    321 }
    322 
    323 static void
    324 lance_setup(struct le_softc *sc)
    325 {
    326 	struct lereg *lereg = sc->sc_reg;
    327 	struct lemem *lemem = sc->sc_mem;
    328 	uint32_t addr;
    329 	int i;
    330 
    331 	/* make sure to stop LANCE chip before setup memory */
    332 	lereg->ler_rap = LE_CSR0;
    333 	lereg->ler_rdp = LE_C0_STOP;
    334 
    335 	memset(lemem, 0, sizeof *lemem);
    336 
    337 	/* Init block */
    338 	lemem->lem_mode = LE_MODE_NORMAL;
    339 	lemem->lem_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0];
    340 	lemem->lem_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2];
    341 	lemem->lem_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4];
    342 	/* Logical address filter */
    343 	for (i = 0; i < 4; i++)
    344 		lemem->lem_ladrf[i] = 0x0000;
    345 
    346 	/* Location of Rx descriptor ring */
    347 	addr = (uint32_t)lemem->lem_rmd;
    348 	lemem->lem_rdra = addr & 0xffff;
    349 	lemem->lem_rlen = LE_RLEN | ((addr >> 16) & 0xff);
    350 
    351 	/* Location of Tx descriptor ring */
    352 	addr = (uint32_t)lemem->lem_tmd;
    353 	lemem->lem_tdra = addr & 0xffff;
    354 	lemem->lem_tlen = LE_TLEN | ((addr >> 16) & 0xff);
    355 
    356 	/* Rx descriptor */
    357 	for (i = 0; i < LERBUF; i++) {
    358 		addr = (uint32_t)lemem->lem_rbuf[i];
    359 		lemem->lem_rmd[i].rmd0 = addr & 0xffff;
    360 		lemem->lem_rmd[i].rmd1_hadr = (addr >> 16) & 0xff;
    361 		lemem->lem_rmd[i].rmd1_bits = LE_R1_OWN;
    362 		lemem->lem_rmd[i].rmd2 = LE_XMD2_ONES | -LEMTU;
    363 		lemem->lem_rmd[i].rmd3 = 0;
    364 	}
    365 
    366 	/* Tx descriptor */
    367 	for (i = 0; i < LETBUF; i++) {
    368 		addr = (uint32_t)lemem->lem_tbuf[i];
    369 		lemem->lem_tmd[i].tmd0 = addr & 0xffff;
    370 		lemem->lem_tmd[i].tmd1_hadr = (addr >> 16) & 0xff;
    371 		lemem->lem_tmd[i].tmd1_bits = 0;
    372 		lemem->lem_tmd[i].tmd2 = LE_XMD2_ONES | 0;
    373 		lemem->lem_tmd[i].tmd3 = 0;
    374 	}
    375 }
    376