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