Commit f1510b2cc3529b1bf26107c3d3890a4efb793afe

Authored by bellard
1 parent 357a9432

added NE2000 emulation


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@269 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 529 additions and 5 deletions
... ... @@ -21,11 +21,19 @@
21 21 #include <termios.h>
22 22 #include <sys/poll.h>
23 23 #include <errno.h>
  24 +#include <sys/wait.h>
  25 +
  26 +#include <sys/ioctl.h>
  27 +#include <sys/socket.h>
  28 +#include <linux/if.h>
  29 +#include <linux/if_tun.h>
24 30  
25 31 #include "cpu-i386.h"
26 32 #include "disas.h"
27 33  
28 34 #define DEBUG_LOGFILE "/tmp/vl.log"
  35 +#define DEFAULT_NETWORK_SCRIPT "/etc/vl-ifup"
  36 +
29 37 //#define DEBUG_UNUSED_IOPORT
30 38  
31 39 #define PHYS_RAM_BASE 0xa8000000
... ... @@ -225,6 +233,24 @@ int register_ioport_writeb(int start, int length, IOPortWriteFunc *func)
225 233 return 0;
226 234 }
227 235  
  236 +int register_ioport_readw(int start, int length, IOPortReadFunc *func)
  237 +{
  238 + int i;
  239 +
  240 + for(i = start; i < start + length; i += 2)
  241 + ioport_readw_table[i] = func;
  242 + return 0;
  243 +}
  244 +
  245 +int register_ioport_writew(int start, int length, IOPortWriteFunc *func)
  246 +{
  247 + int i;
  248 +
  249 + for(i = start; i < start + length; i += 2)
  250 + ioport_writew_table[i] = func;
  251 + return 0;
  252 +}
  253 +
