1 /* $NetBSD: if_le_ibus.c,v 1.3 2002/01/08 17:10:28 chs 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 struct cfattach le_pmax_ca = { 52 sizeof(struct le_softc), le_pmax_match, le_pmax_attach 53 }; 54 extern struct cfdriver ibus_cd; 55 56 int 57 le_pmax_match(struct device *parent, struct cfdata *match, void *aux) 58 { 59 struct ibus_attach_args *d = aux; 60 61 if (parent->dv_cfdata->cf_driver != &ibus_cd) 62 return (0); 63 64 if (strcmp("lance", d->ia_name) != 0) 65 return (0); 66 return (1); 67 } 68 69 void 70 le_pmax_attach(struct device *parent, struct device *self, void *aux) 71 { 72 struct le_softc *lesc = (void *)self; 73 struct lance_softc *sc = &lesc->sc_am7990.lsc; 74 u_char *cp; 75 struct ibus_attach_args *ia = aux; 76 77 /* 78 * It's on the baseboard, with a dedicated interrupt line. 79 */ 80 lesc->sc_r1 = (struct lereg1 *)(ia->ia_addr); 81 sc->sc_mem = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_LANCE_B_START); 82 cp = (u_char *)(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK) + 1); 83 84 sc->sc_copytodesc = le_dec_copytobuf_gap2; 85 sc->sc_copyfromdesc = le_dec_copyfrombuf_gap2; 86 sc->sc_copytobuf = le_dec_copytobuf_gap2; 87 sc->sc_copyfrombuf = le_dec_copyfrombuf_gap2; 88 sc->sc_zerobuf = le_dec_zerobuf_gap2; 89 90 dec_le_common_attach(&lesc->sc_am7990, cp); 91 92 ibus_intr_establish(parent, (void*)ia->ia_cookie, IPL_NET, 93 am7990_intr, sc); 94 } 95 96 /* 97 * gap2: two bytes of data followed by two bytes of pad. 98 * 99 * Buffers must be 4-byte aligned. The code doesn't worry about 100 * doing an extra byte. 101 */ 102 103 void 104 le_dec_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len) 105 { 106 volatile caddr_t buf = sc->sc_mem; 107 caddr_t from = fromv; 108 volatile u_int16_t *bptr; 109 110 if (boff & 0x1) { 111 /* handle unaligned first byte */ 112 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 113 *bptr = (*from++ << 8) | (*bptr & 0xff); 114 bptr += 2; 115 len--; 116 } else 117 bptr = ((volatile u_int16_t *)buf) + boff; 118 while (len > 1) { 119 *bptr = (from[1] << 8) | (from[0] & 0xff); 120 bptr += 2; 121 from += 2; 122 len -= 2; 123 } 124 if (len == 1) 125 *bptr = (u_int16_t)*from; 126 } 127 128 void 129 le_dec_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len) 130 { 131 volatile caddr_t buf = sc->sc_mem; 132 caddr_t to = tov; 133 volatile u_int16_t *bptr; 134 u_int16_t tmp; 135 136 if (boff & 0x1) { 137 /* handle unaligned first byte */ 138 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 139 *to++ = (*bptr >> 8) & 0xff; 140 bptr += 2; 141 len--; 142 } else 143 bptr = ((volatile u_int16_t *)buf) + boff; 144 while (len > 1) { 145 tmp = *bptr; 146 *to++ = tmp & 0xff; 147 *to++ = (tmp >> 8) & 0xff; 148 bptr += 2; 149 len -= 2; 150 } 151 if (len == 1) 152 *to = *bptr & 0xff; 153 } 154 155 static void 156 le_dec_zerobuf_gap2(struct lance_softc *sc, int boff, int len) 157 { 158 volatile caddr_t buf = sc->sc_mem; 159 volatile u_int16_t *bptr; 160 161 if ((unsigned)boff & 0x1) { 162 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 163 *bptr &= 0xff; 164 bptr += 2; 165 len--; 166 } else 167 bptr = ((volatile u_int16_t *)buf) + boff; 168 while (len > 0) { 169 *bptr = 0; 170 bptr += 2; 171 len -= 2; 172 } 173 } 174