Changes in uspace/srv/hw/netif/dp8390/ne2000.c [7e752b2:e0854e3] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/netif/dp8390/ne2000.c
r7e752b2 re0854e3 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 FALSEotherwise.109 */ 110 static int test_16(dpeth_t *dep, int pos, u 8_t *pat);79 * @returns false otherwise. 80 */ 81 static int test_16(dpeth_t *dep, int pos, uint8_t *pat); 111 82 112 83 /** Stops the NE2000 network interface. … … 114 85 */ 115 86 static void ne_stop(dpeth_t *dep); 116 //_PROTOTYPE(static void milli_delay, (unsigned long millis) );117 87 118 88 /** Initializes the NE2000 network interface. … … 121 91 void ne_init(struct dpeth *dep); 122 92 123 /*===========================================================================* 124 * ne_probe * 125 *===========================================================================*/ 126 int ne_probe(dep) 127 dpeth_t *dep; 93 int ne_probe(dpeth_t *dep) 128 94 { 129 95 int byte; … … 131 97 int loc1, loc2; 132 98 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 99 100 dep->de_dp8390_port = dep->de_base_port + NE_DP8390; 101 102 /* 103 * We probe for an ne1000 or an ne2000 by testing whether the 137 104 * on board is reachable through the dp8390. Note that the 138 105 * ne1000 is an 8bit card and has a memory region distict from 139 106 * the 16bit ne2000 140 107 */ 141 142 for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++) 143 { 108 109 for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) { 144 110 /* Reset the ethernet card */ 145 111 byte= inb_ne(dep, NE_RESET); 146 milli_delay(2);112 usleep(2000); 147 113 outb_ne(dep, NE_RESET, byte); 148 milli_delay(2);149 114 usleep(2000); 115 150 116 /* Reset the dp8390 */ 151 117 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++)118 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++) 153 119 ; /* Do nothing */ 154 120 155 121 /* 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 { 122 if ((inb_reg0(dep, DP_CR) & (CR_STP | CR_DM_ABORT)) != 123 (CR_STP | CR_DM_ABORT)) 159 124 return 0; 160 } 161 125 162 126 /* Disable the receiver and init TCR and DCR. */ 163 127 outb_reg0(dep, DP_RCR, RCR_MON); 164 128 outb_reg0(dep, DP_TCR, TCR_NORMAL); 165 if (dep->de_16bit) 166 { 129 if (dep->de_16bit) { 167 130 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | 168 DCR_BMS); 131 DCR_BMS); 132 } else { 133 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | 134 DCR_BMS); 169 135 } 170 else 171 { 172 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | 173 DCR_BMS); 174 } 175 176 if (dep->de_16bit) 177 { 136 137 if (dep->de_16bit) { 178 138 loc1= NE2000_START; 179 139 loc2= NE2000_START + NE2000_SIZE - 4; 180 140 f= test_16; 181 } 182 else 183 { 141 } else { 184 142 loc1= NE1000_START; 185 143 loc2= NE1000_START + NE1000_SIZE - 4; 186 144 f= test_8; 187 145 } 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; 146 147 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) && 148 f(dep, loc1, pat2) && f(dep, loc1, pat3) && 149 f(dep, loc2, pat0) && f(dep, loc2, pat1) && 150 f(dep, loc2, pat2) && f(dep, loc2, pat3)) { 151 dep->de_initf = ne_init; 152 dep->de_stopf = ne_stop; 199 153 return 1; 200 154 } 201 155 } 156 202 157 return 0; 203 158 } 204 159 205 /*===========================================================================* 206 * ne_init * 207 *===========================================================================*/ 208 void ne_init(dep) 209 dpeth_t *dep; 160 void ne_init(dpeth_t *dep) 210 161 { 211 162 int i; 212 163 int word, sendq_nr; 213 164 214 165 /* Setup a transfer to get the ethernet address. */ 215 166 if (dep->de_16bit) … … 217 168 else 218 169 outb_reg0(dep, DP_RBCR0, 6); 170 219 171 outb_reg0(dep, DP_RBCR1, 0); 220 172 outb_reg0(dep, DP_RSAR0, 0); 221 173 outb_reg0(dep, DP_RSAR1, 0); 222 174 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 { 175 176 for (i = 0; i < 6; i++) { 177 if (dep->de_16bit) { 178 word = inw_ne(dep, NE_DATA); 179 dep->de_address.ea_addr[i] = word; 180 } else 233 181 dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA); 234 235 }182 } 183 236 184 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 185 if (dep->de_16bit) { 186 dep->de_ramsize = NE2000_SIZE; 187 dep->de_offset_page = NE2000_START / DP_PAGESIZE; 188 } else { 189 dep->de_ramsize = NE1000_SIZE; 190 dep->de_offset_page = NE1000_START / DP_PAGESIZE; 191 } 192 248 193 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */ 249 sendq_nr= dep->de_ramsize / 0x2000; 194 sendq_nr = dep->de_ramsize / 0x2000; 195 250 196 if (sendq_nr < 1) 251 sendq_nr = 1;197 sendq_nr = 1; 252 198 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]; 199 sendq_nr = SENDQ_NR; 200 201 dep->de_sendq_nr = sendq_nr; 202 for (i = 0; i < sendq_nr; i++) 203 dep->de_sendq[i].sq_sendpage = dep->de_offset_page + i * SENDQ_PAGES; 204 205 dep->de_startpage = dep->de_offset_page + i * SENDQ_PAGES; 206 dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE; 207 208 printf("%s: Novell NE%d000 ethernet card at I/O address " 209 "%#lx, memory size %#lx, irq %d\n", 210 dep->de_name, dep->de_16bit ? 2 : 1, 211 dep->de_base_port, dep->de_ramsize, dep->de_irq); 212 } 213 214 static int test_8(dpeth_t *dep, int pos, uint8_t *pat) 215 { 216 uint8_t buf[4]; 291 217 int i; 292 int r; 293 294 outb_reg0(dep, DP_ISR, 0xFF); 295 218 219 outb_reg0(dep, DP_ISR, 0xff); 220 296 221 /* Setup a transfer to put the pattern. */ 297 222 outb_reg0(dep, DP_RBCR0, 4); 298 223 outb_reg0(dep, DP_RBCR1, 0); 299 outb_reg0(dep, DP_RSAR0, pos & 0xFF);224 outb_reg0(dep, DP_RSAR0, pos & 0xff); 300 225 outb_reg0(dep, DP_RSAR1, pos >> 8); 301 226 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 302 303 for (i = 0; i<4; i++)227 228 for (i = 0; i < 4; i++) 304 229 outb_ne(dep, NE_DATA, pat[i]); 305 306 for (i= 0; i<N; i++) 307 { 230 231 for (i = 0; i < N; i++) { 232 if (inb_reg0(dep, DP_ISR) & ISR_RDC) 233 break; 234 } 235 236 if (i == N) { 237 printf("%s: NE1000 remote DMA test failed\n", dep->de_name); 238 return 0; 239 } 240 241 outb_reg0(dep, DP_RBCR0, 4); 242 outb_reg0(dep, DP_RBCR1, 0); 243 outb_reg0(dep, DP_RSAR0, pos & 0xff); 244 outb_reg0(dep, DP_RSAR1, pos >> 8); 245 outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA); 246 247 for (i = 0; i < 4; i++) 248 buf[i] = inb_ne(dep, NE_DATA); 249 250 return (memcmp(buf, pat, 4) == 0); 251 } 252 253 static int test_16(dpeth_t *dep, int pos, uint8_t *pat) 254 { 255 uint8_t buf[4]; 256 int i; 257 258 outb_reg0(dep, DP_ISR, 0xff); 259 260 /* Setup a transfer to put the pattern. */ 261 outb_reg0(dep, DP_RBCR0, 4); 262 outb_reg0(dep, DP_RBCR1, 0); 263 outb_reg0(dep, DP_RSAR0, pos & 0xff); 264 outb_reg0(dep, DP_RSAR1, pos >> 8); 265 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 266 267 for (i = 0; i < 4; i += 2) 268 outw_ne(dep, NE_DATA, *(uint16_t *)(pat + i)); 269 270 for (i = 0; i < N; i++) { 308 271 if (inb_reg0(dep, DP_ISR) &ISR_RDC) 309 272 break; 310 273 } 311 if (i == N) 312 { 313 if (debug) 314 { 315 printf("%s: NE1000 remote DMA test failed\n", 316 dep->de_name); 317 } 274 275 if (i == N) { 276 printf("%s: NE2000 remote DMA test failed\n", dep->de_name); 318 277 return 0; 319 278 } 320 279 321 280 outb_reg0(dep, DP_RBCR0, 4); 322 281 outb_reg0(dep, DP_RBCR1, 0); 323 outb_reg0(dep, DP_RSAR0, pos & 0xFF);282 outb_reg0(dep, DP_RSAR0, pos & 0xff); 324 283 outb_reg0(dep, DP_RSAR1, pos >> 8); 325 284 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 285 286 for (i = 0; i < 4; i += 2) 287 *(uint16_t *)(buf + i) = inw_ne(dep, NE_DATA); 288 289 return (memcmp(buf, pat, 4) == 0); 290 } 291 292 static void ne_stop(dpeth_t *dep) 293 { 398 294 /* Reset the ethernet card */ 399 byte= inb_ne(dep, NE_RESET);400 milli_delay(2);295 int byte = inb_ne(dep, NE_RESET); 296 usleep(2000); 401 297 outb_ne(dep, NE_RESET, byte); 402 298 } 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 299 415 300 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.