228 254 void pstrcpy(char *buf, int buf_size, const char *str)
229 255 {
230 256 int c;
... ... @@ -1149,6 +1175,474 @@ void serial_init(void)
1149 1175 term_init();
1150 1176 }
1151 1177  
  1178 +/***********************************************************/
  1179 +/* ne2000 emulation */
  1180 +
  1181 +//#define DEBUG_NE2000
  1182 +
  1183 +#define NE2000_IOPORT 0x300
  1184 +#define NE2000_IRQ 9
  1185 +
  1186 +#define MAX_ETH_FRAME_SIZE 1514
  1187 +
  1188 +#define E8390_CMD 0x00 /* The command register (for all pages) */
  1189 +/* Page 0 register offsets. */
  1190 +#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
  1191 +#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
  1192 +#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
  1193 +#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
  1194 +#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
  1195 +#define EN0_TSR 0x04 /* Transmit status reg RD */
  1196 +#define EN0_TPSR 0x04 /* Transmit starting page WR */
  1197 +#define EN0_NCR 0x05 /* Number of collision reg RD */
  1198 +#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
  1199 +#define EN0_FIFO 0x06 /* FIFO RD */
  1200 +#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
  1201 +#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
  1202 +#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
  1203 +#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
  1204 +#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
  1205 +#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
  1206 +#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
  1207 +#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
  1208 +#define EN0_RSR 0x0c /* rx status reg RD */
  1209 +#define EN0_RXCR 0x0c /* RX configuration reg WR */
  1210 +#define EN0_TXCR 0x0d /* TX configuration reg WR */
  1211 +#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
  1212 +#define EN0_DCFG 0x0e /* Data configuration reg WR */
  1213 +#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
  1214 +#define EN0_IMR 0x0f /* Interrupt mask reg WR */
  1215 +#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
  1216 +
  1217 +#define EN1_PHYS 0x11
  1218 +#define EN1_CURPAG 0x17
  1219 +#define EN1_MULT 0x18
  1220 +
  1221 +/* Register accessed at EN_CMD, the 8390 base addr. */
  1222 +#define E8390_STOP 0x01 /* Stop and reset the chip */
  1223 +#define E8390_START 0x02 /* Start the chip, clear reset */
  1224 +#define E8390_TRANS 0x04 /* Transmit a frame */
  1225 +#define E8390_RREAD 0x08 /* Remote read */
  1226 +#define E8390_RWRITE 0x10 /* Remote write */
  1227 +#define E8390_NODMA 0x20 /* Remote DMA */
  1228 +#define E8390_PAGE0 0x00 /* Select page chip registers */
  1229 +#define E8390_PAGE1 0x40 /* using the two high-order bits */
  1230 +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
  1231 +
  1232 +/* Bits in EN0_ISR - Interrupt status register */
  1233 +#define ENISR_RX 0x01 /* Receiver, no error */
  1234 +#define ENISR_TX 0x02 /* Transmitter, no error */
  1235 +#define ENISR_RX_ERR 0x04 /* Receiver, with error */
  1236 +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
  1237 +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
  1238 +#define ENISR_COUNTERS 0x20 /* Counters need emptying */
  1239 +#define ENISR_RDC 0x40 /* remote dma complete */
  1240 +#define ENISR_RESET 0x80 /* Reset completed */
  1241 +#define ENISR_ALL 0x3f /* Interrupts we will enable */
  1242 +
  1243 +/* Bits in received packet status byte and EN0_RSR*/
  1244 +#define ENRSR_RXOK 0x01 /* Received a good packet */
  1245 +#define ENRSR_CRC 0x02 /* CRC error */
  1246 +#define ENRSR_FAE 0x04 /* frame alignment error */
  1247 +#define ENRSR_FO 0x08 /* FIFO overrun */
  1248 +#define ENRSR_MPA 0x10 /* missed pkt */
  1249 +#define ENRSR_PHY 0x20 /* physical/multicast address */
  1250 +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
  1251 +#define ENRSR_DEF 0x80 /* deferring */
  1252 +
  1253 +/* Transmitted packet status, EN0_TSR. */
  1254 +#define ENTSR_PTX 0x01 /* Packet transmitted without error */
  1255 +#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
  1256 +#define ENTSR_COL 0x04 /* The transmit collided at least once. */
  1257 +#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
  1258 +#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
  1259 +#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
  1260 +#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
  1261 +#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
  1262 +
  1263 +#define NE2000_MEM_SIZE 32768
  1264 +
  1265 +typedef struct NE2000State {
  1266 + uint8_t cmd;
  1267 + uint32_t start;
  1268 + uint32_t stop;
  1269 + uint8_t boundary;
  1270 + uint8_t tsr;
  1271 + uint8_t tpsr;
  1272 + uint16_t tcnt;
  1273 + uint16_t rcnt;
  1274 + uint32_t rsar;
  1275 + uint8_t isr;
  1276 + uint8_t dcfg;
  1277 + uint8_t imr;
  1278 + uint8_t phys[6]; /* mac address */
  1279 + uint8_t curpag;
  1280 + uint8_t mult[8]; /* multicast mask array */
  1281 + uint8_t mem[NE2000_MEM_SIZE];
  1282 +} NE2000State;
  1283 +
  1284 +NE2000State ne2000_state;
  1285 +int net_fd = -1;
  1286 +char network_script[1024];
  1287 +
  1288 +void ne2000_reset(void)
  1289 +{
  1290 + NE2000State *s = &ne2000_state;
  1291 + int i;
  1292 +
  1293 + s->isr = ENISR_RESET;
  1294 + s->mem[0] = 0x52;
  1295 + s->mem[1] = 0x54;
  1296 + s->mem[2] = 0x00;
  1297 + s->mem[3] = 0x12;
  1298 + s->mem[4] = 0x34;
  1299 + s->mem[5] = 0x56;
  1300 + s->mem[14] = 0x57;
  1301 + s->mem[15] = 0x57;
  1302 +
  1303 + /* duplicate prom data */
  1304 + for(i = 15;i >= 0; i--) {
  1305 + s->mem[2 * i] = s->mem[i];
  1306 + s->mem[2 * i + 1] = s->mem[i];
  1307 + }
  1308 +}
  1309 +
  1310 +void ne2000_update_irq(NE2000State *s)
  1311 +{
  1312 + int isr;
  1313 + isr = s->isr & s->imr;
  1314 + if (isr)
  1315 + pic_set_irq(NE2000_IRQ, 1);
  1316 + else
  1317 + pic_set_irq(NE2000_IRQ, 0);
  1318 +}
  1319 +
  1320 +int net_init(void)
  1321 +{
  1322 + struct ifreq ifr;
  1323 + int fd, ret, pid, status;
  1324 +
  1325 + fd = open("/dev/net/tun", O_RDWR);
  1326 + if (fd < 0) {
  1327 + fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
  1328 + return -1;
  1329 + }
  1330 + memset(&ifr, 0, sizeof(ifr));
  1331 + ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  1332 + pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d");
  1333 + ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
  1334 + if (ret != 0) {
  1335 + fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n");
  1336 + close(fd);
  1337 + return -1;
  1338 + }
  1339 + printf("connected to host network interface: %s\n", ifr.ifr_name);
  1340 + fcntl(fd, F_SETFL, O_NONBLOCK);
  1341 + net_fd = fd;
  1342 +
  1343 + /* try to launch network init script */
  1344 + pid = fork();
  1345 + if (pid >= 0) {
  1346 + if (pid == 0) {
  1347 + execl(network_script, network_script, ifr.ifr_name, NULL);
  1348 + exit(1);
  1349 + }
  1350 + while (waitpid(pid, &status, 0) != pid);
  1351 + if (!WIFEXITED(status) ||
  1352 + WEXITSTATUS(status) != 0) {
  1353 + fprintf(stderr, "%s: could not launch network script for '%s'\n",
  1354 + network_script, ifr.ifr_name);
  1355 + }
  1356 + }
  1357 + return 0;
  1358 +}
  1359 +
  1360 +void net_send_packet(NE2000State *s, const uint8_t *buf, int size)
  1361 +{
  1362 +#ifdef DEBUG_NE2000
  1363 + printf("NE2000: sending packet size=%d\n", size);
  1364 +#endif
  1365 + write(net_fd, buf, size);
  1366 +}
  1367 +
  1368 +/* return true if the NE2000 can receive more data */
  1369 +int ne2000_can_receive(NE2000State *s)
  1370 +{
  1371 + int avail, index, boundary;
  1372 +
  1373 + if (s->cmd & E8390_STOP)
  1374 + return 0;
  1375 + index = s->curpag << 8;
  1376 + boundary = s->boundary << 8;
  1377 + if (index < boundary)
  1378 + avail = boundary - index;
  1379 + else
  1380 + avail = (s->stop - s->start) - (index - boundary);
  1381 + if (avail < (MAX_ETH_FRAME_SIZE + 4))
  1382 + return 0;
  1383 + return 1;
  1384 +}
  1385 +
  1386 +void ne2000_receive(NE2000State *s, uint8_t *buf, int size)
  1387 +{
  1388 + uint8_t *p;
  1389 + int total_len, next, avail, len, index;
  1390 +
  1391 +#if defined(DEBUG_NE2000)
  1392 + printf("NE2000: received len=%d\n", size);
  1393 +#endif
  1394 +
  1395 + index = s->curpag << 8;
  1396 + /* 4 bytes for header */
  1397 + total_len = size + 4;
  1398 + /* address for next packet (4 bytes for CRC) */
  1399 + next = index + ((total_len + 4 + 255) & ~0xff);
  1400 + if (next >= s->stop)
  1401 + next -= (s->stop - s->start);
  1402 + /* prepare packet header */
  1403 + p = s->mem + index;
  1404 + p[0] = ENRSR_RXOK; /* receive status */
  1405 + p[1] = next >> 8;
  1406 + p[2] = total_len;
  1407 + p[3] = total_len >> 8;
  1408 + index += 4;
  1409 +
  1410 + /* write packet data */
  1411 + while (size > 0) {
  1412 + avail = s->stop - index;
  1413 + len = size;
  1414 + if (len > avail)
  1415 + len = avail;
  1416 + memcpy(s->mem + index, buf, len);
  1417 + buf += len;
  1418 + index += len;
  1419 + if (index == s->stop)
  1420 + index = s->start;
  1421 + size -= len;
  1422 + }
  1423 + s->curpag = next >> 8;
  1424 +
  1425 + /* now we can signal we have receive something */
  1426 + s->isr |= ENISR_RX;
  1427 + ne2000_update_irq(s);
  1428 +}
  1429 +
  1430 +void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
  1431 +{
  1432 + NE2000State *s = &ne2000_state;
  1433 + int offset, page;
  1434 +
  1435 + addr &= 0xf;
  1436 +#ifdef DEBUG_NE2000
  1437 + printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
  1438 +#endif
  1439 + if (addr == E8390_CMD) {
  1440 + /* control register */
  1441 + s->cmd = val;
  1442 + if (val & E8390_START) {
  1443 + /* test specific case: zero length transfert */
  1444 + if ((val & (E8390_RREAD | E8390_RWRITE)) &&
  1445 + s->rcnt == 0) {
  1446 + s->isr |= ENISR_RDC;
  1447 + ne2000_update_irq(s);
  1448 + }
  1449 + if (val & E8390_TRANS) {
  1450 + net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);
  1451 + /* signal end of transfert */
  1452 + s->tsr = ENTSR_PTX;
  1453 + s->isr |= ENISR_TX;
  1454 + ne2000_update_irq(s);
  1455 + }
  1456 + }
  1457 + } else {
  1458 + page = s->cmd >> 6;
  1459 + offset = addr | (page << 4);
  1460 + switch(offset) {
  1461 + case EN0_STARTPG:
  1462 + s->start = val << 8;
  1463 + break;
  1464 + case EN0_STOPPG:
  1465 + s->stop = val << 8;
  1466 + break;
  1467 + case EN0_BOUNDARY:
  1468 + s->boundary = val;
  1469 + break;
  1470 + case EN0_IMR:
  1471 + s->imr = val;
  1472 + ne2000_update_irq(s);
  1473 + break;
  1474 + case EN0_TPSR:
  1475 + s->tpsr = val;
  1476 + break;
  1477 + case EN0_TCNTLO:
  1478 + s->tcnt = (s->tcnt & 0xff00) | val;
  1479 + break;
  1480 + case EN0_TCNTHI:
  1481 + s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
  1482 + break;
  1483 + case EN0_RSARLO:
  1484 + s->rsar = (s->rsar & 0xff00) | val;
  1485 + break;
  1486 + case EN0_RSARHI:
  1487 + s->rsar = (s->rsar & 0x00ff) | (val << 8);
  1488 + break;
  1489 + case EN0_RCNTLO:
  1490 + s->rcnt = (s->rcnt & 0xff00) | val;
  1491 + break;
  1492 + case EN0_RCNTHI:
  1493 + s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
  1494 + break;
  1495 + case EN0_DCFG:
  1496 + s->dcfg = val;
  1497 + break;
  1498 + case EN0_ISR:
  1499 + s->isr &= ~val;
  1500 + ne2000_update_irq(s);
  1501 + break;
  1502 + case EN1_PHYS ... EN1_PHYS + 5:
  1503 + s->phys[offset - EN1_PHYS] = val;
  1504 + break;
  1505 + case EN1_CURPAG:
  1506 + s->curpag = val;
  1507 + break;
  1508 + case EN1_MULT ... EN1_MULT + 7:
  1509 + s->mult[offset - EN1_MULT] = val;
  1510 + break;
  1511 + }
  1512 + }
  1513 +}
  1514 +
  1515 +uint32_t ne2000_ioport_read(CPUX86State *env, uint32_t addr)
  1516 +{
  1517 + NE2000State *s = &ne2000_state;
  1518 + int offset, page, ret;
  1519 +
  1520 + addr &= 0xf;
  1521 + if (addr == E8390_CMD) {
  1522 + ret = s->cmd;
  1523 + } else {
  1524 + page = s->cmd >> 6;
  1525 + offset = addr | (page << 4);
  1526 + switch(offset) {
  1527 + case EN0_TSR:
  1528 + ret = s->tsr;
  1529 + break;
  1530 + case EN0_BOUNDARY:
  1531 + ret = s->boundary;
  1532 + break;
  1533 + case EN0_ISR:
  1534 + ret = s->isr;
  1535 + break;
  1536 + case EN1_PHYS ... EN1_PHYS + 5:
  1537 + ret = s->phys[offset - EN1_PHYS];
  1538 + break;
  1539 + case EN1_CURPAG:
  1540 + ret = s->curpag;
  1541 + break;
  1542 + case EN1_MULT ... EN1_MULT + 7:
  1543 + ret = s->mult[offset - EN1_MULT];
  1544 + break;
  1545 + default:
  1546 + ret = 0x00;
  1547 + break;
  1548 + }
  1549 + }
  1550 +#ifdef DEBUG_NE2000
  1551 + printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
  1552 +#endif
  1553 + return ret;
  1554 +}
  1555 +
  1556 +void ne2000_asic_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
  1557 +{
  1558 + NE2000State *s = &ne2000_state;
  1559 + uint8_t *p;
  1560 +
  1561 +#ifdef DEBUG_NE2000
  1562 + printf("NE2000: asic write val=0x%04x\n", val);
  1563 +#endif
  1564 + p = s->mem + s->rsar;
  1565 + if (s->dcfg & 0x01) {
  1566 + /* 16 bit access */
  1567 + p[0] = val;
  1568 + p[1] = val >> 8;
  1569 + s->rsar += 2;
  1570 + s->rcnt -= 2;
  1571 + } else {
  1572 + /* 8 bit access */
  1573 + p[0] = val;
  1574 + s->rsar++;
  1575 + s->rcnt--;
  1576 + }
  1577 + /* wrap */
  1578 + if (s->rsar == s->stop)
  1579 + s->rsar = s->start;
  1580 + if (s->rcnt == 0) {
  1581 + /* signal end of transfert */
  1582 + s->isr |= ENISR_RDC;
  1583 + ne2000_update_irq(s);
  1584 + }
  1585 +}
  1586 +
  1587 +uint32_t ne2000_asic_ioport_read(CPUX86State *env, uint32_t addr)
  1588 +{
  1589 + NE2000State *s = &ne2000_state;
  1590 + uint8_t *p;
  1591 + int ret;
  1592 +
  1593 + p = s->mem + s->rsar;
  1594 + if (s->dcfg & 0x01) {
  1595 + /* 16 bit access */
  1596 + ret = p[0] | (p[1] << 8);
  1597 + s->rsar += 2;
  1598 + s->rcnt -= 2;
  1599 + } else {
  1600 + /* 8 bit access */
  1601 + ret = p[0];
  1602 + s->rsar++;
  1603 + s->rcnt--;
  1604 + }
  1605 + /* wrap */
  1606 + if (s->rsar == s->stop)
  1607 + s->rsar = s->start;
  1608 + if (s->rcnt == 0) {
  1609 + /* signal end of transfert */
  1610 + s->isr |= ENISR_RDC;
  1611 + ne2000_update_irq(s);
  1612 + }
  1613 +#ifdef DEBUG_NE2000
  1614 + printf("NE2000: asic read val=0x%04x\n", ret);
  1615 +#endif
  1616 + return ret;
  1617 +}
  1618 +
  1619 +void ne2000_reset_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
  1620 +{
  1621 + /* nothing to do (end of reset pulse) */
  1622 +}
  1623 +
  1624 +uint32_t ne2000_reset_ioport_read(CPUX86State *env, uint32_t addr)
  1625 +{
  1626 + ne2000_reset();
  1627 + return 0;
  1628 +}
  1629 +
  1630 +void ne2000_init(void)
  1631 +{
  1632 + register_ioport_writeb(NE2000_IOPORT, 16, ne2000_ioport_write);
  1633 + register_ioport_readb(NE2000_IOPORT, 16, ne2000_ioport_read);
  1634 +
  1635 + register_ioport_writeb(NE2000_IOPORT + 0x10, 1, ne2000_asic_ioport_write);
  1636 + register_ioport_readb(NE2000_IOPORT + 0x10, 1, ne2000_asic_ioport_read);
  1637 + register_ioport_writew(NE2000_IOPORT + 0x10, 2, ne2000_asic_ioport_write);
  1638 + register_ioport_readw(NE2000_IOPORT + 0x10, 2, ne2000_asic_ioport_read);
  1639 +
  1640 + register_ioport_writeb(NE2000_IOPORT + 0x1f, 1, ne2000_reset_ioport_write);
  1641 + register_ioport_readb(NE2000_IOPORT + 0x1f, 1, ne2000_reset_ioport_read);
  1642 + ne2000_reset();
  1643 +}
  1644 +
  1645 +/***********************************************************/
