1 /* $NetBSD: ne.c,v 1.4 2001/11/07 08:46:24 yamt Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet 42 * adapters. 43 * 44 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 45 * 46 * Copyright (C) 1993, David Greenman. This software may be used, modified, 47 * copied, distributed, and sold, in both source and binary form provided that 48 * the above copyright and these terms are retained. Under no circumstances is 49 * the author responsible for the proper functioning of this software, nor does 50 * the author assume any responsibility for damages incurred with its use. 51 */ 52 53 /* 54 * this code is mainly obtained from /sys/dev/ic/ne2000.c . 55 */ 56 57 #include <sys/types.h> 58 #include <machine/pio.h> 59 60 #include <lib/libsa/stand.h> 61 #include <libi386.h> 62 63 #ifdef _STANDALONE 64 #include <lib/libkern/libkern.h> 65 #include <bootinfo.h> 66 #endif 67 68 #include "etherdrv.h" 69 #include <dev/ic/dp8390reg.h> 70 #include <dev/ic/ne2000reg.h> 71 #include "dp8390.h" 72 #include "ne.h" 73 74 #ifndef BASEREG 75 #define BASEREG 0x300 76 #endif 77 78 #define NE_BASEREG BASEREG 79 #define NE_ASIC_BASEREG (NE_BASEREG+NE2000_ASIC_OFFSET) 80 81 #define NIC_PORT(x) (NE_BASEREG + (x)) 82 #define NIC_INB(x) inb(NIC_PORT(x)) 83 #define NIC_OUTB(x, b) outb(NIC_PORT(x), (b)) 84 85 #define NE_16BIT 86 87 #define DELAY(x) delay(x) 88 89 #define ASIC_PORT(x) (NE_ASIC_BASEREG + (x)) 90 #define ASIC_INB(x) inb(ASIC_PORT(x)) 91 #define ASIC_INW(x) inw(ASIC_PORT(x)) 92 #define ASIC_OUTB(x, b) outb(ASIC_PORT(x), (b)) 93 #define ASIC_OUTW(x, b) outw(ASIC_PORT(x), (b)) 94 95 u_char eth_myaddr[6]; 96 97 #ifdef _STANDALONE 98 static struct btinfo_netif bi_netif; 99 #endif 100 101 int 102 EtherInit(unsigned char *myadr) 103 { 104 u_int8_t tmp; 105 int i; 106 107 printf("ne: trying iobase=0x%x\n", NE_BASEREG); 108 109 dp8390_iobase = NE_BASEREG; 110 dp8390_membase = dp8390_memsize = 8192*2; 111 dp8390_cr_proto = ED_CR_RD2; 112 dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS 113 #ifdef NE_16BIT 114 | ED_DCR_WTS 115 #endif 116 ; 117 118 /* reset */ 119 tmp = ASIC_INB(NE2000_ASIC_RESET); 120 DELAY(10000); 121 ASIC_OUTB(NE2000_ASIC_RESET, tmp); 122 DELAY(5000); 123 124 NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP); 125 DELAY(5000); 126 127 tmp = NIC_INB(ED_P0_CR); 128 if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) != 129 (ED_CR_RD2 | ED_CR_STP)) { 130 goto out; 131 } 132 133 tmp = NIC_INB(ED_P0_ISR); 134 if ((tmp & ED_ISR_RST) != ED_ISR_RST) { 135 goto out; 136 } 137 138 NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA); 139 140 for (i = 0; i < 100; i++) { 141 if ((NIC_INB(ED_P0_ISR) & ED_ISR_RST) == 142 ED_ISR_RST) { 143 /* Ack the reset bit. */ 144 NIC_OUTB(ED_P0_ISR, ED_ISR_RST); 145 break; 146 } 147 DELAY(100); 148 } 149 150 printf("ne: found\n"); 151 152 /* 153 * This prevents packets from being stored in the NIC memory when 154 * the readmem routine turns on the start bit in the CR. 155 */ 156 NIC_OUTB(ED_P0_RCR, ED_RCR_MON); 157 158 /* Temporarily initialize DCR for byte operations. */ 159 NIC_OUTB(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS); 160 161 NIC_OUTB(ED_P0_PSTART, 8192 >> ED_PAGE_SHIFT); 162 NIC_OUTB(ED_P0_PSTOP, 16384 >> ED_PAGE_SHIFT); 163 164 #ifdef HWADDR 165 for (i = 0; i < 6; i++) 166 myadr[i] = eth_myaddr[i] = HWADDR[i]; 167 #else 168 { 169 u_int8_t romdata[16]; 170 171 ne2000_readmem(0, romdata, 16); 172 for (i = 0; i < 6; i++) 173 myadr[i] = eth_myaddr[i] = romdata[i*2]; 174 } 175 #endif 176 177 if (dp8390_config()) 178 goto out; 179 180 #ifdef _STANDALONE 181 strncpy(bi_netif.ifname, "ne", sizeof(bi_netif.ifname)); 182 bi_netif.bus = BI_BUS_ISA; 183 bi_netif.addr.iobase = NE_BASEREG; 184 185 BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); 186 #endif 187 return 1; 188 out: 189 return 0; 190 } 191 192 void 193 EtherStop() { 194 u_int8_t tmp; 195 196 dp8390_stop(); 197 198 tmp = ASIC_INB(NE2000_ASIC_RESET); 199 DELAY(10000); 200 ASIC_OUTB(NE2000_ASIC_RESET, tmp); 201 DELAY(5000); 202 203 NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP); 204 DELAY(5000); 205 } 206 207 void 208 ne2000_writemem(u_int8_t *src, int dst, size_t len) 209 { 210 size_t i; 211 int maxwait = 100; /* about 120us */ 212 213 /* Select page 0 registers. */ 214 NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA); 215 216 /* Reset remote DMA complete flag. */ 217 NIC_OUTB(ED_P0_ISR, ED_ISR_RDC); 218 219 /* Set up DMA byte count. */ 220 NIC_OUTB(ED_P0_RBCR0, len); 221 NIC_OUTB(ED_P0_RBCR1, len >> 8); 222 223 /* Set up destination address in NIC mem. */ 224 NIC_OUTB(ED_P0_RSAR0, dst); 225 NIC_OUTB(ED_P0_RSAR1, dst >> 8); 226 227 /* Set remote DMA write. */ 228 NIC_OUTB(ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA); 229 230 #ifdef NE_16BIT 231 for (i = 0; i < len; i += 2, src += 2) 232 ASIC_OUTW(NE2000_ASIC_DATA, *(u_int16_t *)src); 233 #else 234 for (i = 0; i < len; i++) 235 ASIC_OUTB(NE2000_ASIC_DATA, *src++); 236 #endif 237 238 /* 239 * Wait for remote DMA to complete. This is necessary because on the 240 * transmit side, data is handled internally by the NIC in bursts, and 241 * we can't start another remote DMA until this one completes. Not 242 * waiting causes really bad things to happen - like the NIC wedging 243 * the bus. 244 */ 245 while (((NIC_INB(ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) && --maxwait) 246 DELAY(1); 247 248 if (maxwait == 0) 249 printf("ne2000_writemem: failed to complete\n"); 250 } 251 252 void 253 ne2000_readmem(int src, u_int8_t *dst, size_t amount) 254 { 255 size_t i; 256 257 /* Select page 0 registers. */ 258 NIC_OUTB(ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA); 259 260 /* Round up to a word. */ 261 if (amount & 1) 262 ++amount; 263 264 /* Set up DMA byte count. */ 265 NIC_OUTB(ED_P0_RBCR0, amount); 266 NIC_OUTB(ED_P0_RBCR1, amount >> 8); 267 268 /* Set up source address in NIC mem. */ 269 NIC_OUTB(ED_P0_RSAR0, src); 270 NIC_OUTB(ED_P0_RSAR1, src >> 8); 271 272 NIC_OUTB(ED_P0_CR, ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA); 273 274 #ifdef NE_16BIT 275 for (i = 0; i < amount; i += 2, dst += 2) 276 *(u_int16_t *)dst = ASIC_INW(NE2000_ASIC_DATA); 277 #else 278 for (i = 0; i < amount; i++) 279 *dst++ = ASIC_INB(NE2000_ASIC_DATA); 280 #endif 281 } 282