devsd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /*
  2. * Storage Device.
  3. */
  4. #include "u.h"
  5. #include "mem.h"
  6. #include "lib.h"
  7. #include "dat.h"
  8. #include "fns.h"
  9. #include "io.h"
  10. #include "ureg.h"
  11. #include "error.h"
  12. #include "sd.h"
  13. #include "fs.h"
  14. #define parttrace 0
  15. extern SDifc* sdifc[];
  16. static SDev* sdlist;
  17. static SDunit** sdunit;
  18. static int sdnunit;
  19. static int _sdmask;
  20. static int cdmask;
  21. static int sdmask;
  22. enum {
  23. Rawcmd,
  24. Rawdata,
  25. Rawstatus,
  26. };
  27. void
  28. sdaddpart(SDunit* unit, char* name, ulong start, ulong end)
  29. {
  30. SDpart *pp;
  31. int i, partno;
  32. if(parttrace)
  33. print("add %d %s %s %ld %ld\n", unit->npart, unit->name, name, start, end);
  34. /*
  35. * Check name not already used
  36. * and look for a free slot.
  37. */
  38. if(unit->part != nil){
  39. partno = -1;
  40. for(i = 0; i < SDnpart; i++){
  41. pp = &unit->part[i];
  42. if(!pp->valid){
  43. if(partno == -1)
  44. partno = i;
  45. break;
  46. }
  47. if(strcmp(name, pp->name) == 0){
  48. if(pp->start == start && pp->end == end){
  49. if(parttrace)
  50. print("already present\n");
  51. return;
  52. }
  53. }
  54. }
  55. }else{
  56. if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil){
  57. if(parttrace)
  58. print("malloc failed\n");
  59. return;
  60. }
  61. partno = 0;
  62. }
  63. /*
  64. * Check there is a free slot and size and extent are valid.
  65. */
  66. if(partno == -1 || start > end || end > unit->sectors){
  67. print("cannot add %s!%s [%lud,%lud) to disk [0,%lud): %s\n",
  68. unit->name, name, start, end, unit->sectors,
  69. partno==-1 ? "no free partitions" : "partition boundaries out of range");
  70. return;
  71. }
  72. pp = &unit->part[partno];
  73. pp->start = start;
  74. pp->end = end;
  75. strncpy(pp->name, name, NAMELEN);
  76. pp->valid = 1;
  77. unit->npart++;
  78. }
  79. void
  80. sddelpart(SDunit* unit, char* name)
  81. {
  82. int i;
  83. SDpart *pp;
  84. if(parttrace)
  85. print("del %d %s %s\n", unit->npart, unit->name, name);
  86. /*
  87. * Look for the partition to delete.
  88. * Can't delete if someone still has it open.
  89. * If it's the last valid partition zap the
  90. * whole table.
  91. */
  92. pp = unit->part;
  93. for(i = 0; i < SDnpart; i++){
  94. if(strncmp(name, pp->name, NAMELEN) == 0)
  95. break;
  96. pp++;
  97. }
  98. if(i >= SDnpart)
  99. return;
  100. pp->valid = 0;
  101. unit->npart--;
  102. if(unit->npart == 0){
  103. free(unit->part);
  104. unit->part = nil;
  105. }
  106. }
  107. static int
  108. sdinitpart(SDunit* unit)
  109. {
  110. unit->sectors = unit->secsize = 0;
  111. unit->npart = 0;
  112. if(unit->part){
  113. free(unit->part);
  114. unit->part = nil;
  115. }
  116. if(unit->inquiry[0] & 0xC0)
  117. return 0;
  118. switch(unit->inquiry[0] & 0x1F){
  119. case 0x00: /* DA */
  120. case 0x04: /* WORM */
  121. case 0x05: /* CD-ROM */
  122. case 0x07: /* MO */
  123. break;
  124. default:
  125. return 0;
  126. }
  127. if(unit->dev->ifc->online == nil || unit->dev->ifc->online(unit) == 0)
  128. return 0;
  129. sdaddpart(unit, "data", 0, unit->sectors);
  130. return 1;
  131. }
  132. static SDunit*
  133. sdgetunit(SDev* sdev, int subno)
  134. {
  135. int index;
  136. SDunit *unit;
  137. /*
  138. * Associate a unit with a given device and sub-unit
  139. * number on that device.
  140. * The device will be probed if it has not already been
  141. * successfully accessed.
  142. */
  143. qlock(&sdqlock);
  144. index = sdev->index+subno;
  145. unit = sdunit[index];
  146. if(unit == nil){
  147. if((unit = malloc(sizeof(SDunit))) == nil){
  148. qunlock(&sdqlock);
  149. return nil;
  150. }
  151. if(sdev->enabled == 0 && sdev->ifc->enable)
  152. sdev->ifc->enable(sdev);
  153. sdev->enabled = 1;
  154. snprint(unit->name, NAMELEN, "sd%c%d", sdev->idno, subno);
  155. unit->subno = subno;
  156. unit->dev = sdev;
  157. /*
  158. * No need to lock anything here as this is only
  159. * called before the unit is made available in the
  160. * sdunit[] array.
  161. */
  162. if(unit->dev->ifc->verify(unit) == 0){
  163. qunlock(&sdqlock);
  164. free(unit);
  165. return nil;
  166. }
  167. sdunit[index] = unit;
  168. }
  169. qunlock(&sdqlock);
  170. return unit;
  171. }
  172. static SDunit*
  173. sdindex2unit(int index)
  174. {
  175. SDev *sdev;
  176. /*
  177. * Associate a unit with a given index into the top-level
  178. * device directory.
  179. * The device will be probed if it has not already been
  180. * successfully accessed.
  181. */
  182. for(sdev = sdlist; sdev != nil; sdev = sdev->next){
  183. if(index >= sdev->index && index < sdev->index+sdev->nunit)
  184. return sdgetunit(sdev, index-sdev->index);
  185. }
  186. return nil;
  187. }
  188. static void
  189. _sddetach(void)
  190. {
  191. SDev *sdev;
  192. for(sdev = sdlist; sdev != nil; sdev = sdev->next){
  193. if(sdev->enabled == 0)
  194. continue;
  195. if(sdev->ifc->disable)
  196. sdev->ifc->disable(sdev);
  197. sdev->enabled = 0;
  198. }
  199. }
  200. static int
  201. _sdinit(void)
  202. {
  203. ulong m;
  204. int i;
  205. SDev *sdev, *tail;
  206. SDunit *unit;
  207. /*
  208. * Probe all configured controllers and make a list
  209. * of devices found, accumulating a possible maximum number
  210. * of units attached and marking each device with an index
  211. * into the linear top-level directory array of units.
  212. */
  213. tail = nil;
  214. for(i = 0; sdifc[i] != nil; i++){
  215. if((sdev = sdifc[i]->pnp()) == nil)
  216. continue;
  217. if(sdlist != nil)
  218. tail->next = sdev;
  219. else
  220. sdlist = sdev;
  221. for(tail = sdev; tail->next != nil; tail = tail->next){
  222. tail->index = sdnunit;
  223. sdnunit += tail->nunit;
  224. }
  225. tail->index = sdnunit;
  226. sdnunit += tail->nunit;
  227. }
  228. /*
  229. * Legacy and option code goes here. This will be hard...
  230. */
  231. /*
  232. * The maximum number of possible units is known, allocate
  233. * placeholders for their datastructures; the units will be
  234. * probed and structures allocated when attached.
  235. * Allocate controller names for the different types.
  236. */
  237. if(sdnunit == 0)
  238. return 0;
  239. if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
  240. return 0;
  241. sddetach = _sddetach;
  242. for(i = 0; sdifc[i] != nil; i++){
  243. if(sdifc[i]->id)
  244. sdifc[i]->id(sdlist);
  245. }
  246. m = 0;
  247. cdmask = sdmask = 0;
  248. for(i=0; i<sdnunit && i < 32; i++) {
  249. unit = sdindex2unit(i);
  250. if(unit == nil)
  251. continue;
  252. sdinitpart(unit);
  253. partition(unit);
  254. if(unit->npart > 0){ /* BUG */
  255. if((unit->inquiry[0] & 0x1F) == 0x05)
  256. cdmask |= (1<<i);
  257. else
  258. sdmask |= (1<<i);
  259. m |= (1<<i);
  260. }
  261. }
  262. //notesdinfo();
  263. _sdmask = m;
  264. return m;
  265. }
  266. int
  267. cdinit(void)
  268. {
  269. if(sdnunit == 0)
  270. _sdinit();
  271. return cdmask;
  272. }
  273. int
  274. sdinit(void)
  275. {
  276. if(sdnunit == 0)
  277. _sdinit();
  278. return sdmask;
  279. }
  280. void
  281. sdinitdev(int i, char *s)
  282. {
  283. SDunit *unit;
  284. unit = sdindex2unit(i);
  285. strcpy(s, unit->name);
  286. }
  287. void
  288. sdprintdevs(int i)
  289. {
  290. char *s;
  291. SDunit *unit;
  292. unit = sdindex2unit(i);
  293. for(i=0; i<unit->npart; i++){
  294. s = unit->part[i].name;
  295. if(strncmp(s, "dos", 3) == 0
  296. || strncmp(s, "9fat", 4) == 0
  297. || strncmp(s, "fs", 2) == 0)
  298. print(" %s!%s", unit->name, s);
  299. }
  300. }
  301. SDpart*
  302. sdfindpart(SDunit *unit, char *name)
  303. {
  304. int i;
  305. if(parttrace)
  306. print("findpart %d %s %s\t\n", unit->npart, unit->name, name);
  307. for(i=0; i<unit->npart; i++) {
  308. if(parttrace)
  309. print("%s...", unit->part[i].name);
  310. if(strcmp(unit->part[i].name, name) == 0){
  311. if(parttrace)
  312. print("\n");
  313. return &unit->part[i];
  314. }
  315. }
  316. if(parttrace)
  317. print("not found\n");
  318. return nil;
  319. }
  320. typedef struct Scsicrud Scsicrud;
  321. struct Scsicrud {
  322. Fs fs;
  323. vlong offset;
  324. SDunit *unit;
  325. SDpart *part;
  326. };
  327. long
  328. sdread(Fs *vcrud, void *v, long n)
  329. {
  330. Scsicrud *crud;
  331. long x;
  332. crud = (Scsicrud*)vcrud;
  333. x = sdbio(crud->unit, crud->part, v, n, crud->offset);
  334. if(x > 0)
  335. crud->offset += x;
  336. return x;
  337. }
  338. vlong
  339. sdseek(Fs *vcrud, vlong seek)
  340. {
  341. ((Scsicrud*)vcrud)->offset = seek;
  342. return seek;
  343. }
  344. void*
  345. sdgetfspart(int i, char *s, int chatty)
  346. {
  347. SDunit *unit;
  348. SDpart *p;
  349. Scsicrud *crud;
  350. if(cdmask&(1<<i)){
  351. if(strcmp(s, "cdboot") != 0)
  352. return nil;
  353. }else if(sdmask&(1<<i)){
  354. if(strcmp(s, "cdboot") == 0)
  355. return nil;
  356. }
  357. unit = sdindex2unit(i);
  358. if((p = sdfindpart(unit, s)) == nil){
  359. if(chatty)
  360. print("unknown partition %s!%s\n", unit->name, s);
  361. return nil;
  362. }
  363. if(p->crud == nil) {
  364. crud = malloc(sizeof(Scsicrud));
  365. crud->fs.dev = i;
  366. crud->fs.diskread = sdread;
  367. crud->fs.diskseek = sdseek;
  368. // crud->start = 0;
  369. crud->unit = unit;
  370. crud->part = p;
  371. if(dosinit(&crud->fs) < 0 && dosinit(&crud->fs) < 0 && kfsinit(&crud->fs) < 0){
  372. if(chatty)
  373. print("partition %s!%s does not contain a DOS or KFS file system\n",
  374. unit->name, s);
  375. return nil;
  376. }
  377. p->crud = crud;
  378. }
  379. return p->crud;
  380. }
  381. /*
  382. * Leave partitions around for devsd to pick up.
  383. * (Needed by boot process; more extensive
  384. * partitioning is done by termrc or cpurc).
  385. */
  386. void
  387. sdaddconf(int i)
  388. {
  389. SDunit *unit;
  390. SDpart *pp;
  391. unit = sdindex2unit(i);
  392. /*
  393. * If there were no partitions (just data and partition), don't bother.
  394. */
  395. if(unit->npart<= 1 || (unit->npart==2 && strcmp(unit->part[1].name, "partition")==0))
  396. return;
  397. addconf("%spart=", unit->name);
  398. for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++) /* skip 0, which is "data" */
  399. addconf("%s%s %ld %ld", i==1 ? "" : "/", pp->name,
  400. pp->start, pp->end);
  401. addconf("\n");
  402. }
  403. int
  404. sdboot(int dev, char *pname, Boot *b)
  405. {
  406. char *file;
  407. Fs *fs;
  408. if((file = strchr(pname, '!')) == nil) {
  409. print("syntax is sdC0!partition!file\n");
  410. return -1;
  411. }
  412. *file++ = '\0';
  413. fs = sdgetfspart(dev, pname, 1);
  414. if(fs == nil)
  415. return -1;
  416. return fsboot(fs, file, b);
  417. }
  418. long
  419. sdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
  420. {
  421. long l;
  422. ulong bno, max, nb, offset;
  423. static uchar *b;
  424. char *a;
  425. static ulong bsz;
  426. a = va;
  427. memset(a, 0xDA, len);
  428. qlock(&unit->ctl);
  429. if(unit->changed){
  430. qunlock(&unit->ctl);
  431. return 0;
  432. }
  433. /*
  434. * Check the request is within bounds.
  435. * Removeable drives are locked throughout the I/O
  436. * in case the media changes unexpectedly.
  437. * Non-removeable drives are not locked during the I/O
  438. * to allow the hardware to optimise if it can; this is
  439. * a little fast and loose.
  440. * It's assumed that non-removable media parameters
  441. * (sectors, secsize) can't change once the drive has
  442. * been brought online.
  443. */
  444. bno = (off/unit->secsize) + pp->start;
  445. nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
  446. max = SDmaxio/unit->secsize;
  447. if(nb > max)
  448. nb = max;
  449. if(bno+nb > pp->end)
  450. nb = pp->end - bno;
  451. if(bno >= pp->end || nb == 0){
  452. qunlock(&unit->ctl);
  453. return 0;
  454. }
  455. if(!(unit->inquiry[1] & 0x80))
  456. qunlock(&unit->ctl);
  457. if(bsz < nb*unit->secsize){
  458. b = malloc(nb*unit->secsize);
  459. bsz = nb*unit->secsize;
  460. }
  461. // b = sdmalloc(nb*unit->secsize);
  462. // if(b == nil)
  463. // return 0;
  464. offset = off%unit->secsize;
  465. if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) {
  466. // sdfree(b);
  467. return 0;
  468. }
  469. if(l < offset)
  470. len = 0;
  471. else if(len > l - offset)
  472. len = l - offset;
  473. if(len)
  474. memmove(a, b+offset, len);
  475. // sdfree(b);
  476. if(unit->inquiry[1] & 0x80)
  477. qunlock(&unit->ctl);
  478. return len;
  479. }
  480. #ifdef DMA
  481. long
  482. sdrio(SDreq *r, void* a, long n)
  483. {
  484. if(n >= SDmaxio || n < 0)
  485. return 0;
  486. r->data = nil;
  487. if(n){
  488. if((r->data = malloc(n)) == nil)
  489. return 0;
  490. if(r->write)
  491. memmove(r->data, a, n);
  492. }
  493. r->dlen = n;
  494. if(r->unit->dev->ifc->rio(r) != SDok){
  495. // cgascreenputs("1", 1);
  496. if(r->data != nil){
  497. sdfree(r->data);
  498. r->data = nil;
  499. }
  500. return 0;
  501. }
  502. // cgascreenputs("2", 1);
  503. if(!r->write && r->rlen > 0)
  504. memmove(a, r->data, r->rlen);
  505. // cgascreenputs("3", 1);
  506. if(r->data != nil){
  507. sdfree(r->data);
  508. r->data = nil;
  509. }
  510. // cgascreenputs("4", 1);
  511. return r->rlen;
  512. }
  513. #endif /* DMA */
  514. void
  515. sleep(void*, int (*fn)(void*), void *v)
  516. {
  517. int x;
  518. x = spllo();
  519. while(!fn(v))
  520. ;
  521. splx(x);
  522. return;
  523. }
  524. void
  525. tsleep(void*, int (*fn)(void*), void *v, int msec)
  526. {
  527. int x;
  528. ulong start;
  529. x = spllo();
  530. for(start = m->ticks; TK2MS(m->ticks - start) < msec
  531. && !fn(v); )
  532. ;
  533. splx(x);
  534. return;
  535. }
  536. void*
  537. sdmalloc(void *p, ulong sz)
  538. {
  539. if(p != nil) {
  540. memset(p, 0, sz);
  541. return p;
  542. }
  543. return malloc(sz);
  544. }