1 /* $NetBSD: if_le_ibus.c,v 1.7 2002/10/02 04:15:09 thorpej Exp $ */ 2 3 /* 4 * Copyright 1996 The Board of Trustees of The Leland Stanford 5 * Junior University. All Rights Reserved. 6 * 7 * Permission to use, copy, modify, and distribute this 8 * software and its documentation for any purpose and without 9 * fee is hereby granted, provided that the above copyright 10 * notice appear in all copies. Stanford University 11 * makes no representations about the suitability of this 12 * software for any purpose. It is provided "as is" without 13 * express or implied warranty. 14 * 15 * This driver was contributed by Jonathan Stone. 16 */ 17 18 /* 19 * LANCE on Decstation kn01/kn220(?) baseboard. 20 */ 21 #include "opt_inet.h" 22 23 #include <sys/param.h> 24 #include <sys/socket.h> 25 #include <sys/systm.h> 26 27 #include <net/if.h> 28 #include <net/if_ether.h> 29 #include <net/if_media.h> 30 31 #ifdef INET 32 #include <netinet/in.h> 33 #include <netinet/if_inarp.h> 34 #endif 35 36 #include <dev/ic/lancevar.h> 37 #include <dev/ic/am7990var.h> 38 39 #include <dev/tc/if_levar.h> 40 #include <pmax/ibus/ibusvar.h> 41 #include <pmax/pmax/kn01.h> 42 43 static void le_dec_copyfrombuf_gap2(struct lance_softc *, void *, int, int); 44 static void le_dec_copytobuf_gap2(struct lance_softc *, void *, int, int); 45 static void le_dec_zerobuf_gap2(struct lance_softc *, int, int); 46 47 48 static int le_pmax_match(struct device *, struct cfdata *, void *); 49 static void le_pmax_attach(struct device *, struct device *, void *); 50 51 CFATTACH_DECL(le_pmax, sizeof(struct le_softc), 52 le_pmax_match, le_pmax_attach, NULL, NULL); 53 54 int 55 le_pmax_match(struct device *parent, struct cfdata *match, void *aux) 56 { 57 struct ibus_attach_args *d = aux; 58 59 if (strcmp("lance", d->ia_name) != 0) 60 return (0); 61 return (1); 62 } 63 64 void 65 le_pmax_attach(struct device *parent, struct device *self, void *aux) 66 { 67 struct le_softc *lesc = (void *)self; 68 struct lance_softc *sc = &lesc->sc_am7990.lsc; 69 u_char *cp; 70 struct ibus_attach_args *ia = aux; 71 72 /* 73 * It's on the baseboard, with a dedicated interrupt line. 74 */ 75 lesc->sc_r1 = (struct lereg1 *)(ia->ia_addr); 76 sc->sc_mem = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_LANCE_B_START); 77 cp = (u_char *)(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK) + 1); 78 79 sc->sc_copytodesc = le_dec_copytobuf_gap2; 80 sc->sc_copyfromdesc = le_dec_copyfrombuf_gap2; 81 sc->sc_copytobuf = le_dec_copytobuf_gap2; 82 sc->sc_copyfrombuf = le_dec_copyfrombuf_gap2; 83 sc->sc_zerobuf = le_dec_zerobuf_gap2; 84 85 dec_le_common_attach(&lesc->sc_am7990, cp); 86 87 ibus_intr_establish(parent, (void*)ia->ia_cookie, IPL_NET, 88 am7990_intr, sc); 89 } 90 91 /* 92 * gap2: two bytes of data followed by two bytes of pad. 93 * 94 * Buffers must be 4-byte aligned. The code doesn't worry about 95 * doing an extra byte. 96 */ 97 98 void 99 le_dec_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len) 100 { 101 volatile caddr_t buf = sc->sc_mem; 102 caddr_t from = fromv; 103 volatile u_int16_t *bptr; 104 105 if (boff & 0x1) { 106 /* handle unaligned first byte */ 107 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 108 *bptr = (*from++ << 8) | (*bptr & 0xff); 109 bptr += 2; 110 len--; 111 } else 112 bptr = ((volatile u_int16_t *)buf) + boff; 113 while (len > 1) { 114 *bptr = (from[1] << 8) | (from[0] & 0xff); 115 bptr += 2; 116 from += 2; 117 len -= 2; 118 } 119 if (len == 1) 120 *bptr = (u_int16_t)*from; 121 } 122 123 void 124 le_dec_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len) 125 { 126 volatile caddr_t buf = sc->sc_mem; 127 caddr_t to = tov; 128 volatile u_int16_t *bptr; 129 u_int16_t tmp; 130 131 if (boff & 0x1) { 132 /* handle unaligned first byte */ 133 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 134 *to++ = (*bptr >> 8) & 0xff; 135 bptr += 2; 136 len--; 137 } else 138 bptr = ((volatile u_int16_t *)buf) + boff; 139 while (len > 1) { 140 tmp = *bptr; 141 *to++ = tmp & 0xff; 142 *to++ = (tmp >> 8) & 0xff; 143 bptr += 2; 144 len -= 2; 145 } 146 if (len == 1) 147 *to = *bptr & 0xff; 148 } 149 150 static void 151 le_dec_zerobuf_gap2(struct lance_softc *sc, int boff, int len) 152 { 153 volatile caddr_t buf = sc->sc_mem; 154 volatile u_int16_t *bptr; 155 156 if ((unsigned)boff & 0x1) { 157 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 158 *bptr &= 0xff; 159 bptr += 2; 160 len--; 161 } else 162 bptr = ((volatile u_int16_t *)buf) + boff; 163 while (len > 0) { 164 *bptr = 0; 165 bptr += 2; 166 len -= 2; 167 } 168 } 169