etherec2t.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c
  3. */
  4. #include "u.h"
  5. #include "lib.h"
  6. #include "mem.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "io.h"
  10. #include "etherif.h"
  11. #include "ether8390.h"
  12. enum {
  13. Data = 0x10, /* offset from I/O base of data port */
  14. Reset = 0x1F, /* offset from I/O base of reset port */
  15. };
  16. static char* ec2tpcmcia[] = {
  17. "EC2T", /* Linksys Combo PCMCIA EthernetCard */
  18. "PCMPC100", /* EtherFast 10/100 PC Card */
  19. "EN2216", /* Accton EtherPair-PCMCIA */
  20. "FA410TX", /* Netgear FA410TX */
  21. "Network Everywhere", /* Linksys NP10T 10BaseT Card */
  22. nil,
  23. };
  24. int
  25. ec2treset(Ether* ether)
  26. {
  27. ushort buf[16];
  28. ulong port;
  29. Dp8390 *ctlr;
  30. int i, slot;
  31. uchar ea[Eaddrlen], sum, x;
  32. char *type;
  33. /*
  34. * Set up the software configuration.
  35. * Use defaults for port, irq, mem and size
  36. * if not specified.
  37. * The manual says 16KB memory, the box
  38. * says 32KB. The manual seems to be correct.
  39. */
  40. if(ether->port == 0)
  41. ether->port = 0x300;
  42. if(ether->irq == 0)
  43. ether->irq = 9;
  44. if(ether->mem == 0)
  45. ether->mem = 0x4000;
  46. if(ether->size == 0)
  47. ether->size = 16*1024;
  48. port = ether->port;
  49. //if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0)
  50. // return -1;
  51. slot = -1;
  52. type = nil;
  53. for(i = 0; ec2tpcmcia[i] != nil; i++){
  54. type = ec2tpcmcia[i];
  55. if((slot = pcmspecial(type, ether)) >= 0)
  56. break;
  57. }
  58. if(ec2tpcmcia[i] == nil){
  59. for(i = 0; i < ether->nopt; i++){
  60. if(cistrncmp(ether->opt[i], "id=", 3))
  61. continue;
  62. type = &ether->opt[i][3];
  63. if((slot = pcmspecial(type, ether)) >= 0)
  64. break;
  65. }
  66. }
  67. if(slot < 0){
  68. // iofree(port);
  69. return -1;
  70. }
  71. ether->ctlr = malloc(sizeof(Dp8390));
  72. ctlr = ether->ctlr;
  73. ctlr->width = 2;
  74. ctlr->ram = 0;
  75. ctlr->port = port;
  76. ctlr->data = port+Data;
  77. ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz);
  78. ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
  79. ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz);
  80. ctlr->dummyrr = 0;
  81. for(i = 0; i < ether->nopt; i++){
  82. if(cistrcmp(ether->opt[i], "nodummyrr") == 0)
  83. ctlr->dummyrr = 0;
  84. else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0)
  85. ctlr->dummyrr = strtol(&ether->opt[i][8], nil, 0);
  86. }
  87. /*
  88. * Reset the board. This is done by doing a read
  89. * followed by a write to the Reset address.
  90. */
  91. buf[0] = inb(port+Reset);
  92. delay(2);
  93. outb(port+Reset, buf[0]);
  94. delay(2);
  95. /*
  96. * Init the (possible) chip, then use the (possible)
  97. * chip to read the (possible) PROM for ethernet address
  98. * and a marker byte.
  99. * Could just look at the DP8390 command register after
  100. * initialisation has been tried, but that wouldn't be
  101. * enough, there are other ethernet boards which could
  102. * match.
  103. */
  104. dp8390reset(ether);
  105. sum = 0;
  106. if(cistrcmp(type, "PCMPC100") == 0 || cistrcmp(type, "FA410TX") == 0){
  107. /*
  108. * The PCMPC100 has the ethernet address in I/O space.
  109. * There's a checksum over 8 bytes which sums to 0xFF.
  110. */
  111. for(i = 0; i < 8; i++){
  112. x = inb(port+0x14+i);
  113. sum += x;
  114. buf[i] = (x<<8)|x;
  115. }
  116. }
  117. else{
  118. memset(buf, 0, sizeof(buf));
  119. dp8390read(ctlr, buf, 0, sizeof(buf));
  120. if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
  121. sum = 0xFF;
  122. }
  123. if(sum != 0xFF){
  124. pcmspecialclose(slot);
  125. //iofree(ether->port);
  126. free(ether->ctlr);
  127. return -1;
  128. }
  129. /*
  130. * Stupid machine. Shorts were asked for,
  131. * shorts were delivered, although the PROM is a byte array.
  132. * Set the ethernet address.
  133. */
  134. memset(ea, 0, Eaddrlen);
  135. if(memcmp(ea, ether->ea, Eaddrlen) == 0){
  136. for(i = 0; i < sizeof(ether->ea); i++)
  137. ether->ea[i] = buf[i];
  138. }
  139. dp8390setea(ether);
  140. return 0;
  141. }