aoe.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // aoe.c: the ATA over Ethernet virtual EtherDrive (R) blade
  2. #include "config.h"
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <fcntl.h>
  9. #include <netinet/in.h>
  10. #include "dat.h"
  11. #include "fns.h"
  12. char cfg_str[1024];
  13. int cfg_str_len = 0;
  14. int
  15. qcget(uchar *p, int len)
  16. {
  17. if (len > cfg_str_len)
  18. len = cfg_str_len;
  19. memcpy(p, cfg_str, len);
  20. return len;
  21. }
  22. int
  23. qcset(uchar *p, int len)
  24. {
  25. if (len > sizeof(cfg_str))
  26. len = sizeof(cfg_str);
  27. memcpy(cfg_str, p, len);
  28. cfg_str_len = len;
  29. return len;
  30. }
  31. void
  32. aoead(int fd) // advertise the virtual blade
  33. {
  34. int len;
  35. uchar buf[2000];
  36. Conf *p;
  37. p = (Conf *)buf;
  38. memset(p, 0, sizeof *p);
  39. memset(p->h.dst, 0xff, 6);
  40. memmove(p->h.src, mac, 6);
  41. p->h.type = htons(0x88a2);
  42. p->h.flags = Resp;
  43. p->h.maj = htons(shelf);
  44. p->h.min = slot;
  45. p->h.cmd = Config;
  46. p->bufcnt = htons(Bufcount);
  47. p->firmware = htons(FWV);
  48. p->vercmd = 0x10 | Qread;
  49. len = qcget(p->data, 1024);
  50. p->len = htons(len);
  51. if (putpkt(fd, buf, sizeof *p - sizeof p->data + len) == -1)
  52. perror("putpkt aoe id");
  53. }
  54. int
  55. isbcast(uchar *ea) // replace with assembler routine
  56. {
  57. uchar *b = (uchar *)"\377\377\377\377\377\377";
  58. return memcmp(ea, b, 6) == 0;
  59. }
  60. long long
  61. getlba(uchar *p)
  62. {
  63. vlong v;
  64. int i;
  65. v = 0;
  66. for (i = 0; i < 6; i++)
  67. v |= (vlong)(*p++) << i * 8;
  68. return v;
  69. }
  70. int
  71. aoeata(Ata *p) // do ATA reqeust
  72. {
  73. Ataregs r;
  74. int len = 60;
  75. if (p->sectors && (p->aflag & Write) == 0)
  76. len = sizeof (Ata);
  77. r.lba = getlba(p->lba);
  78. r.sectors = p->sectors;
  79. r.feature = p->err;
  80. r.cmd = p->cmd;
  81. atacmd(&r, p->data);
  82. p->sectors = r.sectors;
  83. p->err = r.err;
  84. p->cmd = r.status;
  85. return len;
  86. }
  87. int
  88. confcmd(Conf *p) // process conf request
  89. {
  90. uchar buf[1024];
  91. int len = 0, len2;
  92. switch (p->vercmd & 0xf) {
  93. case Qread:
  94. len = qcget(p->data, 1024);
  95. p->len = htons(len);
  96. break;
  97. case Qtest:
  98. len = qcget(buf, 1024);
  99. if (len != ntohs(p->len))
  100. return 0;
  101. if (memcmp(buf, p->data, len) != 0)
  102. return 0;
  103. memmove(p->data, buf, len);
  104. break;
  105. case Qprefix:
  106. len = qcget(buf, 1024);
  107. len2 = ntohs(p->len);
  108. if (len2 > len)
  109. return 0;
  110. if (memcmp(buf, p->data, len2) != 0)
  111. return 0;
  112. memmove(p->data, buf, len);
  113. p->len = htons(len);
  114. break;
  115. case Qset:
  116. len = qcget(buf, 1024);
  117. if (len > 0 && (len != p->len || memcmp(buf, p->data, len))) {
  118. p->h.flags |= Error;
  119. p->h.error = ConfigErr;
  120. break;
  121. }
  122. // fall thru
  123. case Qfset:
  124. len = ntohs(p->len);
  125. qcset(p->data, len);
  126. break;
  127. default:
  128. p->h.flags |= BadArg;
  129. }
  130. p->bufcnt = htons(Bufcount);
  131. p->firmware = htons(FWV);
  132. p->vercmd |= 0x10;
  133. return len + sizeof(Conf) - 1024;
  134. }
  135. void
  136. doaoe(Aoehdr *p)
  137. {
  138. int len;
  139. switch (p->cmd) {
  140. case ATAcmd:
  141. len = aoeata((Ata*)p);
  142. break;
  143. case Config:
  144. if ((len = confcmd((Conf *)p)) == 0)
  145. return;
  146. break;
  147. default:
  148. p->error = BadCmd;
  149. len = 1024;
  150. break;
  151. }
  152. memmove(p->dst, p->src, 6);
  153. memmove(p->src, mac, 6);
  154. p->maj = htons(shelf);
  155. p->min = slot;
  156. p->flags |= Resp;
  157. if (putpkt(sfd, (uchar *) p, len) == -1) {
  158. perror("write to network");
  159. exit(1);
  160. }
  161. }
  162. void
  163. aoe(void)
  164. {
  165. Aoehdr *p;
  166. uchar buf[1400];
  167. int n, sh;
  168. aoead(sfd);
  169. for (;;) {
  170. n = getpkt(sfd, buf, sizeof buf);
  171. if (n < 0) {
  172. perror("read network");
  173. exit(1);
  174. }
  175. if (n < 60)
  176. continue;
  177. p = (Aoehdr *)buf;
  178. if (ntohs(p->type) != 0x88a2)
  179. continue;
  180. if (p->flags & Resp)
  181. continue;
  182. sh = ntohs(p->maj);
  183. if (sh != shelf && sh != (ushort)~0)
  184. continue;
  185. if (p->min != slot && p->min != (uchar)~0)
  186. continue;
  187. doaoe(p);
  188. }
  189. }
  190. void
  191. usage(void)
  192. {
  193. fprintf(stderr, "usage: %s <shelf> <slot> <ethn> <device>\n",
  194. progname);
  195. exit(1);
  196. }
  197. int
  198. main(int argc, char **argv)
  199. {
  200. setbuf(stdin, NULL);
  201. atainit();
  202. progname = *argv;
  203. if (argc != 5)
  204. usage();
  205. bfd = open(argv[4], O_RDWR);
  206. if (bfd == -1) {
  207. perror("open");
  208. exit(1);
  209. }
  210. shelf = atoi(argv[1]);
  211. slot = atoi(argv[2]);
  212. size = getsize(bfd);
  213. size /= 512;
  214. sfd = dial(argv[3]);
  215. getea(sfd, argv[3], mac);
  216. printf("pid %ld: e%d.%d, %lld sectors\n",
  217. (long) getpid(), shelf, slot, size);
  218. fflush(stdout);
  219. aoe();
  220. return 0;
  221. }