Changeset ae1f70e in mainline for uspace/srv/hw/netif/dp8390/ne2000.c
- Timestamp:
- 2011-01-07T08:54:28Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0f191a2, 8f8a0cd6
- Parents:
- f03d3786 (diff), 3d5e190 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/netif/dp8390/ne2000.c
rf03d3786 rae1f70e 1 1 /* 2 * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 3 * 4 * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 5 * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 6 * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission. 7 * * Any deviations from these conditions require written permission from the copyright holder in advance 8 * 9 * 10 * Disclaimer 11 * 12 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 2 * Copyright (c) 2009 Lukas Mejdrech 3 * Copyright (c) 2011 Martin Decky 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * - Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * - Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * - The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 13 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 14 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 15 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORSBE LIABLE FOR ANY DIRECT, INDIRECT,21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 16 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 17 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, … … 20 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * 23 * Changes: 24 * 2009 ported to HelenOS, Lukas Mejdrech 28 */ 29 30 /* 31 * This code is based upon the NE2000 driver for MINIX, 32 * distributed according to a BSD-style license. 33 * 34 * Copyright (c) 1987, 1997, 2006 Vrije Universiteit 35 * Copyright (c) 1992, 1994 Philip Homburg 36 * Copyright (c) 1996 G. Falzoni 37 * 25 38 */ 26 39 … … 35 48 #include <stdio.h> 36 49 #include <unistd.h> 37 38 50 #include "dp8390_port.h" 39 40 /*41 ne2000.c42 43 Driver for the ne2000 ethernet cards. This file contains only the ne200044 specific code, the rest is in dp8390.c45 46 Created: March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>47 */48 49 //#include "../drivers.h"50 51 //#include <net/gen/ether.h>52 //#include <net/gen/eth_io.h>53 //#if __minix_vmd54 //#include "config.h"55 //#endif56 57 #include "local.h"58 51 #include "dp8390.h" 59 52 #include "ne2000.h" 60 53 61 #if ENABLE_NE2000 62 63 /** Number of bytes to transfer. 64 */ 65 #define N 100 66 67 //#define MILLIS_TO_TICKS(m) (((m)*HZ/1000)+1) 68 69 /** Sleeps for the defined millicesonds. 70 * @param[in] millis The number of milliseconds to sleep. 71 */ 72 #define milli_delay(millis) usleep((millis) * 1000) 73 74 /** Type definition of the testing function. 75 */ 76 _PROTOTYPE(typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat) ); 77 78 /** First data pattern. 79 */ 80 u8_t pat0[]= {0x00, 0x00, 0x00, 0x00}; 81 82 /** Second data pattern. 83 */ 84 u8_t pat1[]= {0xFF, 0xFF, 0xFF, 0xFF}; 85 86 /** Third data pattern. 87 */ 88 u8_t pat2[]= {0xA5, 0x5A, 0x69, 0x96}; 89 90 /** Fourth data pattern. 91 */ 92 u8_t pat3[]= {0x96, 0x69, 0x5A, 0xA5}; 54 /** Number of bytes to transfer */ 55 #define N 100 56 57 typedef int (*testf_t)(dpeth_t *dep, int pos, uint8_t *pat); 58 59 /** Data patterns */ 60 uint8_t pat0[] = {0x00, 0x00, 0x00, 0x00}; 61 uint8_t pat1[] = {0xFF, 0xFF, 0xFF, 0xFF}; 62 uint8_t pat2[] = {0xA5, 0x5A, 0x69, 0x96}; 63 uint8_t pat3[] = {0x96, 0x69, 0x5A, 0xA5}; 93 64 94 65 /** Tests 8 bit NE2000 network interface. … … 97 68 * @param[in] pat The data pattern to be written. 98 69 * @returns True on success. 99 * @returns FALSEotherwise.100 */ 101 static int test_8(dpeth_t *dep, int pos, u 8_t *pat);70 * @returns false otherwise. 71 */ 72 static int test_8(dpeth_t *dep, int pos, uint8_t *pat); 102 73 103 74 /** Tests 16 bit NE2000 network interface. … … 106 77 * @param[in] pat The data pattern to be written. 107 78 * @returns True on success. 108 * @returns FALSE otherwise. 109 */ 110 static int test_16(dpeth_t *dep, int pos, u8_t *pat); 111 112 /** Stops the NE2000 network interface. 113 * @param[in,out] dep The network interface structure. 114 */ 115 static void ne_stop(dpeth_t *dep); 116 //_PROTOTYPE(static void milli_delay, (unsigned long millis) ); 117 118 /** Initializes the NE2000 network interface. 119 * @param[in,out] dep The network interface structure. 120 */ 121 void ne_init(struct dpeth *dep); 122 123 /*===========================================================================* 124 * ne_probe * 125 *===========================================================================*/ 126 int ne_probe(dep) 127 dpeth_t *dep; 79 * @returns false otherwise. 80 */ 81 static int test_16(dpeth_t *dep, int pos, uint8_t *pat); 82 83 int ne_probe(dpeth_t *dep) 128 84 { 129 85 int byte; … … 131 87 int loc1, loc2; 132 88 testf_t f; 133 134 dep->de_dp8390_port= dep->de_base_port + NE_DP8390; 135 136 /* We probe for an ne1000 or an ne2000 by testing whether the 89 90 dep->de_dp8390_port = dep->de_base_port + NE_DP8390; 91 92 /* 93 * We probe for an ne1000 or an ne2000 by testing whether the 137 94 * on board is reachable through the dp8390. Note that the 138 95 * ne1000 is an 8bit card and has a memory region distict from 139 96 * the 16bit ne2000 140 97 */ 141 142 for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++) 143 { 98 99 for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) { 144 100 /* Reset the ethernet card */ 145 101 byte= inb_ne(dep, NE_RESET); 146 milli_delay(2);102 usleep(2000); 147 103 outb_ne(dep, NE_RESET, byte); 148 milli_delay(2);149 104 usleep(2000); 105 150 106 /* Reset the dp8390 */ 151 107 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT); 152 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)108 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++) 153 109 ; /* Do nothing */ 154 110 155 111 /* Check if the dp8390 is really there */ 156 if ((inb_reg0(dep, DP_CR) &(CR_STP|CR_DM_ABORT)) != 157 (CR_STP|CR_DM_ABORT)) 158 { 112 if ((inb_reg0(dep, DP_CR) & (CR_STP | CR_DM_ABORT)) != 113 (CR_STP | CR_DM_ABORT)) 159 114 return 0; 160 } 161 115 162 116 /* Disable the receiver and init TCR and DCR. */ 163 117 outb_reg0(dep, DP_RCR, RCR_MON); 164 118 outb_reg0(dep, DP_TCR, TCR_NORMAL); 165 if (dep->de_16bit) 166 { 119 if (dep->de_16bit) { 167 120 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | 168 DCR_BMS); 121 DCR_BMS); 122 } else { 123 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | 124 DCR_BMS); 169 125 } 170 else 171 { 172 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | 173 DCR_BMS); 126 127 if (dep->de_16bit) { 128 loc1 = NE2000_START; 129 loc2 = NE2000_START + NE2000_SIZE - 4; 130 f = test_16; 131 } else { 132 loc1 = NE1000_START; 133 loc2 = NE1000_START + NE1000_SIZE - 4; 134 f = test_8; 174 135 } 175 176 if (dep->de_16bit) 177 { 178 loc1= NE2000_START; 179 loc2= NE2000_START + NE2000_SIZE - 4; 180 f= test_16; 181 } 182 else 183 { 184 loc1= NE1000_START; 185 loc2= NE1000_START + NE1000_SIZE - 4; 186 f= test_8; 187 } 188 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) && 189 f(dep, loc1, pat2) && f(dep, loc1, pat3) && 190 f(dep, loc2, pat0) && f(dep, loc2, pat1) && 191 f(dep, loc2, pat2) && f(dep, loc2, pat3)) 192 { 193 /* We don't need a memory segment */ 194 dep->de_linmem= 0; 195 if (!dep->de_pci) 196 dep->de_initf= ne_init; 197 dep->de_stopf= ne_stop; 198 dep->de_prog_IO= 1; 136 137 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) && 138 f(dep, loc1, pat2) && f(dep, loc1, pat3) && 139 f(dep, loc2, pat0) && f(dep, loc2, pat1) && 140 f(dep, loc2, pat2) && f(dep, loc2, pat3)) { 199 141 return 1; 200 142 } 201 143 } 144 202 145 return 0; 203 146 } 204 147 205 /*===========================================================================* 206 * ne_init * 207 *===========================================================================*/ 208 void ne_init(dep) 209 dpeth_t *dep; 148 /** Initializes the NE2000 network interface. 149 * 150 * @param[in,out] dep The network interface structure. 151 * 152 */ 153 void ne_init(dpeth_t *dep) 210 154 { 211 155 int i; 212 156 int word, sendq_nr; 213 157 214 158 /* Setup a transfer to get the ethernet address. */ 215 159 if (dep->de_16bit) … … 217 161 else 218 162 outb_reg0(dep, DP_RBCR0, 6); 163 219 164 outb_reg0(dep, DP_RBCR1, 0); 220 165 outb_reg0(dep, DP_RSAR0, 0); 221 166 outb_reg0(dep, DP_RSAR1, 0); 222 167 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 223 224 for (i= 0; i<6; i++) 225 { 226 if (dep->de_16bit) 227 { 228 word= inw_ne(dep, NE_DATA); 229 dep->de_address.ea_addr[i]= word; 230 } 231 else 232 { 168 169 for (i = 0; i < 6; i++) { 170 if (dep->de_16bit) { 171 word = inw_ne(dep, NE_DATA); 172 dep->de_address.ea_addr[i] = word; 173 } else 233 174 dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA); 234 235 }175 } 176 236 177 dep->de_data_port= dep->de_base_port + NE_DATA; 237 if (dep->de_16bit) 238 { 239 dep->de_ramsize= NE2000_SIZE; 240 dep->de_offset_page= NE2000_START / DP_PAGESIZE; 241 } 242 else 243 { 244 dep->de_ramsize= NE1000_SIZE; 245 dep->de_offset_page= NE1000_START / DP_PAGESIZE; 246 } 247 178 if (dep->de_16bit) { 179 dep->de_ramsize = NE2000_SIZE; 180 dep->de_offset_page = NE2000_START / DP_PAGESIZE; 181 } else { 182 dep->de_ramsize = NE1000_SIZE; 183 dep->de_offset_page = NE1000_START / DP_PAGESIZE; 184 } 185 248 186 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */ 249 sendq_nr= dep->de_ramsize / 0x2000; 187 sendq_nr = dep->de_ramsize / 0x2000; 188 250 189 if (sendq_nr < 1) 251 sendq_nr = 1;190 sendq_nr = 1; 252 191 else if (sendq_nr > SENDQ_NR) 253 sendq_nr= SENDQ_NR; 254 dep->de_sendq_nr= sendq_nr; 255 for (i= 0; i<sendq_nr; i++) 256 { 257 dep->de_sendq[i].sq_sendpage= dep->de_offset_page + 258 i*SENDQ_PAGES; 259 } 260 261 dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES; 262 dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE; 263 264 /* Can't override the default IRQ. */ 265 dep->de_irq &= ~DEI_DEFAULT; 266 267 if (!debug) 268 { 269 printf("%s: NE%d000 at %#lx:%d\n", 270 dep->de_name, dep->de_16bit ? 2 : 1, 271 dep->de_base_port, dep->de_irq); 272 } 273 else 274 { 275 printf("%s: Novell NE%d000 ethernet card at I/O address " 276 "%#lx, memory size %#lx, irq %d\n", 277 dep->de_name, dep->de_16bit ? 2 : 1, 278 dep->de_base_port, dep->de_ramsize, dep->de_irq); 279 } 280 } 281 282 /*===========================================================================* 283 * test_8 * 284 *===========================================================================*/ 285 static int test_8(dep, pos, pat) 286 dpeth_t *dep; 287 int pos; 288 u8_t *pat; 289 { 290 u8_t buf[4]; 291 int i; 292 int r; 293 294 outb_reg0(dep, DP_ISR, 0xFF); 295 192 sendq_nr = SENDQ_NR; 193 194 dep->de_sendq_nr = sendq_nr; 195 for (i = 0; i < sendq_nr; i++) 196 dep->de_sendq[i].sq_sendpage = dep->de_offset_page + i * SENDQ_PAGES; 197 198 dep->de_startpage = dep->de_offset_page + i * SENDQ_PAGES; 199 dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE; 200 201 printf("Novell NE%d000 ethernet card at I/O address " 202 "%#lx, memory size %#lx, irq %d\n", 203 dep->de_16bit ? 2 : 1, dep->de_base_port, dep->de_ramsize, 204 dep->de_irq); 205 } 206 207 static int test_8(dpeth_t *dep, int pos, uint8_t *pat) 208 { 209 uint8_t buf[4]; 210 int i; 211 212 outb_reg0(dep, DP_ISR, 0xff); 213 296 214 /* Setup a transfer to put the pattern. */ 297 215 outb_reg0(dep, DP_RBCR0, 4); 298 216 outb_reg0(dep, DP_RBCR1, 0); 299 outb_reg0(dep, DP_RSAR0, pos & 0xFF);217 outb_reg0(dep, DP_RSAR0, pos & 0xff); 300 218 outb_reg0(dep, DP_RSAR1, pos >> 8); 301 219 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 302 303 for (i = 0; i<4; i++)220 221 for (i = 0; i < 4; i++) 304 222 outb_ne(dep, NE_DATA, pat[i]); 305 306 for (i= 0; i<N; i++) 307 { 223 224 for (i = 0; i < N; i++) { 225 if (inb_reg0(dep, DP_ISR) & ISR_RDC) 226 break; 227 } 228 229 if (i == N) { 230 printf("NE1000 remote DMA test failed\n"); 231 return 0; 232 } 233 234 outb_reg0(dep, DP_RBCR0, 4); 235 outb_reg0(dep, DP_RBCR1, 0); 236 outb_reg0(dep, DP_RSAR0, pos & 0xff); 237 outb_reg0(dep, DP_RSAR1, pos >> 8); 238 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 239 240 for (i = 0; i < 4; i++) 241 buf[i] = inb_ne(dep, NE_DATA); 242 243 return (memcmp(buf, pat, 4) == 0); 244 } 245 246 static int test_16(dpeth_t *dep, int pos, uint8_t *pat) 247 { 248 uint8_t buf[4]; 249 int i; 250 251 outb_reg0(dep, DP_ISR, 0xff); 252 253 /* Setup a transfer to put the pattern. */ 254 outb_reg0(dep, DP_RBCR0, 4); 255 outb_reg0(dep, DP_RBCR1, 0); 256 outb_reg0(dep, DP_RSAR0, pos & 0xff); 257 outb_reg0(dep, DP_RSAR1, pos >> 8); 258 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 259 260 for (i = 0; i < 4; i += 2) 261 outw_ne(dep, NE_DATA, *(uint16_t *)(pat + i)); 262 263 for (i = 0; i < N; i++) { 308 264 if (inb_reg0(dep, DP_ISR) &ISR_RDC) 309 265 break; 310 266 } 311 if (i == N) 312 { 313 if (debug) 314 { 315 printf("%s: NE1000 remote DMA test failed\n", 316 dep->de_name); 317 } 267 268 if (i == N) { 269 printf("NE2000 remote DMA test failed\n"); 318 270 return 0; 319 271 } 320 321 outb_reg0(dep, DP_RBCR0, 4); 322 outb_reg0(dep, DP_RBCR1, 0); 323 outb_reg0(dep, DP_RSAR0, pos & 0xFF);272 273 outb_reg0(dep, DP_RBCR0, 4); 274 outb_reg0(dep, DP_RBCR1, 0); 275 outb_reg0(dep, DP_RSAR0, pos & 0xff); 324 276 outb_reg0(dep, DP_RSAR1, pos >> 8); 325 277 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 326 327 for (i= 0; i<4; i++) 328 buf[i]= inb_ne(dep, NE_DATA); 329 330 r= (memcmp(buf, pat, 4) == 0); 331 return r; 332 } 333 334 /*===========================================================================* 335 * test_16 * 336 *===========================================================================*/ 337 static int test_16(dep, pos, pat) 338 dpeth_t *dep; 339 int pos; 340 u8_t *pat; 341 { 342 u8_t buf[4]; 343 int i; 344 int r; 345 346 outb_reg0(dep, DP_ISR, 0xFF); 347 348 /* Setup a transfer to put the pattern. */ 349 outb_reg0(dep, DP_RBCR0, 4); 350 outb_reg0(dep, DP_RBCR1, 0); 351 outb_reg0(dep, DP_RSAR0, pos &0xFF); 352 outb_reg0(dep, DP_RSAR1, pos >> 8); 353 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 354 355 for (i= 0; i<4; i += 2) 356 { 357 outw_ne(dep, NE_DATA, *(u16_t *)(pat+i)); 358 } 359 360 for (i= 0; i<N; i++) 361 { 362 if (inb_reg0(dep, DP_ISR) &ISR_RDC) 363 break; 364 } 365 if (i == N) 366 { 367 if (debug) 368 { 369 printf("%s: NE2000 remote DMA test failed\n", 370 dep->de_name); 371 } 372 return 0; 373 } 374 375 outb_reg0(dep, DP_RBCR0, 4); 376 outb_reg0(dep, DP_RBCR1, 0); 377 outb_reg0(dep, DP_RSAR0, pos &0xFF); 378 outb_reg0(dep, DP_RSAR1, pos >> 8); 379 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 380 381 for (i= 0; i<4; i += 2) 382 { 383 *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA); 384 } 385 386 r= (memcmp(buf, pat, 4) == 0); 387 return r; 388 } 389 390 /*===========================================================================* 391 * ne_stop * 392 *===========================================================================*/ 393 static void ne_stop(dep) 394 dpeth_t *dep; 395 { 396 int byte; 397 278 279 for (i = 0; i < 4; i += 2) 280 *(uint16_t *)(buf + i) = inw_ne(dep, NE_DATA); 281 282 return (memcmp(buf, pat, 4) == 0); 283 } 284 285 /** Stop the NE2000 network interface. 286 * 287 * @param[in,out] dep The network interface structure. 288 * 289 */ 290 void ne_stop(dpeth_t *dep) 291 { 398 292 /* Reset the ethernet card */ 399 byte= inb_ne(dep, NE_RESET);400 milli_delay(2);293 int byte = inb_ne(dep, NE_RESET); 294 usleep(2000); 401 295 outb_ne(dep, NE_RESET, byte); 402 296 } 403 /*404 static void milli_delay(unsigned long millis)405 {406 tickdelay(MILLIS_TO_TICKS(millis));407 }408 */409 #endif /* ENABLE_NE2000 */410 411 /*412 * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $413 */414 297 415 298 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.