+
+/*
+ * Write a lance register port, reading it back to ensure success. This seems
+ * to be necessary during initialization, since the chip appears to be a bit
+ * pokey sometimes.
+ */
+static void
+lewritereg(regptr, val)
+ register volatile u_short *regptr;
+ register u_short val;
+{
+ register int i = 0;
+
+ while (*regptr != val) {
+ *regptr = val;
+ MachEmptyWriteBuffer();
+ if (++i > 10000) {
+ printf("le: Reg did not settle (to x%x): x%x\n",
+ val, *regptr);
+ return;
+ }
+ DELAY(100);
+ }
+}
+
+/*
+ * Routines for accessing the transmit and receive buffers. Unfortunately,
+ * CPU addressing of these buffers is done in one of 3 ways:
+ * - contiguous (for the 3max and turbochannel option card)
+ * - gap2, which means shorts (2 bytes) interspersed with short (2 byte)
+ * spaces (for the pmax)
+ * - gap16, which means 16bytes interspersed with 16byte spaces
+ * for buffers which must begin on a 32byte boundary (for 3min and maxine)
+ * The buffer offset is the logical byte offset, assuming contiguous storage.
+ */
+void
+copytobuf_contig(from, lebuf, boff, len)
+ char *from;
+ volatile void *lebuf;
+ int boff;
+ int len;
+{
+
+ /*
+ * Just call bcopy() to do the work.
+ */
+ bcopy(from, ((char *)lebuf) + boff, len);
+}
+
+void
+copyfrombuf_contig(lebuf, boff, to, len)
+ volatile void *lebuf;
+ int boff;
+ char *to;
+ int len;
+{
+
+ /*
+ * Just call bcopy() to do the work.
+ */
+ bcopy(((char *)lebuf) + boff, to, len);
+}
+
+void
+bzerobuf_contig(lebuf, boff, len)
+ volatile void *lebuf;
+ int boff;
+ int len;
+{
+
+ /*
+ * Just let bzero() do the work
+ */
+ bzero(((char *)lebuf) + boff, len);
+}
+
+/*
+ * For the pmax the buffer consists of shorts (2 bytes) interspersed with
+ * short (2 byte) spaces and must be accessed with halfword load/stores.
+ * (don't worry about doing an extra byte)
+ */
+void
+copytobuf_gap2(from, lebuf, boff, len)
+ register char *from;
+ volatile void *lebuf;
+ int boff;
+ register int len;
+{
+ register volatile u_short *bptr;
+ register int xfer;
+
+ if (boff & 0x1) {
+ /* handle unaligned first byte */
+ bptr = ((volatile u_short *)lebuf) + (boff - 1);
+ *bptr = (*from++ << 8) | (*bptr & 0xff);
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_short *)lebuf) + boff;
+ if ((unsigned)from & 0x1) {
+ while (len > 1) {
+ *bptr = (from[1] << 8) | (from[0] & 0xff);
+ bptr += 2;
+ from += 2;
+ len -= 2;
+ }
+ } else {
+ /* optimize for aligned transfers */
+ xfer = (int)((unsigned)len & ~0x1);
+ CopyToBuffer((u_short *)from, bptr, xfer);
+ bptr += xfer;
+ from += xfer;
+ len -= xfer;
+ }
+ if (len == 1)
+ *bptr = (u_short)*from;
+}
+
+void
+copyfrombuf_gap2(lebuf, boff, to, len)
+ volatile void *lebuf;
+ int boff;
+ register char *to;
+ register int len;
+{
+ register volatile u_short *bptr;
+ register u_short tmp;
+ register int xfer;
+
+ if (boff & 0x1) {
+ /* handle unaligned first byte */
+ bptr = ((volatile u_short *)lebuf) + (boff - 1);
+ *to++ = (*bptr >> 8) & 0xff;
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_short *)lebuf) + boff;
+ if ((unsigned)to & 0x1) {
+ while (len > 1) {
+ tmp = *bptr;
+ *to++ = tmp & 0xff;
+ *to++ = (tmp >> 8) & 0xff;
+ bptr += 2;
+ len -= 2;
+ }
+ } else {
+ /* optimize for aligned transfers */
+ xfer = (int)((unsigned)len & ~0x1);
+ CopyFromBuffer(bptr, to, xfer);
+ bptr += xfer;
+ to += xfer;
+ len -= xfer;
+ }
+ if (len == 1)
+ *to = *bptr & 0xff;
+}
+
+void
+bzerobuf_gap2(lebuf, boff, len)
+ volatile void *lebuf;
+ int boff;
+ int len;
+{
+ register volatile u_short *bptr;
+
+ if ((unsigned)boff & 0x1) {
+ bptr = ((volatile u_short *)lebuf) + (boff - 1);
+ *bptr &= 0xff;
+ bptr += 2;
+ len--;
+ } else
+ bptr = ((volatile u_short *)lebuf) + boff;
+ while (len > 0) {
+ *bptr = 0;
+ bptr += 2;
+ len -= 2;
+ }
+}
+
+/*
+ * For the 3min and maxine, the buffers are in main memory filled in with
+ * 16byte blocks interspersed with 16byte spaces.
+ */
+void
+copytobuf_gap16(from, lebuf, boff, len)
+ register char *from;
+ volatile void *lebuf;
+ int boff;
+ register int len;
+{
+ register char *bptr;
+ register int xfer;
+
+ bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f);
+ boff &= 0xf;
+ xfer = min(len, 16 - boff);
+ while (len > 0) {
+ bcopy(from, ((char *)bptr) + boff, xfer);
+ from += xfer;
+ bptr += 32;
+ boff = 0;
+ len -= xfer;
+ xfer = min(len, 16);
+ }
+}
+
+void
+copyfrombuf_gap16(lebuf, boff, to, len)
+ volatile void *lebuf;
+ int boff;
+ register char *to;
+ register int len;
+{
+ register char *bptr;
+ register int xfer;
+
+ bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f);
+ boff &= 0xf;
+ xfer = min(len, 16 - boff);
+ while (len > 0) {
+ bcopy(((char *)bptr) + boff, to, xfer);
+ to += xfer;
+ bptr += 32;
+ boff = 0;
+ len -= xfer;
+ xfer = min(len, 16);
+ }
+}
+
+void
+bzerobuf_gap16(lebuf, boff, len)
+ volatile void *lebuf;
+ int boff;
+ register int len;
+{
+ register char *bptr;
+ register int xfer;
+
+ bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f);
+ boff &= 0xf;
+ xfer = min(len, 16 - boff);
+ while (len > 0) {
+ bzero(((char *)bptr) + boff, xfer);
+ bptr += 32;
+ boff = 0;
+ len -= xfer;
+ xfer = min(len, 16);
+ }
+}
+#endif /* NLE */