diff --git a/sys/arch/sun3/dev/if_ie_sebuf.c b/sys/arch/sun3/dev/if_ie_sebuf.c index 8ba5c1863d80..63b1e2a2b804 100644 --- a/sys/arch/sun3/dev/if_ie_sebuf.c +++ b/sys/arch/sun3/dev/if_ie_sebuf.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ie_sebuf.c,v 1.3 1997/10/25 18:04:21 gwr Exp $ */ +/* $NetBSD: if_ie_sebuf.c,v 1.4 1997/12/08 19:22:52 gwr Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -73,6 +73,14 @@ static void ie_sebuf_reset __P((struct ie_softc *)); static void ie_sebuf_attend __P((struct ie_softc *)); static void ie_sebuf_run __P((struct ie_softc *)); +/* + * zero/copy functions: OBIO can use the normal functions, but VME + * must do only byte or half-word (16 bit) accesses... + */ +static void wcopy __P((const void *vb1, void *vb2, u_int l)); +static void wzero __P((void *vb, u_int l)); + + /* * New-style autoconfig attachment */ @@ -117,8 +125,19 @@ ie_sebuf_attach(parent, self, args) sc->reset_586 = ie_sebuf_reset; sc->chan_attn = ie_sebuf_attend; sc->run_586 = ie_sebuf_run; - sc->sc_bcopy = bcopy; - sc->sc_bzero = bzero; + sc->sc_bcopy = wcopy; + sc->sc_bzero = wzero; + + /* Control regs mapped by parent. */ + sc->sc_reg = aa->regs; + regs = (struct ie_regs *) sc->sc_reg; + + /* + * On this hardware, the i82586 address zero + * maps to the start of the board, which we + * happen to know is 128K below (XXX). + */ + sc->sc_iobase = aa->buf - 0x20000; /* * There is 128K of memory for the i82586 on @@ -130,18 +149,19 @@ ie_sebuf_attach(parent, self, args) panic("ie_sebuf: bad size"); sc->sc_msize = SE_IEBUFSIZE; sc->sc_maddr = aa->buf; - sc->sc_reg = aa->regs; - regs = (volatile struct ie_regs *) sc->sc_reg; - - /* - * On this hardware, the i82586 address is just - * masked to 17 bits, so sc_iobase == sc_maddr - */ - sc->sc_iobase = sc->sc_maddr; /* Clear the memory. */ (sc->sc_bzero)(sc->sc_maddr, sc->sc_msize); + /* + * XXX: Unfortunately, the common driver code + * is not ready to deal with more than 64K of + * memory, so skip the first 64K. Too bad. + * Note: device needs the SCP at the end. + */ + sc->sc_msize -= 0x10000; + sc->sc_maddr += 0x10000; + /* * Set the System Configuration Pointer (SCP). * Its location is system-dependent because the @@ -150,8 +170,8 @@ ie_sebuf_attach(parent, self, args) * masked down to 17 bits, so the SCP is found * at the end of the RAM on the VME board. */ - off = IE_SCP_ADDR & (SE_IEBUFSIZE-1); - sc->scp = (volatile void *) (sc->sc_iobase + off); + off = IE_SCP_ADDR & 0xFFFF; + sc->scp = (volatile void *) (sc->sc_maddr + off); /* * The rest of ram is used for buffers, etc. @@ -159,33 +179,20 @@ ie_sebuf_attach(parent, self, args) sc->buf_area = sc->sc_maddr; sc->buf_area_sz = off; - /* Set the ethernet address. */ - idprom_etheraddr(sc->sc_addr); - /* Install interrupt handler. */ regs->ie_ivec = aa->ca.ca_intvec; isr_add_vectored(ie_intr, (void *)sc, aa->ca.ca_intpri, aa->ca.ca_intvec); + /* Set the ethernet address. */ + idprom_etheraddr(sc->sc_addr); + /* Do machine-independent parts of attach. */ ie_attach(sc); } - -/* - * MULTIBUS/VME support - */ -void -ie_sebuf_reset(sc) - struct ie_softc *sc; -{ - volatile struct ie_regs *regs = (struct ie_regs *) sc->sc_reg; - regs->ie_csr = IE_CSR_RESET; - delay(10); - regs->ie_csr = 0; -} - +/* Whack the "channel attetion" line. */ void ie_sebuf_attend(sc) struct ie_softc *sc; @@ -196,11 +203,103 @@ ie_sebuf_attend(sc) regs->ie_csr &= ~IE_CSR_ATTEN; /* down. */ } +/* + * This is called during driver attach. + * Reset and initialize. + */ void -ie_sebuf_run(sc) +ie_sebuf_reset(sc) struct ie_softc *sc; { volatile struct ie_regs *regs = (struct ie_regs *) sc->sc_reg; - - regs->ie_csr |= IE_CSR_IENAB; + regs->ie_csr = IE_CSR_RESET; + delay(20); + regs->ie_csr = (IE_CSR_NOLOOP | IE_CSR_IENAB); +} + +/* + * This is called at the end of ieinit(). + * optional. + */ +void +ie_sebuf_run(sc) + struct ie_softc *sc; +{ + /* do it all in reset */ +} + +/* + * wcopy/wzero - like bcopy/bzero but largest access is 16-bits, + * and also does byte swaps... + * XXX - Would be nice to have asm versions in some library... + */ + +static void +wzero(vb, l) + void *vb; + u_int l; +{ + u_char *b = vb; + u_char *be = b + l; + u_short *sp; + + if (l == 0) + return; + + /* front, */ + if ((u_long)b & 1) + *b++ = 0; + + /* back, */ + if (b != be && ((u_long)be & 1) != 0) { + be--; + *be = 0; + } + + /* and middle. */ + sp = (u_short *)b; + while (sp != (u_short *)be) + *sp++ = 0; +} + +static void +wcopy(vb1, vb2, l) + const void *vb1; + void *vb2; + u_int l; +{ + const u_char *b1e, *b1 = vb1; + u_char *b2 = vb2; + u_short *sp; + int bstore = 0; + + if (l == 0) + return; + + /* front, */ + if ((u_long)b1 & 1) { + *b2++ = *b1++; + l--; + } + + /* middle, */ + sp = (u_short *)b1; + b1e = b1 + l; + if (l & 1) + b1e--; + bstore = (u_long)b2 & 1; + + while (sp < (u_short *)b1e) { + if (bstore) { + b2[1] = *sp & 0xff; + b2[0] = *sp >> 8; + } else + *((short *)b2) = *sp; + sp++; + b2 += 2; + } + + /* and back. */ + if (l & 1) + *b2 = *b1e; }