1 1.6 mrg /* $NetBSD: le_poll.c,v 1.6 2018/03/08 03:12:02 mrg Exp $ */ 2 1.1 chuck 3 1.1 chuck /* 4 1.1 chuck * Copyright (c) 1993 Adam Glass 5 1.1 chuck * All rights reserved. 6 1.1 chuck * 7 1.1 chuck * Redistribution and use in source and binary forms, with or without 8 1.1 chuck * modification, are permitted provided that the following conditions 9 1.1 chuck * are met: 10 1.1 chuck * 1. Redistributions of source code must retain the above copyright 11 1.1 chuck * notice, this list of conditions and the following disclaimer. 12 1.1 chuck * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 chuck * notice, this list of conditions and the following disclaimer in the 14 1.1 chuck * documentation and/or other materials provided with the distribution. 15 1.1 chuck * 3. All advertising materials mentioning features or use of this software 16 1.1 chuck * must display the following acknowledgement: 17 1.1 chuck * This product includes software developed by Adam Glass. 18 1.1 chuck * 4. The name of the Author may not be used to endorse or promote products 19 1.1 chuck * derived from this software without specific prior written permission. 20 1.1 chuck * 21 1.1 chuck * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND 22 1.1 chuck * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 1.1 chuck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 1.1 chuck * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 1.1 chuck * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 1.1 chuck * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 1.1 chuck * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 1.1 chuck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 1.1 chuck * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 1.1 chuck * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 1.1 chuck * SUCH DAMAGE. 32 1.1 chuck */ 33 1.1 chuck 34 1.1 chuck #include "sboot.h" 35 1.1 chuck #include "if_lereg.h" 36 1.1 chuck 37 1.1 chuck struct { 38 1.1 chuck struct lereg1 *sc_r1; /* LANCE registers */ 39 1.1 chuck struct lereg2 *sc_r2; /* RAM */ 40 1.1 chuck int next_rmd; 41 1.1 chuck int next_tmd; 42 1.1 chuck } le_softc; 43 1.1 chuck 44 1.2 jdolecek static void le_error(const char *, struct lereg1 *); 45 1.2 jdolecek static void le_reset(u_char *); 46 1.2 jdolecek static int le_poll(void *, int); 47 1.2 jdolecek 48 1.2 jdolecek static void 49 1.5 tsutsui le_error(const char *str, struct lereg1 *ler1) 50 1.1 chuck { 51 1.5 tsutsui 52 1.5 tsutsui /* ler1->ler1_rap = LE_CSRO done in caller */ 53 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_BABL) { 54 1.5 tsutsui printf("le0: been babbling, found by '%s'\n", str); 55 1.5 tsutsui callrom(); 56 1.5 tsutsui } 57 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_CERR) { 58 1.5 tsutsui ler1->ler1_rdp = LE_C0_CERR; 59 1.5 tsutsui } 60 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_MISS) { 61 1.5 tsutsui ler1->ler1_rdp = LE_C0_MISS; 62 1.5 tsutsui } 63 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_MERR) { 64 1.5 tsutsui printf("le0: memory error in '%s'\n", str); 65 1.5 tsutsui callrom(); 66 1.5 tsutsui } 67 1.1 chuck } 68 1.1 chuck 69 1.2 jdolecek static void 70 1.5 tsutsui le_reset(u_char *myea) 71 1.1 chuck { 72 1.5 tsutsui struct lereg1 *ler1 = le_softc.sc_r1; 73 1.5 tsutsui struct lereg2 *ler2 = le_softc.sc_r2; 74 1.5 tsutsui unsigned int a; 75 1.5 tsutsui int timo = 100000, stat = 0, i; 76 1.5 tsutsui 77 1.5 tsutsui ler1->ler1_rap = LE_CSR0; 78 1.5 tsutsui ler1->ler1_rdp = LE_C0_STOP; /* do nothing until we are finished */ 79 1.5 tsutsui 80 1.5 tsutsui memset(ler2, 0, sizeof(*ler2)); 81 1.5 tsutsui 82 1.5 tsutsui ler2->ler2_mode = LE_MODE_NORMAL; 83 1.5 tsutsui ler2->ler2_padr[0] = myea[1]; 84 1.5 tsutsui ler2->ler2_padr[1] = myea[0]; 85 1.5 tsutsui ler2->ler2_padr[2] = myea[3]; 86 1.5 tsutsui ler2->ler2_padr[3] = myea[2]; 87 1.5 tsutsui ler2->ler2_padr[4] = myea[5]; 88 1.5 tsutsui ler2->ler2_padr[5] = myea[4]; 89 1.5 tsutsui 90 1.5 tsutsui 91 1.5 tsutsui ler2->ler2_ladrf0 = 0; 92 1.5 tsutsui ler2->ler2_ladrf1 = 0; 93 1.5 tsutsui 94 1.5 tsutsui a = (u_int)ler2->ler2_rmd; 95 1.5 tsutsui ler2->ler2_rlen = LE_RLEN | (a >> 16); 96 1.5 tsutsui ler2->ler2_rdra = a & LE_ADDR_LOW_MASK; 97 1.5 tsutsui 98 1.5 tsutsui a = (u_int)ler2->ler2_tmd; 99 1.5 tsutsui ler2->ler2_tlen = LE_TLEN | (a >> 16); 100 1.5 tsutsui ler2->ler2_tdra = a & LE_ADDR_LOW_MASK; 101 1.5 tsutsui 102 1.5 tsutsui ler1->ler1_rap = LE_CSR1; 103 1.5 tsutsui a = (u_int)ler2; 104 1.5 tsutsui ler1->ler1_rdp = a & LE_ADDR_LOW_MASK; 105 1.5 tsutsui ler1->ler1_rap = LE_CSR2; 106 1.5 tsutsui ler1->ler1_rdp = a >> 16; 107 1.5 tsutsui 108 1.5 tsutsui for (i = 0; i < LERBUF; i++) { 109 1.5 tsutsui a = (u_int)&ler2->ler2_rbuf[i]; 110 1.5 tsutsui ler2->ler2_rmd[i].rmd0 = a & LE_ADDR_LOW_MASK; 111 1.5 tsutsui ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN; 112 1.5 tsutsui ler2->ler2_rmd[i].rmd1_hadr = a >> 16; 113 1.5 tsutsui ler2->ler2_rmd[i].rmd2 = -LEMTU; 114 1.5 tsutsui ler2->ler2_rmd[i].rmd3 = 0; 115 1.5 tsutsui } 116 1.5 tsutsui for (i = 0; i < LETBUF; i++) { 117 1.5 tsutsui a = (u_int)&ler2->ler2_tbuf[i]; 118 1.5 tsutsui ler2->ler2_tmd[i].tmd0 = a & LE_ADDR_LOW_MASK; 119 1.5 tsutsui ler2->ler2_tmd[i].tmd1_bits = 0; 120 1.5 tsutsui ler2->ler2_tmd[i].tmd1_hadr = a >> 16; 121 1.5 tsutsui ler2->ler2_tmd[i].tmd2 = 0; 122 1.5 tsutsui ler2->ler2_tmd[i].tmd3 = 0; 123 1.1 chuck } 124 1.5 tsutsui 125 1.5 tsutsui ler1->ler1_rap = LE_CSR3; 126 1.5 tsutsui ler1->ler1_rdp = LE_C3_BSWP; 127 1.5 tsutsui 128 1.5 tsutsui ler1->ler1_rap = LE_CSR0; 129 1.5 tsutsui ler1->ler1_rdp = LE_C0_INIT; 130 1.5 tsutsui do { 131 1.5 tsutsui if (--timo == 0) { 132 1.5 tsutsui printf("le0: init timeout, stat = 0x%x\n", stat); 133 1.5 tsutsui break; 134 1.5 tsutsui } 135 1.5 tsutsui stat = ler1->ler1_rdp; 136 1.5 tsutsui } while ((stat & LE_C0_IDON) == 0); 137 1.1 chuck 138 1.5 tsutsui ler1->ler1_rdp = LE_C0_IDON; 139 1.5 tsutsui le_softc.next_rmd = 0; 140 1.5 tsutsui le_softc.next_tmd = 0; 141 1.5 tsutsui ler1->ler1_rap = LE_CSR0; 142 1.5 tsutsui ler1->ler1_rdp = LE_C0_STRT; 143 1.1 chuck } 144 1.1 chuck 145 1.2 jdolecek static int 146 1.5 tsutsui le_poll(void *pkt, int len) 147 1.1 chuck { 148 1.5 tsutsui struct lereg1 *ler1 = le_softc.sc_r1; 149 1.5 tsutsui struct lereg2 *ler2 = le_softc.sc_r2; 150 1.5 tsutsui unsigned int a; 151 1.5 tsutsui int length; 152 1.5 tsutsui struct lermd *rmd; 153 1.5 tsutsui 154 1.5 tsutsui ler1->ler1_rap = LE_CSR0; 155 1.5 tsutsui if ((ler1->ler1_rdp & LE_C0_RINT) != 0) 156 1.5 tsutsui ler1->ler1_rdp = LE_C0_RINT; 157 1.5 tsutsui rmd = &ler2->ler2_rmd[le_softc.next_rmd]; 158 1.5 tsutsui if (rmd->rmd1_bits & LE_R1_OWN) { 159 1.5 tsutsui return 0; 160 1.5 tsutsui } 161 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_ERR) 162 1.5 tsutsui le_error("le_poll", ler1); 163 1.5 tsutsui if (rmd->rmd1_bits & LE_R1_ERR) { 164 1.5 tsutsui printf("le0_poll: rmd status 0x%x\n", rmd->rmd1_bits); 165 1.5 tsutsui length = 0; 166 1.5 tsutsui goto cleanup; 167 1.5 tsutsui } 168 1.5 tsutsui if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) != (LE_R1_STP|LE_R1_ENP)) { 169 1.5 tsutsui printf("le_poll: chained packet\n"); 170 1.5 tsutsui callrom(); 171 1.5 tsutsui } 172 1.5 tsutsui 173 1.5 tsutsui length = rmd->rmd3; 174 1.5 tsutsui if (length >= LEMTU) { 175 1.5 tsutsui length = 0; 176 1.5 tsutsui printf("csr0 when bad things happen: %x\n", ler1->ler1_rdp); 177 1.5 tsutsui callrom(); 178 1.5 tsutsui goto cleanup; 179 1.5 tsutsui } 180 1.5 tsutsui if (length == 0) 181 1.5 tsutsui goto cleanup; 182 1.5 tsutsui length -= 4; 183 1.5 tsutsui if (length > 0) 184 1.5 tsutsui memcpy(pkt, (char *)&ler2->ler2_rbuf[le_softc.next_rmd], 185 1.5 tsutsui length); 186 1.1 chuck 187 1.1 chuck cleanup: 188 1.5 tsutsui a = (u_int)&ler2->ler2_rbuf[le_softc.next_rmd]; 189 1.5 tsutsui rmd->rmd0 = a & LE_ADDR_LOW_MASK; 190 1.5 tsutsui rmd->rmd1_hadr = a >> 16; 191 1.5 tsutsui rmd->rmd2 = -LEMTU; 192 1.5 tsutsui le_softc.next_rmd = 193 1.5 tsutsui (le_softc.next_rmd == (LERBUF - 1)) ? 0 : (le_softc.next_rmd + 1); 194 1.5 tsutsui rmd->rmd1_bits = LE_R1_OWN; 195 1.5 tsutsui return length; 196 1.1 chuck } 197 1.1 chuck 198 1.5 tsutsui int le_put(u_char *pkt, size_t len) 199 1.1 chuck { 200 1.5 tsutsui struct lereg1 *ler1 = le_softc.sc_r1; 201 1.5 tsutsui struct lereg2 *ler2 = le_softc.sc_r2; 202 1.5 tsutsui struct letmd *tmd; 203 1.5 tsutsui int timo = 100000, stat = 0; 204 1.5 tsutsui unsigned int a; 205 1.5 tsutsui 206 1.5 tsutsui ler1->ler1_rap = LE_CSR0; 207 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_ERR) 208 1.5 tsutsui le_error("le_put(way before xmit)", ler1); 209 1.5 tsutsui tmd = &ler2->ler2_tmd[le_softc.next_tmd]; 210 1.5 tsutsui while (tmd->tmd1_bits & LE_T1_OWN) { 211 1.5 tsutsui printf("le0: output buffer busy\n"); 212 1.5 tsutsui } 213 1.5 tsutsui memcpy((char *)ler2->ler2_tbuf[le_softc.next_tmd], pkt, len); 214 1.5 tsutsui if (len < 64) 215 1.5 tsutsui tmd->tmd2 = -64; 216 1.5 tsutsui else 217 1.5 tsutsui tmd->tmd2 = -len; 218 1.5 tsutsui tmd->tmd3 = 0; 219 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_ERR) 220 1.5 tsutsui le_error("le_put(before xmit)", ler1); 221 1.5 tsutsui tmd->tmd1_bits = LE_T1_STP | LE_T1_ENP | LE_T1_OWN; 222 1.5 tsutsui a = (u_int)&ler2->ler2_tbuf[le_softc.next_tmd]; 223 1.5 tsutsui tmd->tmd0 = a & LE_ADDR_LOW_MASK; 224 1.5 tsutsui tmd->tmd1_hadr = a >> 16; 225 1.5 tsutsui ler1->ler1_rdp = LE_C0_TDMD; 226 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_ERR) 227 1.5 tsutsui le_error("le_put(after xmit)", ler1); 228 1.5 tsutsui do { 229 1.5 tsutsui if (--timo == 0) { 230 1.5 tsutsui printf("le0: transmit timeout, stat = 0x%x\n", 231 1.5 tsutsui stat); 232 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_ERR) 233 1.5 tsutsui le_error("le_put(timeout)", ler1); 234 1.5 tsutsui break; 235 1.5 tsutsui } 236 1.5 tsutsui stat = ler1->ler1_rdp; 237 1.5 tsutsui } while ((stat & LE_C0_TINT) == 0); 238 1.5 tsutsui ler1->ler1_rdp = LE_C0_TINT; 239 1.5 tsutsui if (ler1->ler1_rdp & LE_C0_ERR) { 240 1.5 tsutsui if ((ler1->ler1_rdp & 241 1.5 tsutsui (LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR)) != 242 1.6 mrg LE_C0_CERR) { 243 1.5 tsutsui printf("le_put: xmit error, buf %d\n", 244 1.5 tsutsui le_softc.next_tmd); 245 1.5 tsutsui le_error("le_put(xmit error)", ler1); 246 1.5 tsutsui } 247 1.5 tsutsui le_softc.next_tmd = 0; 248 1.5 tsutsui #if 0 249 1.5 tsutsui (le_softc.next_tmd == (LETBUF - 1)) ? 0 : le_softc.next_tmd + 1; 250 1.5 tsutsui #endif 251 1.6 mrg if (tmd->tmd1_bits & LE_T1_ERR) 252 1.5 tsutsui printf("le0: transmit error, error = 0x%x\n", 253 1.5 tsutsui tmd->tmd3); 254 1.5 tsutsui return -1; 255 1.5 tsutsui } 256 1.5 tsutsui return len; 257 1.1 chuck } 258 1.1 chuck 259 1.5 tsutsui int le_get(u_char *pkt, size_t len, u_long timeout) 260 1.1 chuck { 261 1.5 tsutsui int cc; 262 1.5 tsutsui int now, then; 263 1.5 tsutsui int stopat = time() + timeout; 264 1.5 tsutsui then = 0; 265 1.5 tsutsui 266 1.5 tsutsui cc = 0; 267 1.5 tsutsui while ((now = time()) < stopat && !cc) { 268 1.5 tsutsui cc = le_poll(pkt, len); 269 1.5 tsutsui if (then != now) { 270 1.1 chuck #ifdef LE_DEBUG 271 1.5 tsutsui printf("%d \r", stopat - now); 272 1.1 chuck #endif 273 1.5 tsutsui then = now; 274 1.5 tsutsui } 275 1.5 tsutsui if (cc && (pkt[0] != myea[0] || pkt[1] != myea[1] || 276 1.5 tsutsui pkt[2] != myea[2] || pkt[3] != myea[3] || 277 1.5 tsutsui pkt[4] != myea[4] || pkt[5] != myea[5])) { 278 1.5 tsutsui cc = 0; /* ignore broadcast / multicast */ 279 1.1 chuck #ifdef LE_DEBUG 280 1.5 tsutsui printf("reject (%d sec left)\n", stopat - now); 281 1.1 chuck #endif 282 1.5 tsutsui } 283 1.5 tsutsui } 284 1.1 chuck #ifdef LE_DEBUG 285 1.5 tsutsui printf("\n"); 286 1.1 chuck #endif 287 1.5 tsutsui return cc; 288 1.1 chuck } 289 1.1 chuck 290 1.5 tsutsui void le_init(void) 291 1.1 chuck { 292 1.5 tsutsui int *ea = (int *)LANCE_ADDR; 293 1.5 tsutsui u_long *eram = (u_long *)ERAM_ADDR; 294 1.5 tsutsui u_long e = *ea; 295 1.5 tsutsui 296 1.5 tsutsui if ((e & 0x2fffff00) == 0x2fffff00) { 297 1.5 tsutsui printf("ERROR: ethernet address not set! Use LSAD.\n"); 298 1.5 tsutsui callrom(); 299 1.5 tsutsui } 300 1.5 tsutsui myea[0] = 0x08; 301 1.5 tsutsui myea[1] = 0x00; 302 1.5 tsutsui myea[2] = 0x3e; 303 1.5 tsutsui e = e >> 8; 304 1.5 tsutsui myea[5] = e & 0xff; 305 1.5 tsutsui e = e >> 8; 306 1.5 tsutsui myea[4] = e & 0xff; 307 1.5 tsutsui e = e >> 8; 308 1.5 tsutsui myea[3] = e; 309 1.5 tsutsui printf("le0: ethernet address: %x:%x:%x:%x:%x:%x\n", 310 1.5 tsutsui myea[0], myea[1], myea[2], myea[3], myea[4], myea[5]); 311 1.5 tsutsui memset(&le_softc, 0, sizeof(le_softc)); 312 1.5 tsutsui le_softc.sc_r1 = (struct lereg1 *)LANCE_REG_ADDR; 313 1.5 tsutsui le_softc.sc_r2 = (struct lereg2 *)(*eram - (1024*1024)); 314 1.5 tsutsui le_reset(myea); 315 1.1 chuck } 316 1.1 chuck 317 1.5 tsutsui void le_end(void) 318 1.1 chuck { 319 1.5 tsutsui struct lereg1 *ler1 = le_softc.sc_r1; 320 1.1 chuck 321 1.5 tsutsui ler1->ler1_rap = LE_CSR0; 322 1.5 tsutsui ler1->ler1_rdp = LE_C0_STOP; 323 1.1 chuck } 324