1152 1646 /* cpu signal handler */
1153 1647 static void host_segv_handler(int host_signum, siginfo_t *info,
1154 1648 void *puc)
... ... @@ -1178,10 +1672,11 @@ void help(void)
1178 1672 "to 0x90000000 in asm/page.h and arch/i386/vmlinux.lds)\n"
1179 1673 "'initrd' is an initrd image\n"
1180 1674 "-m megs set virtual RAM size to megs MB\n"
  1675 + "-n script set network init script [default=%s]\n"
1181 1676 "-d output log in /tmp/vl.log\n"
1182 1677 "\n"
1183   - "During emulation, use C-a h to get terminal commands:\n"
1184   - );
  1678 + "During emulation, use C-a h to get terminal commands:\n",
  1679 + DEFAULT_NETWORK_SCRIPT);
1185 1680 term_print_help();
1186 1681 exit(1);
1187 1682 }
... ... @@ -1198,8 +1693,9 @@ int main(int argc, char **argv)
1198 1693 mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
1199 1694  
1200 1695 phys_ram_size = 32 * 1024 * 1024;
  1696 + pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
1201 1697 for(;;) {
1202   - c = getopt(argc, argv, "hm:d");
  1698 + c = getopt(argc, argv, "hm:dn:");
1203 1699 if (c == -1)
1204 1700 break;
1205 1701 switch(c) {
... ... @@ -1214,6 +1710,9 @@ int main(int argc, char **argv)
1214 1710 case 'd':
1215 1711 loglevel = 1;
1216 1712 break;
  1713 + case 'n':
  1714 + pstrcpy(network_script, sizeof(network_script), optarg);
  1715 + break;
1217 1716 }
1218 1717 }
1219 1718 if (optind + 1 >= argc)
... ... @@ -1229,6 +1728,9 @@ int main(int argc, char **argv)
1229 1728 setvbuf(logfile, NULL, _IOLBF, 0);
1230 1729 }
1231 1730  
  1731 + /* init network tun interface */
  1732 + net_init();
  1733 +
