1 /* $NetBSD: if_ae.c,v 1.65 1997/08/11 22:53:32 scottr Exp $ */ 2 3 /* 4 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 5 * adapters. 6 * 7 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 8 * 9 * Copyright (C) 1993, David Greenman. This software may be used, modified, 10 * copied, distributed, and sold, in both source and binary form provided that 11 * the above copyright and these terms are retained. Under no circumstances is 12 * the author responsible for the proper functioning of this software, nor does 13 * the author assume any responsibility for damages incurred with its use. 14 */ 15 16 #include "bpfilter.h" 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/mbuf.h> 22 #include <sys/socket.h> 23 24 #include <net/if.h> 25 #include <net/if_ether.h> 26 27 #include <machine/bus.h> 28 29 #include <dev/ic/dp8390reg.h> 30 #include <dev/ic/dp8390var.h> 31 #include <mac68k/dev/if_aevar.h> 32 33 struct cfdriver ae_cd = { 34 NULL, "ae", DV_IFNET 35 }; 36 37 int 38 ae_size_card_memory(bst, bsh, ofs) 39 bus_space_tag_t bst; 40 bus_space_handle_t bsh; 41 int ofs; 42 { 43 int i1, i2, i3, i4; 44 45 /* 46 * banks; also assume it will generally mirror in upper banks 47 * if not installed. 48 */ 49 i1 = (8192 * 0); 50 i2 = (8192 * 1); 51 i3 = (8192 * 2); 52 i4 = (8192 * 3); 53 54 bus_space_write_2(bst, bsh, ofs + i1, 0x1111); 55 bus_space_write_2(bst, bsh, ofs + i2, 0x2222); 56 bus_space_write_2(bst, bsh, ofs + i3, 0x3333); 57 bus_space_write_2(bst, bsh, ofs + i4, 0x4444); 58 59 if (bus_space_read_2(bst, bsh, ofs + i1) == 0x1111 && 60 bus_space_read_2(bst, bsh, ofs + i2) == 0x2222 && 61 bus_space_read_2(bst, bsh, ofs + i3) == 0x3333 && 62 bus_space_read_2(bst, bsh, ofs + i4) == 0x4444) 63 return 8192 * 4; 64 65 if ((bus_space_read_2(bst, bsh, ofs + i1) == 0x1111 && 66 bus_space_read_2(bst, bsh, ofs + i2) == 0x2222) || 67 (bus_space_read_2(bst, bsh, ofs + i1) == 0x3333 && 68 bus_space_read_2(bst, bsh, ofs + i2) == 0x4444)) 69 return 8192 * 2; 70 71 if (bus_space_read_2(bst, bsh, ofs + i1) == 0x1111 || 72 bus_space_read_2(bst, bsh, ofs + i1) == 0x4444) 73 return 8192; 74 75 return 0; 76 } 77 78 /* 79 * Zero memory and verify that it is clear. The only difference between 80 * this and the default test_mem function is that the DP8390-based NuBus 81 * cards * apparently require word-wide writes and byte-wide reads, an 82 * `interesting' combination. 83 */ 84 int 85 ae_test_mem(sc) 86 struct dp8390_softc *sc; 87 { 88 bus_space_tag_t buft = sc->sc_buft; 89 bus_space_handle_t bufh = sc->sc_bufh; 90 int i; 91 92 bus_space_set_region_2(buft, bufh, sc->mem_start, 0, 93 sc->mem_size / 2); 94 95 for (i = 0; i < sc->mem_size; ++i) { 96 if (bus_space_read_1(sc->sc_buft, sc->sc_bufh, i)) { 97 printf(": failed to clear NIC buffer at offset %x - " 98 "check configuration\n", (sc->mem_start + i)); 99 return 1; 100 } 101 } 102 103 return 0; 104 } 105 106 /* 107 * Copy packet from mbuf to the board memory Currently uses an extra 108 * buffer/extra memory copy, unless the whole packet fits in one mbuf. 109 * 110 * As in the test_mem function, we use word-wide writes. 111 */ 112 int 113 ae_write_mbuf(sc, m, buf) 114 struct dp8390_softc *sc; 115 struct mbuf *m; 116 int buf; 117 { 118 u_char *data, savebyte[2]; 119 int len, wantbyte; 120 u_short totlen = 0; 121 122 wantbyte = 0; 123 124 for (; m ; m = m->m_next) { 125 data = mtod(m, u_char *); 126 len = m->m_len; 127 totlen += len; 128 if (len > 0) { 129 /* Finish the last word. */ 130 if (wantbyte) { 131 savebyte[1] = *data; 132 bus_space_write_region_2(sc->sc_buft, 133 sc->sc_bufh, buf, savebyte, 1); 134 buf += 2; 135 data++; 136 len--; 137 wantbyte = 0; 138 } 139 /* Output contiguous words. */ 140 if (len > 1) { 141 bus_space_write_region_2(sc->sc_buft, 142 sc->sc_bufh, buf, data, len >> 1); 143 buf += len & ~1; 144 data += len & ~1; 145 len &= 1; 146 } 147 /* Save last byte, if necessary. */ 148 if (len == 1) { 149 savebyte[0] = *data; 150 wantbyte = 1; 151 } 152 } 153 } 154 155 if (wantbyte) { 156 savebyte[1] = 0; 157 bus_space_write_region_2(sc->sc_buft, sc->sc_bufh, 158 buf, savebyte, 1); 159 } 160 return (totlen); 161 } 162