1 /* $NetBSD: dp8390.c,v 1.3 2001/11/01 09:37:17 yamt Exp $ */ 2 3 /* 4 * Polling driver for National Semiconductor DS8390/WD83C690 based 5 * ethernet adapters. 6 * 7 * Copyright (c) 1998 Matthias Drochner. All rights reserved. 8 * 9 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved. 10 * 11 * Copyright (C) 1993, David Greenman. This software may be used, modified, 12 * copied, distributed, and sold, in both source and binary form provided that 13 * the above copyright and these terms are retained. Under no circumstances is 14 * the author responsible for the proper functioning of this software, nor does 15 * the author assume any responsibility for damages incurred with its use. 16 */ 17 18 #include <sys/types.h> 19 #include <machine/pio.h> 20 21 #include <lib/libsa/stand.h> 22 #include <libi386.h> 23 24 #include <dev/ic/dp8390reg.h> 25 #include "dp8390.h" 26 #ifdef SUPPORT_NE2000 27 #include "ne.h" 28 #endif 29 30 #include "etherdrv.h" 31 32 int dp8390_iobase, dp8390_membase, dp8390_memsize; 33 #if defined(SUPPORT_WD80X3) && defined(SUPPORT_SMC_ULTRA) 34 int dp8390_is790; 35 #endif 36 u_int8_t dp8390_cr_proto; 37 u_int8_t dp8390_dcr_reg; 38 39 #define WE_IOBASE dp8390_iobase 40 41 static u_short rec_page_start; 42 static u_short rec_page_stop; 43 static u_short next_packet; 44 45 extern u_char eth_myaddr[6]; 46 47 #ifndef _STANDALONE 48 static caddr_t vmembase; 49 extern caddr_t mapmem __P((int, int)); 50 extern void unmapmem __P((caddr_t, int)); 51 extern int mapio __P((void)); 52 53 static void bbcopy(src, dst, len) 54 caddr_t src, dst; 55 int len; 56 { 57 char *s = (char *)src, *d = (char *)dst; 58 59 while(len--) 60 *d++ = *s++; 61 } 62 #endif 63 64 static void dp8390_read __P((int, char *, u_short)); 65 66 #define NIC_GET(reg) inb(WE_IOBASE + reg) 67 #define NIC_PUT(reg, val) outb(WE_IOBASE + reg, val) 68 69 static void 70 dp8390_init() 71 { 72 int i; 73 74 /* 75 * Initialize the NIC in the exact order outlined in the NS manual. 76 * This init procedure is "mandatory"...don't change what or when 77 * things happen. 78 */ 79 80 /* Set interface for page 0, remote DMA complete, stopped. */ 81 NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP); 82 83 if (dp8390_dcr_reg & ED_DCR_LS) { 84 NIC_PUT(ED_P0_DCR, dp8390_dcr_reg); 85 } else { 86 /* 87 * Set FIFO threshold to 8, No auto-init Remote DMA, byte 88 * order=80x86, byte-wide DMA xfers, 89 */ 90 NIC_PUT(ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS); 91 } 92 93 /* Clear remote byte count registers. */ 94 NIC_PUT(ED_P0_RBCR0, 0); 95 NIC_PUT(ED_P0_RBCR1, 0); 96 97 /* Tell RCR to do nothing for now. */ 98 NIC_PUT(ED_P0_RCR, ED_RCR_MON); 99 100 /* Place NIC in internal loopback mode. */ 101 NIC_PUT(ED_P0_TCR, ED_TCR_LB0); 102 103 /* Set lower bits of byte addressable framing to 0. */ 104 if (dp8390_is790) 105 NIC_PUT(0x09, 0); 106 107 /* Initialize receive buffer ring. */ 108 NIC_PUT(ED_P0_BNRY, rec_page_start); 109 NIC_PUT(ED_P0_PSTART, rec_page_start); 110 NIC_PUT(ED_P0_PSTOP, rec_page_stop); 111 112 /* 113 * Clear all interrupts. A '1' in each bit position clears the 114 * corresponding flag. 115 */ 116 NIC_PUT(ED_P0_ISR, 0xff); 117 118 /* 119 * Disable all interrupts. 120 */ 121 NIC_PUT(ED_P0_IMR, 0); 122 123 /* Program command register for page 1. */ 124 NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_1 | ED_CR_STP); 125 126 /* Copy out our station address. */ 127 for (i = 0; i < 6; ++i) 128 NIC_PUT(ED_P1_PAR0 + i, eth_myaddr[i]); 129 130 /* 131 * Set current page pointer to one page after the boundary pointer, as 132 * recommended in the National manual. 133 */ 134 next_packet = rec_page_start + 1; 135 NIC_PUT(ED_P1_CURR, next_packet); 136 137 /* Program command register for page 0. */ 138 NIC_PUT(ED_P1_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP); 139 140 /* directed and broadcast */ 141 NIC_PUT(ED_P0_RCR, ED_RCR_AB); 142 143 /* Take interface out of loopback. */ 144 NIC_PUT(ED_P0_TCR, 0); 145 146 /* Fire up the interface. */ 147 NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STA); 148 } 149 150 int 151 dp8390_config() 152 { 153 #ifndef _STANDALONE 154 if (mapio()) { 155 printf("no IO access\n"); 156 return(-1); 157 } 158 vmembase = mapmem(dp8390_membase, dp8390_memsize); 159 if (!vmembase) { 160 printf("no memory access\n"); 161 return(-1); 162 } 163 #endif 164 165 rec_page_start = TX_PAGE_START + ED_TXBUF_SIZE; 166 rec_page_stop = TX_PAGE_START + (dp8390_memsize >> ED_PAGE_SHIFT); 167 168 dp8390_init(); 169 170 return(0); 171 } 172 173 void 174 dp8390_stop() 175 { 176 int n = 5000; 177 178 /* Stop everything on the interface, and select page 0 registers. */ 179 NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STP); 180 181 /* 182 * Wait for interface to enter stopped state, but limit # of checks to 183 * 'n' (about 5ms). It shouldn't even take 5us on modern DS8390's, but 184 * just in case it's an old one. 185 */ 186 while (((NIC_GET(ED_P0_ISR) & ED_ISR_RST) == 0) && --n); 187 188 #ifndef _STANDALONE 189 unmapmem(vmembase, dp8390_memsize); 190 #endif 191 } 192 193 int 194 EtherSend(pkt, len) 195 char *pkt; 196 int len; 197 { 198 #ifdef SUPPORT_NE2000 199 ne2000_writemem(pkt, dp8390_membase, len); 200 #else 201 #ifdef _STANDALONE 202 vpbcopy(pkt, (void *)dp8390_membase, len); 203 #else 204 bbcopy(pkt, vmembase, len); 205 #endif 206 #endif 207 208 /* Set TX buffer start page. */ 209 NIC_PUT(ED_P0_TPSR, TX_PAGE_START); 210 211 /* Set TX length. */ 212 NIC_PUT(ED_P0_TBCR0, len < 60 ? 60 : len); 213 NIC_PUT(ED_P0_TBCR1, len >> 8); 214 215 /* Set page 0, remote DMA complete, transmit packet, and *start*. */ 216 NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA); 217 218 return(len); 219 } 220 221 static void 222 dp8390_read(buf, dest, len) 223 int buf; 224 char *dest; 225 u_short len; 226 { 227 u_short tmp_amount; 228 229 /* Does copy wrap to lower addr in ring buffer? */ 230 if (buf + len > dp8390_membase + dp8390_memsize) { 231 tmp_amount = dp8390_membase + dp8390_memsize - buf; 232 233 /* Copy amount up to end of NIC memory. */ 234 #ifdef SUPPORT_NE2000 235 ne2000_readmem(buf, dest, tmp_amount); 236 #else 237 #ifdef _STANDALONE 238 pvbcopy((void *)buf, dest, tmp_amount); 239 #else 240 bbcopy(vmembase + buf - dp8390_membase, dest, tmp_amount); 241 #endif 242 #endif 243 244 len -= tmp_amount; 245 buf = RX_BUFBASE + (rec_page_start << ED_PAGE_SHIFT); 246 dest += tmp_amount; 247 } 248 #ifdef SUPPORT_NE2000 249 ne2000_readmem(buf, dest, len); 250 #else 251 #ifdef _STANDALONE 252 pvbcopy((void *)buf, dest, len); 253 #else 254 bbcopy(vmembase + buf - dp8390_membase, dest, len); 255 #endif 256 #endif 257 } 258 259 int 260 EtherReceive(pkt, maxlen) 261 char *pkt; 262 int maxlen; 263 { 264 struct dp8390_ring packet_hdr; 265 int packet_ptr; 266 u_short len; 267 u_char boundary, current; 268 #ifdef DP8390_OLDCHIPS 269 u_char nlen; 270 #endif 271 272 if (!(NIC_GET(ED_P0_RSR) & ED_RSR_PRX)) 273 return(0); /* XXX error handling */ 274 275 /* Set NIC to page 1 registers to get 'current' pointer. */ 276 NIC_PUT(ED_P0_CR, dp8390_cr_proto | ED_CR_PAGE_1 | ED_CR_STA); 277 278 /* 279 * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e. 280 * it points to where new data has been buffered. The 'CURR' (current) 281 * register points to the logical end of the ring-buffer - i.e. it 282 * points to where additional new data will be added. We loop here 283 * until the logical beginning equals the logical end (or in other 284 * words, until the ring-buffer is empty). 285 */ 286 current = NIC_GET(ED_P1_CURR); 287 288 /* Set NIC to page 0 registers to update boundary register. */ 289 NIC_PUT(ED_P1_CR, dp8390_cr_proto | ED_CR_PAGE_0 | ED_CR_STA); 290 291 if (next_packet == current) 292 return(0); 293 294 /* Get pointer to this buffer's header structure. */ 295 packet_ptr = RX_BUFBASE + (next_packet << ED_PAGE_SHIFT); 296 297 /* 298 * The byte count includes a 4 byte header that was added by 299 * the NIC. 300 */ 301 #ifdef SUPPORT_NE2000 302 ne2000_readmem(packet_ptr, (void *)&packet_hdr, 4); 303 #else 304 #ifdef _STANDALONE 305 pvbcopy((void *)packet_ptr, &packet_hdr, 4); 306 #else 307 bbcopy(vmembase + packet_ptr - dp8390_membase, &packet_hdr, 4); 308 #endif 309 #endif 310 311 len = packet_hdr.count; 312 313 #ifdef DP8390_OLDCHIPS 314 /* 315 * Try do deal with old, buggy chips that sometimes duplicate 316 * the low byte of the length into the high byte. We do this 317 * by simply ignoring the high byte of the length and always 318 * recalculating it. 319 * 320 * NOTE: sc->next_packet is pointing at the current packet. 321 */ 322 if (packet_hdr.next_packet >= next_packet) 323 nlen = (packet_hdr.next_packet - next_packet); 324 else 325 nlen = ((packet_hdr.next_packet - rec_page_start) + 326 (rec_page_stop - next_packet)); 327 --nlen; 328 if ((len & ED_PAGE_MASK) + sizeof(packet_hdr) > ED_PAGE_SIZE) 329 --nlen; 330 len = (len & ED_PAGE_MASK) | (nlen << ED_PAGE_SHIFT); 331 #ifdef DIAGNOSTIC 332 if (len != packet_hdr.count) { 333 printf(IFNAME ": length does not match next packet pointer\n"); 334 printf(IFNAME ": len %04x nlen %04x start %02x " 335 "first %02x curr %02x next %02x stop %02x\n", 336 packet_hdr.count, len, 337 rec_page_start, next_packet, current, 338 packet_hdr.next_packet, rec_page_stop); 339 } 340 #endif 341 #endif 342 343 if (packet_hdr.next_packet < rec_page_start || 344 packet_hdr.next_packet >= rec_page_stop) 345 panic(IFNAME ": RAM corrupt"); 346 347 len -= sizeof(struct dp8390_ring); 348 if (len < maxlen) { 349 /* Go get packet. */ 350 dp8390_read(packet_ptr + sizeof(struct dp8390_ring), 351 pkt, len); 352 } else 353 len = 0; 354 355 /* Update next packet pointer. */ 356 next_packet = packet_hdr.next_packet; 357 358 /* 359 * Update NIC boundary pointer - being careful to keep it one 360 * buffer behind (as recommended by NS databook). 361 */ 362 boundary = next_packet - 1; 363 if (boundary < rec_page_start) 364 boundary = rec_page_stop - 1; 365 NIC_PUT(ED_P0_BNRY, boundary); 366 367 return(len); 368 } 369