aoe.c 3.7 KB

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