1 /* $NetBSD: if_le_ioasic.c,v 1.2 1996/05/07 02:24:56 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 /* 31 * LANCE on DEC IOCTL ASIC. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/mbuf.h> 37 #include <sys/syslog.h> 38 #include <sys/socket.h> 39 #include <sys/device.h> 40 41 #include <net/if.h> 42 43 #ifdef INET 44 #include <netinet/in.h> 45 #include <netinet/if_ether.h> 46 #endif 47 48 #include <dev/ic/am7990reg.h> 49 #include <dev/ic/am7990var.h> 50 51 #include <dev/tc/if_levar.h> 52 #include <dev/tc/tcvar.h> 53 #include <dev/tc/ioasicvar.h> 54 55 extern caddr_t le_iomem; 56 57 int le_ioasic_match __P((struct device *, void *, void *)); 58 void le_ioasic_attach __P((struct device *, struct device *, void *)); 59 60 hide void le_ioasic_copytobuf_gap2 __P((struct am7990_softc *, void *, 61 int, int)); 62 hide void le_ioasic_copyfrombuf_gap2 __P((struct am7990_softc *, void *, 63 int, int)); 64 65 hide void le_ioasic_copytobuf_gap16 __P((struct am7990_softc *, void *, 66 int, int)); 67 hide void le_ioasic_copyfrombuf_gap16 __P((struct am7990_softc *, void *, 68 int, int)); 69 hide void le_ioasic_zerobuf_gap16 __P((struct am7990_softc *, int, int)); 70 71 struct cfattach le_ioasic_ca = { 72 sizeof(struct le_softc), le_ioasic_match, le_ioasic_attach 73 }; 74 75 int 76 le_ioasic_match(parent, match, aux) 77 struct device *parent; 78 void *match, *aux; 79 { 80 struct ioasicdev_attach_args *d = aux; 81 82 if (!ioasic_submatch(match, aux)) 83 return (0); 84 if (strncmp("lance", d->iada_modname, TC_ROM_LLEN)) 85 return (0); 86 87 return (1); 88 } 89 90 void 91 le_ioasic_attach(parent, self, aux) 92 struct device *parent, *self; 93 void *aux; 94 { 95 struct ioasicdev_attach_args *d = aux; 96 register struct le_softc *lesc = (void *)self; 97 register struct am7990_softc *sc = &lesc->sc_am7990; 98 99 lesc->sc_r1 = (struct lereg1 *) 100 TC_DENSE_TO_SPARSE(TC_PHYS_TO_UNCACHED(d->iada_addr)); 101 sc->sc_mem = (void *)TC_PHYS_TO_UNCACHED(le_iomem); 102 103 sc->sc_copytodesc = le_ioasic_copytobuf_gap2; 104 sc->sc_copyfromdesc = le_ioasic_copyfrombuf_gap2; 105 sc->sc_copytobuf = le_ioasic_copytobuf_gap16; 106 sc->sc_copyfrombuf = le_ioasic_copyfrombuf_gap16; 107 sc->sc_zerobuf = le_ioasic_zerobuf_gap16; 108 109 ioasic_lance_dma_setup(le_iomem); /* XXX more thought */ 110 111 dec_le_common_attach(sc, ioasic_lance_ether_address()); 112 113 ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_NET, 114 am7990_intr, sc); 115 } 116 117 /* 118 * Special memory access functions needed by ioasic-attached LANCE 119 * chips. 120 */ 121 122 /* 123 * gap2: two bytes of data followed by two bytes of pad. 124 * 125 * Buffers must be 4-byte aligned. The code doesn't worry about 126 * doing an extra byte. 127 */ 128 129 void 130 le_ioasic_copytobuf_gap2(sc, fromv, boff, len) 131 struct am7990_softc *sc; 132 void *fromv; 133 int boff; 134 register int len; 135 { 136 volatile caddr_t buf = sc->sc_mem; 137 register caddr_t from = fromv; 138 register volatile u_int16_t *bptr; 139 140 if (boff & 0x1) { 141 /* handle unaligned first byte */ 142 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 143 *bptr = (*from++ << 8) | (*bptr & 0xff); 144 bptr += 2; 145 len--; 146 } else 147 bptr = ((volatile u_int16_t *)buf) + boff; 148 while (len > 1) { 149 *bptr = (from[1] << 8) | (from[0] & 0xff); 150 bptr += 2; 151 from += 2; 152 len -= 2; 153 } 154 if (len == 1) 155 *bptr = (u_int16_t)*from; 156 } 157 158 void 159 le_ioasic_copyfrombuf_gap2(sc, tov, boff, len) 160 struct am7990_softc *sc; 161 void *tov; 162 int boff, len; 163 { 164 volatile caddr_t buf = sc->sc_mem; 165 register caddr_t to = tov; 166 register volatile u_int16_t *bptr; 167 register u_int16_t tmp; 168 169 if (boff & 0x1) { 170 /* handle unaligned first byte */ 171 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 172 *to++ = (*bptr >> 8) & 0xff; 173 bptr += 2; 174 len--; 175 } else 176 bptr = ((volatile u_int16_t *)buf) + boff; 177 while (len > 1) { 178 tmp = *bptr; 179 *to++ = tmp & 0xff; 180 *to++ = (tmp >> 8) & 0xff; 181 bptr += 2; 182 len -= 2; 183 } 184 if (len == 1) 185 *to = *bptr & 0xff; 186 } 187 188 /* 189 * gap16: 16 bytes of data followed by 16 bytes of pad. 190 * 191 * Buffers must be 32-byte aligned. 192 */ 193 194 void 195 le_ioasic_copytobuf_gap16(sc, fromv, boff, len) 196 struct am7990_softc *sc; 197 void *fromv; 198 int boff; 199 register int len; 200 { 201 volatile caddr_t buf = sc->sc_mem; 202 register caddr_t from = fromv; 203 register caddr_t bptr; 204 register int xfer; 205 206 bptr = buf + ((boff << 1) & ~0x1f); 207 boff &= 0xf; 208 xfer = min(len, 16 - boff); 209 while (len > 0) { 210 bcopy(from, bptr + boff, xfer); 211 from += xfer; 212 bptr += 32; 213 boff = 0; 214 len -= xfer; 215 xfer = min(len, 16); 216 } 217 } 218 219 void 220 le_ioasic_copyfrombuf_gap16(sc, tov, boff, len) 221 struct am7990_softc *sc; 222 void *tov; 223 int boff, len; 224 { 225 volatile caddr_t buf = sc->sc_mem; 226 register caddr_t to = tov; 227 register caddr_t bptr; 228 register int xfer; 229 230 bptr = buf + ((boff << 1) & ~0x1f); 231 boff &= 0xf; 232 xfer = min(len, 16 - boff); 233 while (len > 0) { 234 bcopy(bptr + boff, to, xfer); 235 to += xfer; 236 bptr += 32; 237 boff = 0; 238 len -= xfer; 239 xfer = min(len, 16); 240 } 241 } 242 243 void 244 le_ioasic_zerobuf_gap16(sc, boff, len) 245 struct am7990_softc *sc; 246 int boff, len; 247 { 248 volatile caddr_t buf = sc->sc_mem; 249 register caddr_t bptr; 250 register int xfer; 251 252 bptr = buf + ((boff << 1) & ~0x1f); 253 boff &= 0xf; 254 xfer = min(len, 16 - boff); 255 while (len > 0) { 256 bzero(bptr + boff, xfer); 257 bptr += 32; 258 boff = 0; 259 len -= xfer; 260 xfer = min(len, 16); 261 } 262 } 263