devsd.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  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, uvlong start, uvlong end)
  29. {
  30. SDpart *pp;
  31. int i, partno;
  32. if(parttrace)
  33. print("add %d %s %s %lld %lld\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 [%llud,%llud) to disk [0,%llud): %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 void
  201. sddump(void)
  202. {
  203. SDev *sdev;
  204. print("sdevs:\n");
  205. for(sdev = sdlist; sdev != nil; sdev = sdev->next){
  206. print("sdev %c index %d nunit %d: ",
  207. sdev->idno, sdev->index, sdev->nunit);
  208. print("\n");
  209. }
  210. }
  211. static int
  212. _sdinit(void)
  213. {
  214. ulong m;
  215. int i;
  216. SDev *sdev, *tail;
  217. SDunit *unit;
  218. /*
  219. * Probe all configured controllers and make a list
  220. * of devices found, accumulating a possible maximum number
  221. * of units attached and marking each device with an index
  222. * into the linear top-level directory array of units.
  223. */
  224. tail = nil;
  225. for(i = 0; sdifc[i] != nil; i++){
  226. if((sdev = sdifc[i]->pnp()) == nil)
  227. continue;
  228. if(sdlist != nil)
  229. tail->next = sdev;
  230. else
  231. sdlist = sdev;
  232. for(tail = sdev; tail->next != nil; tail = tail->next){
  233. tail->index = sdnunit;
  234. sdnunit += tail->nunit;
  235. }
  236. tail->index = sdnunit;
  237. sdnunit += tail->nunit;
  238. }
  239. /*
  240. * Legacy and option code goes here. This will be hard...
  241. */
  242. /*
  243. * The maximum number of possible units is known, allocate
  244. * placeholders for their datastructures; the units will be
  245. * probed and structures allocated when attached.
  246. * Allocate controller names for the different types.
  247. */
  248. if(sdnunit == 0)
  249. return 0;
  250. if((sdunit = malloc(sdnunit*sizeof(SDunit*))) == nil)
  251. return 0;
  252. sddetach = _sddetach;
  253. for(i = 0; sdifc[i] != nil; i++){
  254. if(sdifc[i]->id)
  255. sdifc[i]->id(sdlist);
  256. }
  257. if (0)
  258. sddump();
  259. m = 0;
  260. cdmask = sdmask = 0;
  261. for(i=0; i<sdnunit && i < 32; i++) {
  262. unit = sdindex2unit(i);
  263. if(unit == nil)
  264. continue;
  265. sdinitpart(unit);
  266. partition(unit);
  267. if(unit->npart > 0){ /* BUG */
  268. if((unit->inquiry[0] & 0x1F) == 0x05)
  269. cdmask |= (1<<i);
  270. else
  271. sdmask |= (1<<i);
  272. m |= (1<<i);
  273. }
  274. }
  275. //notesdinfo();
  276. _sdmask = m;
  277. return m;
  278. }
  279. int
  280. cdinit(void)
  281. {
  282. if(sdnunit == 0)
  283. _sdinit();
  284. return cdmask;
  285. }
  286. int
  287. sdinit(void)
  288. {
  289. if(sdnunit == 0)
  290. _sdinit();
  291. return sdmask;
  292. }
  293. void
  294. sdinitdev(int i, char *s)
  295. {
  296. SDunit *unit;
  297. unit = sdindex2unit(i);
  298. strcpy(s, unit->name);
  299. }
  300. void
  301. sdprintdevs(int i)
  302. {
  303. char *s;
  304. SDunit *unit;
  305. unit = sdindex2unit(i);
  306. for(i=0; i<unit->npart; i++){
  307. s = unit->part[i].name;
  308. if(strncmp(s, "dos", 3) == 0
  309. || strncmp(s, "9fat", 4) == 0
  310. || strncmp(s, "fs", 2) == 0)
  311. print(" %s!%s", unit->name, s);
  312. }
  313. }
  314. SDpart*
  315. sdfindpart(SDunit *unit, char *name)
  316. {
  317. int i;
  318. if(parttrace)
  319. print("findpart %d %s %s\t\n", unit->npart, unit->name, name);
  320. for(i=0; i<unit->npart; i++) {
  321. if(parttrace)
  322. print("%s...", unit->part[i].name);
  323. if(strcmp(unit->part[i].name, name) == 0){
  324. if(parttrace)
  325. print("\n");
  326. return &unit->part[i];
  327. }
  328. }
  329. if(parttrace)
  330. print("not found\n");
  331. return nil;
  332. }
  333. typedef struct Scsicrud Scsicrud;
  334. struct Scsicrud {
  335. Fs fs;
  336. vlong offset;
  337. SDunit *unit;
  338. SDpart *part;
  339. };
  340. long
  341. sdread(Fs *vcrud, void *v, long n)
  342. {
  343. Scsicrud *crud;
  344. long x;
  345. crud = (Scsicrud*)vcrud;
  346. x = sdbio(crud->unit, crud->part, v, n, crud->offset);
  347. if(x > 0)
  348. crud->offset += x;
  349. return x;
  350. }
  351. vlong
  352. sdseek(Fs *vcrud, vlong seek)
  353. {
  354. ((Scsicrud*)vcrud)->offset = seek;
  355. return seek;
  356. }
  357. void*
  358. sdgetfspart(int i, char *s, int chatty)
  359. {
  360. SDunit *unit;
  361. SDpart *p;
  362. Scsicrud *crud;
  363. if(cdmask&(1<<i)){
  364. if(strcmp(s, "cdboot") != 0)
  365. return nil;
  366. }else if(sdmask&(1<<i)){
  367. if(strcmp(s, "cdboot") == 0)
  368. return nil;
  369. }
  370. unit = sdindex2unit(i);
  371. if((p = sdfindpart(unit, s)) == nil){
  372. if(chatty)
  373. print("unknown partition %s!%s\n", unit->name, s);
  374. return nil;
  375. }
  376. if(p->crud == nil) {
  377. crud = malloc(sizeof(Scsicrud));
  378. crud->fs.dev = i;
  379. crud->fs.diskread = sdread;
  380. crud->fs.diskseek = sdseek;
  381. // crud->start = 0;
  382. crud->unit = unit;
  383. crud->part = p;
  384. if(dosinit(&crud->fs) < 0 && dosinit(&crud->fs) < 0 && kfsinit(&crud->fs) < 0){
  385. if(chatty)
  386. print("partition %s!%s does not contain a DOS or KFS file system\n",
  387. unit->name, s);
  388. return nil;
  389. }
  390. p->crud = crud;
  391. }
  392. return p->crud;
  393. }
  394. /*
  395. * Leave partitions around for devsd to pick up.
  396. * (Needed by boot process; more extensive
  397. * partitioning is done by termrc or cpurc).
  398. */
  399. void
  400. sdaddconf(int i)
  401. {
  402. SDunit *unit;
  403. SDpart *pp;
  404. unit = sdindex2unit(i);
  405. /*
  406. * If there were no partitions (just data and partition), don't bother.
  407. */
  408. if(unit->npart<= 1 || (unit->npart==2 && strcmp(unit->part[1].name, "partition")==0))
  409. return;
  410. addconf("%spart=", unit->name);
  411. for(i=1, pp=&unit->part[i]; i<unit->npart; i++, pp++) /* skip 0, which is "data" */
  412. addconf("%s%s %lld %lld", i==1 ? "" : "/", pp->name,
  413. pp->start, pp->end);
  414. addconf("\n");
  415. }
  416. int
  417. sdboot(int dev, char *pname, Boot *b)
  418. {
  419. char *file;
  420. Fs *fs;
  421. if((file = strchr(pname, '!')) == nil) {
  422. print("syntax is sdC0!partition!file\n");
  423. return -1;
  424. }
  425. *file++ = '\0';
  426. fs = sdgetfspart(dev, pname, 1);
  427. if(fs == nil)
  428. return -1;
  429. return fsboot(fs, file, b);
  430. }
  431. long
  432. sdbio(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
  433. {
  434. long l;
  435. ulong bno, max, nb, offset;
  436. static uchar *b;
  437. char *a;
  438. static ulong bsz;
  439. a = va;
  440. memset(a, 0xDA, len);
  441. qlock(&unit->ctl);
  442. if(unit->changed){
  443. qunlock(&unit->ctl);
  444. return 0;
  445. }
  446. /*
  447. * Check the request is within bounds.
  448. * Removeable drives are locked throughout the I/O
  449. * in case the media changes unexpectedly.
  450. * Non-removeable drives are not locked during the I/O
  451. * to allow the hardware to optimise if it can; this is
  452. * a little fast and loose.
  453. * It's assumed that non-removable media parameters
  454. * (sectors, secsize) can't change once the drive has
  455. * been brought online.
  456. */
  457. if (unit->secsize == 0)
  458. panic("sdbio: zero sector size");
  459. bno = (off/unit->secsize) + pp->start;
  460. nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
  461. max = SDmaxio/unit->secsize;
  462. if(nb > max)
  463. nb = max;
  464. if(bno+nb > pp->end)
  465. nb = pp->end - bno;
  466. if(bno >= pp->end || nb == 0){
  467. qunlock(&unit->ctl);
  468. return 0;
  469. }
  470. if(!(unit->inquiry[1] & 0x80))
  471. qunlock(&unit->ctl);
  472. if(bsz < nb*unit->secsize){
  473. b = malloc(nb*unit->secsize);
  474. bsz = nb*unit->secsize;
  475. }
  476. // b = sdmalloc(nb*unit->secsize);
  477. // if(b == nil)
  478. // return 0;
  479. offset = off%unit->secsize;
  480. if((l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno)) < 0) {
  481. // sdfree(b);
  482. return 0;
  483. }
  484. if(l < offset)
  485. len = 0;
  486. else if(len > l - offset)
  487. len = l - offset;
  488. if(len)
  489. memmove(a, b+offset, len);
  490. // sdfree(b);
  491. if(unit->inquiry[1] & 0x80)
  492. qunlock(&unit->ctl);
  493. return len;
  494. }
  495. #ifdef DMA
  496. long
  497. sdrio(SDreq *r, void* a, long n)
  498. {
  499. if(n >= SDmaxio || n < 0)
  500. return 0;
  501. r->data = nil;
  502. if(n){
  503. if((r->data = malloc(n)) == nil)
  504. return 0;
  505. if(r->write)
  506. memmove(r->data, a, n);
  507. }
  508. r->dlen = n;
  509. if(r->unit->dev->ifc->rio(r) != SDok){
  510. // cgascreenputs("1", 1);
  511. if(r->data != nil){
  512. sdfree(r->data);
  513. r->data = nil;
  514. }
  515. return 0;
  516. }
  517. // cgascreenputs("2", 1);
  518. if(!r->write && r->rlen > 0)
  519. memmove(a, r->data, r->rlen);
  520. // cgascreenputs("3", 1);
  521. if(r->data != nil){
  522. sdfree(r->data);
  523. r->data = nil;
  524. }
  525. // cgascreenputs("4", 1);
  526. return r->rlen;
  527. }
  528. #endif /* DMA */
  529. void
  530. sleep(void*, int (*fn)(void*), void *v)
  531. {
  532. int x;
  533. x = spllo();
  534. while(!fn(v))
  535. ;
  536. splx(x);
  537. }
  538. void
  539. tsleep(void*, int (*fn)(void*), void *v, int msec)
  540. {
  541. int x;
  542. ulong start;
  543. x = spllo();
  544. for(start = m->ticks; TK2MS(m->ticks - start) < msec && !fn(v); )
  545. ;
  546. splx(x);
  547. }
  548. void*
  549. sdmalloc(void *p, ulong sz)
  550. {
  551. if(p != nil) {
  552. memset(p, 0, sz);
  553. return p;
  554. }
  555. return malloc(sz);
  556. }