Changeset 3c106e88 in mainline for uspace/srv/hw/netif/dp8390/ne2000.c
- Timestamp:
- 2011-01-09T23:09:02Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 774e6d1a
- Parents:
- 7ea7db31
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hw/netif/dp8390/ne2000.c
r7ea7db31 r3c106e88 28 28 */ 29 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 * 38 */ 39 40 /** @addtogroup ne2k 30 /** @addtogroup ne2000 41 31 * @{ 42 32 */ 43 33 44 34 /** @file 45 * NE1000 and NE2000 network interface initialization and probe functions implementation. 46 */ 47 48 #include <stdio.h> 49 #include <unistd.h> 50 #include "dp8390_port.h" 35 * NE2000 network interface implementation. 36 */ 37 38 #include <assert.h> 39 #include <async.h> 40 #include <ddi.h> 41 #include <errno.h> 42 #include <err.h> 43 #include <malloc.h> 44 #include <sysinfo.h> 45 #include <ipc/ipc.h> 46 #include <ipc/services.h> 47 #include <ipc/irc.h> 48 #include <net/modules.h> 49 #include <packet_client.h> 50 #include <adt/measured_strings.h> 51 #include <net/device.h> 52 #include <netif_skel.h> 53 #include <nil_interface.h> 51 54 #include "dp8390.h" 52 #include "ne2000.h" 53 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}; 64 65 /** Tests 8 bit NE2000 network interface. 66 * @param[in,out] dep The network interface structure. 67 * @param[in] pos The starting position. 68 * @param[in] pat The data pattern to be written. 69 * @returns True on success. 70 * @returns false otherwise. 71 */ 72 static int test_8(dpeth_t *dep, int pos, uint8_t *pat); 73 74 /** Tests 16 bit NE2000 network interface. 75 * @param[in,out] dep The network interface structure. 76 * @param[in] pos The starting position. 77 * @param[in] pat The data pattern to be written. 78 * @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) 84 { 85 int byte; 86 int i; 87 int loc1, loc2; 88 testf_t f; 89 90 dep->de_dp8390_port = dep->de_base_port + NE_DP8390; 55 56 /** Return the device from the interrupt call. 57 * 58 * @param[in] call The interrupt call. 59 * 60 */ 61 #define IRQ_GET_DEVICE(call) ((device_id_t) IPC_GET_IMETHOD(call)) 62 63 /** Return the ISR from the interrupt call. 64 * 65 * @param[in] call The interrupt call. 66 * 67 */ 68 #define IRQ_GET_ISR(call) ((int) IPC_GET_ARG2(call)) 69 70 static int irc_service = 0; 71 static int irc_phone = -1; 72 73 /** DP8390 kernel interrupt command sequence. 74 * 75 */ 76 static irq_cmd_t ne2k_cmds[] = { 77 { 78 .cmd = CMD_PIO_READ_8, 79 .addr = NULL, 80 .dstarg = 2 81 }, 82 { 83 .cmd = CMD_BTEST, 84 .value = 0x7f, 85 .srcarg = 2, 86 .dstarg = 3, 87 }, 88 { 89 .cmd = CMD_PREDICATE, 90 .value = 2, 91 .srcarg = 3 92 }, 93 { 94 .cmd = CMD_PIO_WRITE_A_8, 95 .addr = NULL, 96 .srcarg = 3 97 }, 98 { 99 .cmd = CMD_ACCEPT 100 } 101 }; 102 103 /** DP8390 kernel interrupt code. 104 * 105 */ 106 static irq_code_t ne2k_code = { 107 sizeof(ne2k_cmds) / sizeof(irq_cmd_t), 108 ne2k_cmds 109 }; 110 111 /** Handle the interrupt notification. 112 * 113 * This is the interrupt notification function. 114 * 115 * @param[in] iid Interrupt notification identifier. 116 * @param[in] call Interrupt notification. 117 * 118 */ 119 static void irq_handler(ipc_callid_t iid, ipc_call_t *call) 120 { 121 device_id_t device_id = IRQ_GET_DEVICE(*call); 122 netif_device_t *device; 123 int nil_phone; 124 ne2k_t *ne2k; 125 126 fibril_rwlock_read_lock(&netif_globals.lock); 127 128 if (find_device(device_id, &device) == EOK) { 129 nil_phone = device->nil_phone; 130 ne2k = (ne2k_t *) device->specific; 131 } else 132 ne2k = NULL; 133 134 fibril_rwlock_read_unlock(&netif_globals.lock); 135 136 if (ne2k != NULL) 137 ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), nil_phone, device_id); 138 } 139 140 /** Change the network interface state. 141 * 142 * @param[in,out] device Network interface. 143 * @param[in] state New state. 144 * 145 */ 146 static void change_state(netif_device_t *device, device_state_t state) 147 { 148 if (device->state != state) { 149 device->state = state; 150 151 const char *desc; 152 switch (state) { 153 case NETIF_ACTIVE: 154 desc = "active"; 155 break; 156 case NETIF_STOPPED: 157 desc = "stopped"; 158 break; 159 default: 160 desc = "unknown"; 161 } 162 163 printf("%s: State changed to %s\n", NAME, desc); 164 } 165 } 166 167 int netif_specific_message(ipc_callid_t callid, ipc_call_t *call, 168 ipc_call_t *answer, size_t *count) 169 { 170 return ENOTSUP; 171 } 172 173 int netif_get_device_stats(device_id_t device_id, device_stats_t *stats) 174 { 175 if (!stats) 176 return EBADMEM; 177 178 netif_device_t *device; 179 int rc = find_device(device_id, &device); 180 if (rc != EOK) 181 return rc; 182 183 ne2k_t *ne2k = (ne2k_t *) device->specific; 184 185 memcpy(stats, &ne2k->stats, sizeof(device_stats_t)); 186 return EOK; 187 } 188 189 int netif_get_addr_message(device_id_t device_id, measured_string_t *address) 190 { 191 if (!address) 192 return EBADMEM; 193 194 netif_device_t *device; 195 int rc = find_device(device_id, &device); 196 if (rc != EOK) 197 return rc; 198 199 ne2k_t *ne2k = (ne2k_t *) device->specific; 200 201 address->value = ne2k->mac; 202 address->length = ETH_ADDR; 203 return EOK; 204 } 205 206 int netif_probe_message(device_id_t device_id, int irq, void *io) 207 { 208 netif_device_t *device = 209 (netif_device_t *) malloc(sizeof(netif_device_t)); 210 if (!device) 211 return ENOMEM; 212 213 ne2k_t *ne2k = (ne2k_t *) malloc(sizeof(ne2k_t)); 214 if (!ne2k) { 215 free(device); 216 return ENOMEM; 217 } 218 219 void *port; 220 int rc = pio_enable((void *) io, NE2K_IO_SIZE, &port); 221 if (rc != EOK) { 222 free(ne2k); 223 free(device); 224 return rc; 225 } 226 227 bzero(device, sizeof(netif_device_t)); 228 bzero(ne2k, sizeof(ne2k_t)); 229 230 device->device_id = device_id; 231 device->nil_phone = -1; 232 device->specific = (void *) ne2k; 233 device->state = NETIF_STOPPED; 234 235 rc = ne2k_probe(ne2k, port, irq); 236 if (rc != EOK) { 237 printf("%s: No ethernet card found at I/O address %p\n", 238 NAME, port); 239 free(ne2k); 240 free(device); 241 return rc; 242 } 243 244 rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device); 245 if (rc != EOK) { 246 free(ne2k); 247 free(device); 248 return rc; 249 } 250 251 printf("%s: Ethernet card at I/O address %p, IRQ %d, MAC ", 252 NAME, port, irq); 253 254 unsigned int i; 255 for (i = 0; i < ETH_ADDR; i++) 256 printf("%02x%c", ne2k->mac[i], i < 5 ? ':' : '\n'); 257 258 return EOK; 259 } 260 261 int netif_start_message(netif_device_t *device) 262 { 263 if (device->state != NETIF_ACTIVE) { 264 ne2k_t *ne2k = (ne2k_t *) device->specific; 265 266 ne2k_cmds[0].addr = ne2k->port + DP_ISR; 267 ne2k_cmds[3].addr = ne2k_cmds[0].addr; 268 269 int rc = ipc_register_irq(ne2k->irq, device->device_id, 270 device->device_id, &ne2k_code); 271 if (rc != EOK) 272 return rc; 273 274 rc = ne2k_up(ne2k); 275 if (rc != EOK) { 276 ipc_unregister_irq(ne2k->irq, device->device_id); 277 return rc; 278 } 279 280 if (irc_service) 281 async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq); 282 283 change_state(device, NETIF_ACTIVE); 284 } 285 286 return device->state; 287 } 288 289 int netif_stop_message(netif_device_t *device) 290 { 291 if (device->state != NETIF_STOPPED) { 292 ne2k_t *ne2k = (ne2k_t *) device->specific; 293 294 ne2k_down(ne2k); 295 ipc_unregister_irq(ne2k->irq, device->device_id); 296 change_state(device, NETIF_STOPPED); 297 } 298 299 return EOK; 300 } 301 302 int netif_send_message(device_id_t device_id, packet_t *packet, 303 services_t sender) 304 { 305 netif_device_t *device; 306 int rc = find_device(device_id, &device); 307 if (rc != EOK) 308 return rc; 309 310 if (device->state != NETIF_ACTIVE) { 311 netif_pq_release(packet_get_id(packet)); 312 return EFORWARD; 313 } 314 315 ne2k_t *ne2k = (ne2k_t *) device->specific; 91 316 92 317 /* 93 * We probe for an ne1000 or an ne2000 by testing whether the 94 * on board is reachable through the dp8390. Note that the 95 * ne1000 is an 8bit card and has a memory region distict from 96 * the 16bit ne2000 318 * Process the packet queue 97 319 */ 98 320 99 for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) { 100 /* Reset the ethernet card */ 101 byte= inb_ne(dep, NE_RESET); 102 usleep(2000); 103 outb_ne(dep, NE_RESET, byte); 104 usleep(2000); 105 106 /* Reset the dp8390 */ 107 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++) 109 ; /* Do nothing */ 110 111 /* 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)) 114 return 0; 115 116 /* Disable the receiver and init TCR and DCR. */ 117 outb_reg0(dep, DP_RCR, RCR_MON); 118 outb_reg0(dep, DP_TCR, TCR_NORMAL); 119 if (dep->de_16bit) { 120 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | 121 DCR_BMS); 122 } else { 123 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | 124 DCR_BMS); 321 do { 322 packet_t *next = pq_detach(packet); 323 ne2k_send(ne2k, packet); 324 netif_pq_release(packet_get_id(packet)); 325 packet = next; 326 } while (packet); 327 328 return EOK; 329 } 330 331 int netif_initialize(void) 332 { 333 sysarg_t apic; 334 sysarg_t i8259; 335 336 if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) 337 irc_service = SERVICE_APIC; 338 else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) 339 irc_service = SERVICE_I8259; 340 341 if (irc_service) { 342 while (irc_phone < 0) { 343 irc_phone = ipc_connect_me_to_blocking(PHONE_NS, irc_service, 344 0, 0); 125 345 } 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)) { 141 return 1; 142 } 143 } 144 145 return 0; 146 } 147 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) 154 { 155 int i; 156 int word, sendq_nr; 157 158 /* Setup a transfer to get the ethernet address. */ 159 if (dep->de_16bit) 160 outb_reg0(dep, DP_RBCR0, 6*2); 161 else 162 outb_reg0(dep, DP_RBCR0, 6); 163 164 outb_reg0(dep, DP_RBCR1, 0); 165 outb_reg0(dep, DP_RSAR0, 0); 166 outb_reg0(dep, DP_RSAR1, 0); 167 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 174 dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA); 175 } 176 177 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 186 /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */ 187 sendq_nr = dep->de_ramsize / 0x2000; 188 189 if (sendq_nr < 1) 190 sendq_nr = 1; 191 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]; 210 int i; 211 212 outb_reg0(dep, DP_ISR, 0xff); 213 214 /* Setup a transfer to put the pattern. */ 215 outb_reg0(dep, DP_RBCR0, 4); 216 outb_reg0(dep, DP_RBCR1, 0); 217 outb_reg0(dep, DP_RSAR0, pos & 0xff); 218 outb_reg0(dep, DP_RSAR1, pos >> 8); 219 outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA); 220 221 for (i = 0; i < 4; i++) 222 outb_ne(dep, NE_DATA, pat[i]); 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 (bcmp(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++) { 264 if (inb_reg0(dep, DP_ISR) &ISR_RDC) 265 break; 266 } 267 268 if (i == N) { 269 printf("NE2000 remote DMA test failed\n"); 270 return 0; 271 } 272 273 outb_reg0(dep, DP_RBCR0, 4); 274 outb_reg0(dep, DP_RBCR1, 0); 275 outb_reg0(dep, DP_RSAR0, pos & 0xff); 276 outb_reg0(dep, DP_RSAR1, pos >> 8); 277 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 (bcmp(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 { 292 /* Reset the ethernet card */ 293 int byte = inb_ne(dep, NE_RESET); 294 usleep(2000); 295 outb_ne(dep, NE_RESET, byte); 346 } 347 348 async_set_interrupt_received(irq_handler); 349 350 sysarg_t phonehash; 351 return ipc_connect_to_me(PHONE_NS, SERVICE_DP8390, 0, 0, &phonehash); 352 } 353 354 int main(int argc, char *argv[]) 355 { 356 /* Start the module */ 357 return netif_module_start(); 296 358 } 297 359
Note:
See TracChangeset
for help on using the changeset viewer.