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