1 /* $NetBSD: if_le_ibus.c,v 1.9 2005/12/11 12:18:36 christos 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 22 #include <sys/cdefs.h> 23 __KERNEL_RCSID(0, "$NetBSD: if_le_ibus.c,v 1.9 2005/12/11 12:18:36 christos Exp $"); 24 25 #include "opt_inet.h" 26 27 #include <sys/param.h> 28 #include <sys/socket.h> 29 #include <sys/systm.h> 30 31 #include <net/if.h> 32 #include <net/if_ether.h> 33 #include <net/if_media.h> 34 35 #ifdef INET 36 #include <netinet/in.h> 37 #include <netinet/if_inarp.h> 38 #endif 39 40 #include <dev/ic/lancevar.h> 41 #include <dev/ic/am7990var.h> 42 43 #include <dev/tc/if_levar.h> 44 #include <pmax/ibus/ibusvar.h> 45 #include <pmax/pmax/kn01.h> 46 47 static void le_dec_copyfrombuf_gap2(struct lance_softc *, void *, int, int); 48 static void le_dec_copytobuf_gap2(struct lance_softc *, void *, int, int); 49 static void le_dec_zerobuf_gap2(struct lance_softc *, int, int); 50 51 52 static int le_pmax_match(struct device *, struct cfdata *, void *); 53 static void le_pmax_attach(struct device *, struct device *, void *); 54 55 CFATTACH_DECL(le_pmax, sizeof(struct le_softc), 56 le_pmax_match, le_pmax_attach, NULL, NULL); 57 58 int 59 le_pmax_match(struct device *parent, struct cfdata *match, void *aux) 60 { 61 struct ibus_attach_args *d = aux; 62 63 if (strcmp("lance", d->ia_name) != 0) 64 return (0); 65 return (1); 66 } 67 68 void 69 le_pmax_attach(struct device *parent, struct device *self, void *aux) 70 { 71 struct le_softc *lesc = (void *)self; 72 struct lance_softc *sc = &lesc->sc_am7990.lsc; 73 u_char *cp; 74 struct ibus_attach_args *ia = aux; 75 76 /* 77 * It's on the baseboard, with a dedicated interrupt line. 78 */ 79 lesc->sc_r1 = (struct lereg1 *)(ia->ia_addr); 80 sc->sc_mem = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_LANCE_B_START); 81 cp = (u_char *)(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK) + 1); 82 83 sc->sc_copytodesc = le_dec_copytobuf_gap2; 84 sc->sc_copyfromdesc = le_dec_copyfrombuf_gap2; 85 sc->sc_copytobuf = le_dec_copytobuf_gap2; 86 sc->sc_copyfrombuf = le_dec_copyfrombuf_gap2; 87 sc->sc_zerobuf = le_dec_zerobuf_gap2; 88 89 dec_le_common_attach(&lesc->sc_am7990, cp); 90 91 ibus_intr_establish(parent, (void*)ia->ia_cookie, IPL_NET, 92 am7990_intr, sc); 93 } 94 95 /* 96 * gap2: two bytes of data followed by two bytes of pad. 97 * 98 * Buffers must be 4-byte aligned. The code doesn't worry about 99 * doing an extra byte. 100 */ 101 102 void 103 le_dec_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len) 104 { 105 volatile caddr_t buf = sc->sc_mem; 106 caddr_t from = fromv; 107 volatile u_int16_t *bptr; 108 109 if (boff & 0x1) { 110 /* handle unaligned first byte */ 111 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 112 *bptr = (*from++ << 8) | (*bptr & 0xff); 113 bptr += 2; 114 len--; 115 } else 116 bptr = ((volatile u_int16_t *)buf) + boff; 117 while (len > 1) { 118 *bptr = (from[1] << 8) | (from[0] & 0xff); 119 bptr += 2; 120 from += 2; 121 len -= 2; 122 } 123 if (len == 1) 124 *bptr = (u_int16_t)*from; 125 } 126 127 void 128 le_dec_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len) 129 { 130 volatile caddr_t buf = sc->sc_mem; 131 caddr_t to = tov; 132 volatile u_int16_t *bptr; 133 u_int16_t tmp; 134 135 if (boff & 0x1) { 136 /* handle unaligned first byte */ 137 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 138 *to++ = (*bptr >> 8) & 0xff; 139 bptr += 2; 140 len--; 141 } else 142 bptr = ((volatile u_int16_t *)buf) + boff; 143 while (len > 1) { 144 tmp = *bptr; 145 *to++ = tmp & 0xff; 146 *to++ = (tmp >> 8) & 0xff; 147 bptr += 2; 148 len -= 2; 149 } 150 if (len == 1) 151 *to = *bptr & 0xff; 152 } 153 154 static void 155 le_dec_zerobuf_gap2(struct lance_softc *sc, int boff, int len) 156 { 157 volatile caddr_t buf = sc->sc_mem; 158 volatile u_int16_t *bptr; 159 160 if ((unsigned)boff & 0x1) { 161 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 162 *bptr &= 0xff; 163 bptr += 2; 164 len--; 165 } else 166 bptr = ((volatile u_int16_t *)buf) + boff; 167 while (len > 0) { 168 *bptr = 0; 169 bptr += 2; 170 len -= 2; 171 } 172 } 173