1 /* $NetBSD: if_ie_vme.c,v 1.4 1996/10/13 03:47:30 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Gordon W. Ross 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Gordon Ross 18 * 4. The name of the Author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Machine-dependent glue for the Intel Ethernet (ie) driver. 35 */ 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/protosw.h> 41 #include <sys/socket.h> 42 #include <net/if.h> 43 44 #ifdef INET 45 #include <netinet/in.h> 46 #include <netinet/in_systm.h> 47 #include <netinet/in_var.h> 48 #include <netinet/ip.h> 49 #include <netinet/if_ether.h> 50 #endif 51 52 #include <machine/autoconf.h> 53 #include <machine/cpu.h> 54 #include <machine/dvma.h> 55 #include <machine/isr.h> 56 #include <machine/idprom.h> 57 #include <machine/vmparam.h> 58 59 #include "i82586.h" 60 #include "if_iereg.h" 61 #include "if_ievar.h" 62 63 static void ie_vmereset __P((struct ie_softc *)); 64 static void ie_vmeattend __P((struct ie_softc *)); 65 static void ie_vmerun __P((struct ie_softc *)); 66 67 /* 68 * zero/copy functions: OBIO can use the normal functions, but VME 69 * must do only byte or half-word (16 bit) accesses... 70 */ 71 static void wcopy(), wzero(); 72 73 /* 74 * New-style autoconfig attachment 75 */ 76 77 static int ie_vmes_match __P((struct device *, void *, void *)); 78 static void ie_vmes_attach __P((struct device *, struct device *, void *)); 79 80 struct cfattach ie_vmes_ca = { 81 sizeof(struct ie_softc), ie_vmes_match, ie_vmes_attach 82 }; 83 84 85 static int 86 ie_vmes_match(parent, vcf, args) 87 struct device *parent; 88 void *vcf, *args; 89 { 90 struct confargs *ca = args; 91 int x, sz; 92 93 #ifdef DIAGNOSTIC 94 if (ca->ca_bustype != BUS_VME16) { 95 printf("ie_vmes_match: bustype %d?\n", ca->ca_bustype); 96 return (0); 97 } 98 #endif 99 100 /* No default VME address. */ 101 if (ca->ca_paddr == -1) 102 return(0); 103 104 /* Default interrupt level. */ 105 if (ca->ca_intpri == -1) 106 ca->ca_intpri = 3; 107 108 x = bus_peek(ca->ca_bustype, ca->ca_paddr, 2); 109 return (x != -1); 110 } 111 112 /* 113 * *note*: we don't detect the difference between a VME3E and 114 * a multibus/vme card. if you want to use a 3E you'll have 115 * to fix this. 116 */ 117 void 118 ie_vmes_attach(parent, self, args) 119 struct device *parent; 120 struct device *self; 121 void *args; 122 { 123 struct ie_softc *sc = (void *) self; 124 struct confargs *ca = args; 125 volatile struct ievme *iev; 126 u_long rampaddr; 127 int lcv, off; 128 129 sc->hard_type = IE_VME; 130 sc->reset_586 = ie_vmereset; 131 sc->chan_attn = ie_vmeattend; 132 sc->run_586 = ie_vmerun; 133 sc->sc_bcopy = wcopy; 134 sc->sc_bzero = wzero; 135 136 /* 137 * There is 64K of memory on the VME board. 138 * (determined by hardware - NOT configurable!) 139 */ 140 sc->sc_msize = 0x10000; /* MEMSIZE 64K */ 141 142 /* Map in the board control regs. */ 143 sc->sc_reg = bus_mapin(ca->ca_bustype, ca->ca_paddr, 144 sizeof(struct ievme)); 145 iev = (volatile struct ievme *) sc->sc_reg; 146 147 /* 148 * Find and map in the board memory. 149 */ 150 /* top 12 bits */ 151 rampaddr = ca->ca_paddr & 0xfff00000; 152 /* 4 more */ 153 rampaddr |= ((iev->status & IEVME_HADDR) << 16); 154 sc->sc_maddr = bus_mapin(ca->ca_bustype, rampaddr, sc->sc_msize); 155 156 /* 157 * On this hardware, the i82586 address is just 158 * masked to 16 bits, so sc_iobase == sc_maddr 159 */ 160 sc->sc_iobase = sc->sc_maddr; 161 162 /* 163 * Set up on-board mapping registers for linear map. 164 */ 165 iev->pectrl |= IEVME_PARACK; /* clear to start */ 166 for (lcv = 0; lcv < IEVME_MAPSZ; lcv++) 167 iev->pgmap[lcv] = IEVME_SBORDR | IEVME_OBMEM | lcv; 168 (sc->sc_bzero)(sc->sc_maddr, sc->sc_msize); 169 170 /* 171 * Set the System Configuration Pointer (SCP). 172 * Its location is system-dependent because the 173 * i82586 reads it from a fixed physical address. 174 * On this hardware, the i82586 address is just 175 * masked down to 16 bits, so the SCP is found 176 * at the end of the RAM on the VME board. 177 */ 178 off = IE_SCP_ADDR & 0xFFFF; 179 sc->scp = (volatile void *) (sc->sc_maddr + off); 180 181 /* 182 * The rest of ram is used for buffers, etc. 183 */ 184 sc->buf_area = sc->sc_maddr; 185 sc->buf_area_sz = off; 186 187 /* Set the ethernet address. */ 188 idprom_etheraddr(sc->sc_addr); 189 190 /* Do machine-independent parts of attach. */ 191 ie_attach(sc); 192 193 /* Install interrupt handler. */ 194 isr_add_vectored(ie_intr, (void *)sc, 195 ca->ca_intpri, ca->ca_intvec); 196 } 197 198 199 /* 200 * MULTIBUS/VME support 201 */ 202 void 203 ie_vmereset(sc) 204 struct ie_softc *sc; 205 { 206 volatile struct ievme *iev = (struct ievme *) sc->sc_reg; 207 iev->status = IEVME_RESET; 208 delay(100); /* XXX could be shorter? */ 209 iev->status = 0; 210 } 211 212 void 213 ie_vmeattend(sc) 214 struct ie_softc *sc; 215 { 216 volatile struct ievme *iev = (struct ievme *) sc->sc_reg; 217 218 iev->status |= IEVME_ATTEN; /* flag! */ 219 iev->status &= ~IEVME_ATTEN; /* down. */ 220 } 221 222 void 223 ie_vmerun(sc) 224 struct ie_softc *sc; 225 { 226 volatile struct ievme *iev = (struct ievme *) sc->sc_reg; 227 228 iev->status |= (IEVME_ONAIR | IEVME_IENAB | IEVME_PEINT); 229 } 230 231 /* 232 * wcopy/wzero - like bcopy/bzero but largest access is 16-bits, 233 * and also does byte swaps... 234 * XXX - Would be nice to have asm versions in some library... 235 */ 236 237 static void 238 wzero(vb, l) 239 void *vb; 240 u_int l; 241 { 242 u_char *b = vb; 243 u_char *be = b + l; 244 u_short *sp; 245 246 if (l == 0) 247 return; 248 249 /* front, */ 250 if ((u_long)b & 1) 251 *b++ = 0; 252 253 /* back, */ 254 if (b != be && ((u_long)be & 1) != 0) { 255 be--; 256 *be = 0; 257 } 258 259 /* and middle. */ 260 sp = (u_short *)b; 261 while (sp != (u_short *)be) 262 *sp++ = 0; 263 } 264 265 static void 266 wcopy(vb1, vb2, l) 267 const void *vb1; 268 void *vb2; 269 u_int l; 270 { 271 const u_char *b1e, *b1 = vb1; 272 u_char *b2 = vb2; 273 u_short *sp; 274 int bstore = 0; 275 276 if (l == 0) 277 return; 278 279 /* front, */ 280 if ((u_long)b1 & 1) { 281 *b2++ = *b1++; 282 l--; 283 } 284 285 /* middle, */ 286 sp = (u_short *)b1; 287 b1e = b1 + l; 288 if (l & 1) 289 b1e--; 290 bstore = (u_long)b2 & 1; 291 292 while (sp < (u_short *)b1e) { 293 if (bstore) { 294 b2[1] = *sp & 0xff; 295 b2[0] = *sp >> 8; 296 } else 297 *((short *)b2) = *sp; 298 sp++; 299 b2 += 2; 300 } 301 302 /* and back. */ 303 if (l & 1) 304 *b2 = *b1e; 305 } 306