1232 1734 /* init the memory */
1233 1735 strcpy(phys_ram_file, "/tmp/vlXXXXXX");
1234 1736 if (mkstemp(phys_ram_file) < 0) {
... ... @@ -1294,6 +1796,7 @@ int main(int argc, char **argv)
1294 1796 pic_init();
1295 1797 pit_init();
1296 1798 serial_init();
  1799 + ne2000_init();
1297 1800  
1298 1801 /* setup cpu signal handlers for MMU / self modifying code handling */
1299 1802 sigfillset(&act.sa_mask);
... ... @@ -1341,7 +1844,7 @@ int main(int argc, char **argv)
1341 1844 setitimer(ITIMER_REAL, &itv, NULL);
1342 1845  
1343 1846 for(;;) {
1344   - struct pollfd ufds[1], *pf;
  1847 + struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd;
1345 1848 int ret, n, timeout;
1346 1849 uint8_t ch;
1347 1850  
... ... @@ -1353,20 +1856,41 @@ int main(int argc, char **argv)
1353 1856 else
1354 1857 timeout = 0;
1355 1858 /* poll any events */
  1859 + serial_ufd = NULL;
  1860 + net_ufd = NULL;
1356 1861 pf = ufds;
1357 1862 if (!(serial_ports[0].lsr & UART_LSR_DR)) {
  1863 + serial_ufd = pf;
1358 1864 pf->fd = 0;
1359 1865 pf->events = POLLIN;
1360 1866 pf++;
1361 1867 }
  1868 + if (net_fd > 0 && ne2000_can_receive(&ne2000_state)) {
  1869 + net_ufd = pf;
  1870 + pf->fd = net_fd;
  1871 + pf->events = POLLIN;
  1872 + pf++;
  1873 + }
1362 1874 ret = poll(ufds, pf - ufds, timeout);
1363 1875 if (ret > 0) {
1364   - if (ufds[0].revents & POLLIN) {
  1876 + if (serial_ufd && (serial_ufd->revents & POLLIN)) {
1365 1877 n = read(0, &ch, 1);
1366 1878 if (n == 1) {
1367 1879 serial_received_byte(&serial_ports[0], ch);
1368 1880 }
1369 1881 }
  1882 + if (net_ufd && (net_ufd->revents & POLLIN)) {
  1883 + uint8_t buf[MAX_ETH_FRAME_SIZE];
  1884 +
  1885 + n = read(net_fd, buf, MAX_ETH_FRAME_SIZE);
  1886 + if (n > 0) {
  1887 + if (n < 60) {
  1888 + memset(buf + n, 0, 60 - n);
  1889 + n = 60;
  1890 + }
  1891 + ne2000_receive(&ne2000_state, buf, n);
  1892 + }
  1893 + }
1370 1894 }
1371 1895  
1372 1896 /* just for testing */
... ...