Changes in uspace/srv/hw/netif/dp8390/ne2000.c [7922dea:7e752b2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/netif/dp8390/ne2000.c
r7922dea r7e752b2 1 1 /* 2 * Copyright (c) 2009 Lukas Mejdrech 3 * Copyright (c) 2011 Martin Decky 4 * All rights reserved. 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: 5 3 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 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 9 8 * 10 * - Redistributions of source code must retain the above copyright11 * notice, this list of conditions and the following disclaimer.12 * - Redistributions in binary form must reproduce the above copyright13 * notice, this list of conditions and the following disclaimer in the14 * documentation and/or other materials provided with the distribution.15 * - The name of the author may not be used to endorse or promote products16 * derived from this software without specific prior written permission.17 9 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 10 * Disclaimer 11 * 12 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 19 13 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 14 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHORBE LIABLE FOR ANY DIRECT, INDIRECT,15 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, … … 26 20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */29 30 /*31 * This code is based upon the NE2000 driver for MINIX,32 * distributed according to a BSD-style license.33 22 * 34 * Copyright (c) 1987, 1997, 2006 Vrije Universiteit 35 * Copyright (c) 1992, 1994 Philip Homburg 36 * Copyright (c) 1996 G. Falzoni 37 * 23 * Changes: 24 * 2009 ported to HelenOS, Lukas Mejdrech 38 25 */ 39 26 … … 48 35 #include <stdio.h> 49 36 #include <unistd.h> 37 50 38 #include "dp8390_port.h" 39 40 /* 41 ne2000.c 42 43 Driver for the ne2000 ethernet cards. This file contains only the ne2000 44 specific code, the rest is in dp8390.c 45 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_vmd 54 //#include "config.h" 55 //#endif 56 57 #include "local.h" 51 58 #include "dp8390.h" 52 59 #include "ne2000.h" 53 60 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}; 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}; 64 93 65 94 /** Tests 8 bit NE2000 network interface. … … 68 97 * @param[in] pat The data pattern to be written. 69 98 * @returns True on success. 70 * @returns falseotherwise.71 */ 72 static int test_8(dpeth_t *dep, int pos, u int8_t *pat);99 * @returns FALSE otherwise. 100 */ 101 static int test_8(dpeth_t *dep, int pos, u8_t *pat); 73 102 74 103 /** Tests 16 bit NE2000 network interface. … … 77 106 * @param[in] pat The data pattern to be written. 78 107 * @returns True on success. 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) 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; 84 128 { 85 129 int byte; … … 87 131 int loc1, loc2; 88 132 testf_t f; 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 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 94 137 * on board is reachable through the dp8390. Note that the 95 138 * ne1000 is an 8bit card and has a memory region distict from 96 139 * the 16bit ne2000 97 140 */ 98 99 for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) { 141 142 for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++) 143 { 100 144 /* Reset the ethernet card */ 101 145 byte= inb_ne(dep, NE_RESET); 102 usleep(2000);146 milli_delay(2); 103 147 outb_ne(dep, NE_RESET, byte); 104 usleep(2000);105 148 milli_delay(2); 149 106 150 /* Reset the dp8390 */ 107 151 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT); 108 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++)152 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RST) == 0); i++) 109 153 ; /* Do nothing */ 110 154 111 155 /* Check if the dp8390 is really there */ 112 if ((inb_reg0(dep, DP_CR) & (CR_STP | CR_DM_ABORT)) != 113 (CR_STP | CR_DM_ABORT)) 156 if ((inb_reg0(dep, DP_CR) &(CR_STP|CR_DM_ABORT)) != 157 (CR_STP|CR_DM_ABORT)) 158 { 114 159 return 0; 115 160 } 161 116 162 /* Disable the receiver and init TCR and DCR. */ 117 163 outb_reg0(dep, DP_RCR, RCR_MON); 118 164 outb_reg0(dep, DP_TCR, TCR_NORMAL); 119 if (dep->de_16bit) { 165 if (dep->de_16bit) 166 { 120 167 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | 121 DCR_BMS); 122 } else { 168 DCR_BMS); 169 } 170 else 171 { 123 172 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | 124 DCR_BMS); 125 } 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; 135 } 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)) { 173 DCR_BMS); 174 } 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; 141 199 return 1; 142 200 } 143 201 } 144 145 202 return 0; 146 203 } 147 204 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) 205 /*===========================================================================* 206 * ne_init * 207 *===========================================================================*/ 208 void ne_init(dep) 209 dpeth_t *dep; 154 210 { 155 211 int i; 156 212 int word, sendq_nr; 157 213 158 214 /* Setup a transfer to get the ethernet address. */ 159 215 if (dep->de_16bit) … … 161 217 else 162 218 outb_reg0(dep, DP_RBCR0, 6); 163 164 219 outb_reg0(dep, DP_RBCR1, 0); 165 220 outb_reg0(dep, DP_RSAR0, 0); 166 221 outb_reg0(dep, DP_RSAR1, 0); 167 222 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 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 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 { 174 233 dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA); 175 }176 234 } 235 } 177 236 dep->de_data_port= dep->de_base_port + NE_DATA; 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 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 186 248 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */ 187 sendq_nr = dep->de_ramsize / 0x2000; 188 249 sendq_nr= dep->de_ramsize / 0x2000; 189 250 if (sendq_nr < 1) 190 sendq_nr 251 sendq_nr= 1; 191 252 else if (sendq_nr > SENDQ_NR) 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]; 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]; 210 291 int i; 211 212 outb_reg0(dep, DP_ISR, 0xff); 213 292 int r; 293 294 outb_reg0(dep, DP_ISR, 0xFF); 295 214 296 /* Setup a transfer to put the pattern. */ 215 297 outb_reg0(dep, DP_RBCR0, 4); 216 298 outb_reg0(dep, DP_RBCR1, 0); 217 outb_reg0(dep, DP_RSAR0, pos & 0xff);299 outb_reg0(dep, DP_RSAR0, pos &0xFF); 218 300 outb_reg0(dep, DP_RSAR1, pos >> 8); 219 301 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 220 221 for (i = 0; i <4; i++)302 303 for (i= 0; i<4; i++) 222 304 outb_ne(dep, NE_DATA, pat[i]); 223 224 for (i = 0; i < N; i++) { 225 if (inb_reg0(dep, DP_ISR) & ISR_RDC) 305 306 for (i= 0; i<N; i++) 307 { 308 if (inb_reg0(dep, DP_ISR) &ISR_RDC) 226 309 break; 227 310 } 228 229 if (i == N) { 230 printf("NE1000 remote DMA test failed\n"); 311 if (i == N) 312 { 313 if (debug) 314 { 315 printf("%s: NE1000 remote DMA test failed\n", 316 dep->de_name); 317 } 231 318 return 0; 232 319 } 233 320 234 321 outb_reg0(dep, DP_RBCR0, 4); 235 322 outb_reg0(dep, DP_RBCR1, 0); 236 outb_reg0(dep, DP_RSAR0, pos & 0xff);323 outb_reg0(dep, DP_RSAR0, pos &0xFF); 237 324 outb_reg0(dep, DP_RSAR1, pos >> 8); 238 325 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]; 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]; 249 343 int i; 250 251 outb_reg0(dep, DP_ISR, 0xff); 252 344 int r; 345 346 outb_reg0(dep, DP_ISR, 0xFF); 347 253 348 /* Setup a transfer to put the pattern. */ 254 349 outb_reg0(dep, DP_RBCR0, 4); 255 350 outb_reg0(dep, DP_RBCR1, 0); 256 outb_reg0(dep, DP_RSAR0, pos & 0xff);351 outb_reg0(dep, DP_RSAR0, pos &0xFF); 257 352 outb_reg0(dep, DP_RSAR1, pos >> 8); 258 353 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++) { 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 { 264 362 if (inb_reg0(dep, DP_ISR) &ISR_RDC) 265 363 break; 266 364 } 267 268 if (i == N) { 269 printf("NE2000 remote DMA test failed\n"); 365 if (i == N) 366 { 367 if (debug) 368 { 369 printf("%s: NE2000 remote DMA test failed\n", 370 dep->de_name); 371 } 270 372 return 0; 271 373 } 272 374 273 375 outb_reg0(dep, DP_RBCR0, 4); 274 376 outb_reg0(dep, DP_RBCR1, 0); 275 outb_reg0(dep, DP_RSAR0, pos & 0xff);377 outb_reg0(dep, DP_RSAR0, pos &0xFF); 276 378 outb_reg0(dep, DP_RSAR1, pos >> 8); 277 379 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 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 { 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 292 398 /* Reset the ethernet card */ 293 int byte= inb_ne(dep, NE_RESET);294 usleep(2000);399 byte= inb_ne(dep, NE_RESET); 400 milli_delay(2); 295 401 outb_ne(dep, NE_RESET, byte); 296 402 } 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 */ 297 414 298 415 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.