00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00038 #include <assert.h>
00039 #include <async.h>
00040 #include <ddi.h>
00041 #include <errno.h>
00042 #include <err.h>
00043 #include <malloc.h>
00044 #include <sysinfo.h>
00045 #include <ipc/services.h>
00046 #include <ipc/ns.h>
00047 #include <ipc/irc.h>
00048 #include <net/modules.h>
00049 #include <packet_client.h>
00050 #include <adt/measured_strings.h>
00051 #include <net/device.h>
00052 #include <netif_skel.h>
00053 #include <nil_remote.h>
00054 #include "dp8390.h"
00055
00061 #define IRQ_GET_DEVICE(call) ((device_id_t) IPC_GET_IMETHOD(call))
00062
00068 #define IRQ_GET_ISR(call) ((int) IPC_GET_ARG2(call))
00069
00075 #define IRQ_GET_TSR(call) ((int) IPC_GET_ARG3(call))
00076
00077 static bool irc_service = false;
00078 static int irc_phone = -1;
00079
00083 static irq_cmd_t ne2k_cmds[] = {
00084 {
00085
00086 .cmd = CMD_PIO_READ_8,
00087 .addr = NULL,
00088 .dstarg = 2
00089 },
00090 {
00091
00092 .cmd = CMD_BTEST,
00093 .value = (ISR_PRX | ISR_PTX | ISR_RXE | ISR_TXE | ISR_OVW |
00094 ISR_CNT | ISR_RDC),
00095 .srcarg = 2,
00096 .dstarg = 3,
00097 },
00098 {
00099
00100 .cmd = CMD_PREDICATE,
00101 .value = 4,
00102 .srcarg = 3
00103 },
00104 {
00105
00106
00107
00108
00109 .cmd = CMD_PIO_WRITE_8,
00110 .addr = NULL,
00111 .value = 0
00112 },
00113 {
00114
00115 .cmd = CMD_PIO_WRITE_A_8,
00116 .addr = NULL,
00117 .srcarg = 3
00118 },
00119 {
00120
00121 .cmd = CMD_PIO_READ_8,
00122 .addr = NULL,
00123 .dstarg = 3
00124 },
00125 {
00126 .cmd = CMD_ACCEPT
00127 }
00128 };
00129
00133 static irq_code_t ne2k_code = {
00134 sizeof(ne2k_cmds) / sizeof(irq_cmd_t),
00135 ne2k_cmds
00136 };
00137
00150 static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
00151 {
00152 device_id_t device_id = IRQ_GET_DEVICE(*call);
00153 netif_device_t *device;
00154 int nil_phone;
00155 ne2k_t *ne2k;
00156
00157 fibril_rwlock_read_lock(&netif_globals.lock);
00158
00159 if (find_device(device_id, &device) == EOK) {
00160 nil_phone = device->nil_phone;
00161 ne2k = (ne2k_t *) device->specific;
00162 } else
00163 ne2k = NULL;
00164
00165 fibril_rwlock_read_unlock(&netif_globals.lock);
00166
00167 if (ne2k != NULL) {
00168 link_t *frames =
00169 ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), IRQ_GET_TSR(*call));
00170
00171 if (frames != NULL) {
00172 while (!list_empty(frames)) {
00173 frame_t *frame =
00174 list_get_instance(frames->next, frame_t, link);
00175
00176 list_remove(&frame->link);
00177 nil_received_msg(nil_phone, device_id, frame->packet,
00178 SERVICE_NONE);
00179 free(frame);
00180 }
00181
00182 free(frames);
00183 }
00184 }
00185 }
00186
00193 static void change_state(netif_device_t *device, device_state_t state)
00194 {
00195 if (device->state != state) {
00196 device->state = state;
00197
00198 const char *desc;
00199 switch (state) {
00200 case NETIF_ACTIVE:
00201 desc = "active";
00202 break;
00203 case NETIF_STOPPED:
00204 desc = "stopped";
00205 break;
00206 default:
00207 desc = "unknown";
00208 }
00209
00210 printf("%s: State changed to %s\n", NAME, desc);
00211 }
00212 }
00213
00214 int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
00215 ipc_call_t *answer, size_t *count)
00216 {
00217 return ENOTSUP;
00218 }
00219
00220 int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
00221 {
00222 if (!stats)
00223 return EBADMEM;
00224
00225 netif_device_t *device;
00226 int rc = find_device(device_id, &device);
00227 if (rc != EOK)
00228 return rc;
00229
00230 ne2k_t *ne2k = (ne2k_t *) device->specific;
00231
00232 memcpy(stats, &ne2k->stats, sizeof(device_stats_t));
00233 return EOK;
00234 }
00235
00236 int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
00237 {
00238 if (!address)
00239 return EBADMEM;
00240
00241 netif_device_t *device;
00242 int rc = find_device(device_id, &device);
00243 if (rc != EOK)
00244 return rc;
00245
00246 ne2k_t *ne2k = (ne2k_t *) device->specific;
00247
00248 address->value = ne2k->mac;
00249 address->length = ETH_ADDR;
00250 return EOK;
00251 }
00252
00253 int netif_probe_message(device_id_t device_id, int irq, void *io)
00254 {
00255 netif_device_t *device =
00256 (netif_device_t *) malloc(sizeof(netif_device_t));
00257 if (!device)
00258 return ENOMEM;
00259
00260 ne2k_t *ne2k = (ne2k_t *) malloc(sizeof(ne2k_t));
00261 if (!ne2k) {
00262 free(device);
00263 return ENOMEM;
00264 }
00265
00266 void *port;
00267 int rc = pio_enable((void *) io, NE2K_IO_SIZE, &port);
00268 if (rc != EOK) {
00269 free(ne2k);
00270 free(device);
00271 return rc;
00272 }
00273
00274 bzero(device, sizeof(netif_device_t));
00275 bzero(ne2k, sizeof(ne2k_t));
00276
00277 device->device_id = device_id;
00278 device->nil_phone = -1;
00279 device->specific = (void *) ne2k;
00280 device->state = NETIF_STOPPED;
00281
00282 rc = ne2k_probe(ne2k, port, irq);
00283 if (rc != EOK) {
00284 printf("%s: No ethernet card found at I/O address %p\n",
00285 NAME, port);
00286 free(ne2k);
00287 free(device);
00288 return rc;
00289 }
00290
00291 rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
00292 if (rc != EOK) {
00293 free(ne2k);
00294 free(device);
00295 return rc;
00296 }
00297
00298 printf("%s: Ethernet card at I/O address %p, IRQ %d, MAC ",
00299 NAME, port, irq);
00300
00301 unsigned int i;
00302 for (i = 0; i < ETH_ADDR; i++)
00303 printf("%02x%c", ne2k->mac[i], i < 5 ? ':' : '\n');
00304
00305 return EOK;
00306 }
00307
00308 int netif_start_message(netif_device_t *device)
00309 {
00310 if (device->state != NETIF_ACTIVE) {
00311 ne2k_t *ne2k = (ne2k_t *) device->specific;
00312
00313 ne2k_cmds[0].addr = ne2k->port + DP_ISR;
00314 ne2k_cmds[3].addr = ne2k->port + DP_IMR;
00315 ne2k_cmds[4].addr = ne2k_cmds[0].addr;
00316 ne2k_cmds[5].addr = ne2k->port + DP_TSR;
00317
00318 int rc = register_irq(ne2k->irq, device->device_id,
00319 device->device_id, &ne2k_code);
00320 if (rc != EOK)
00321 return rc;
00322
00323 rc = ne2k_up(ne2k);
00324 if (rc != EOK) {
00325 unregister_irq(ne2k->irq, device->device_id);
00326 return rc;
00327 }
00328
00329 change_state(device, NETIF_ACTIVE);
00330
00331 if (irc_service)
00332 async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
00333 }
00334
00335 return device->state;
00336 }
00337
00338 int netif_stop_message(netif_device_t *device)
00339 {
00340 if (device->state != NETIF_STOPPED) {
00341 ne2k_t *ne2k = (ne2k_t *) device->specific;
00342
00343 ne2k_down(ne2k);
00344 unregister_irq(ne2k->irq, device->device_id);
00345 change_state(device, NETIF_STOPPED);
00346 }
00347
00348 return device->state;
00349 }
00350
00351 int netif_send_message(device_id_t device_id, packet_t *packet,
00352 services_t sender)
00353 {
00354 netif_device_t *device;
00355 int rc = find_device(device_id, &device);
00356 if (rc != EOK)
00357 return rc;
00358
00359 if (device->state != NETIF_ACTIVE) {
00360 netif_pq_release(packet_get_id(packet));
00361 return EFORWARD;
00362 }
00363
00364 ne2k_t *ne2k = (ne2k_t *) device->specific;
00365
00366
00367
00368
00369
00370 do {
00371 packet_t *next = pq_detach(packet);
00372 ne2k_send(ne2k, packet);
00373 netif_pq_release(packet_get_id(packet));
00374 packet = next;
00375 } while (packet);
00376
00377 return EOK;
00378 }
00379
00380 int netif_initialize(void)
00381 {
00382 sysarg_t apic;
00383 sysarg_t i8259;
00384
00385 if (((sysinfo_get_value("apic", &apic) == EOK) && (apic))
00386 || ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)))
00387 irc_service = true;
00388
00389 if (irc_service) {
00390 while (irc_phone < 0)
00391 irc_phone = service_connect_blocking(SERVICE_IRC, 0, 0);
00392 }
00393
00394 async_set_interrupt_received(irq_handler);
00395
00396 return async_connect_to_me(PHONE_NS, SERVICE_NE2000, 0, 0, NULL);
00397 }
00398
00399 int main(int argc, char *argv[])
00400 {
00401
00402 return netif_module_start();
00403 }
00404