devsd.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Storage Device.
  11. */
  12. #include "u.h"
  13. #include "../port/lib.h"
  14. #include "mem.h"
  15. #include "dat.h"
  16. #include "fns.h"
  17. #include "io.h"
  18. #include "ureg.h"
  19. #include "../port/error.h"
  20. #include "../port/sd.h"
  21. extern Dev sddevtab;
  22. extern SDifc* sdifc[];
  23. static char Echange[] = "media or partition has changed";
  24. static char devletters[] = "0123456789"
  25. "abcdefghijklmnopqrstuvwxyz"
  26. "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  27. static SDev *devs[sizeof devletters-1];
  28. static QLock devslock;
  29. enum {
  30. Rawcmd,
  31. Rawdata,
  32. Rawstatus,
  33. };
  34. enum {
  35. Qtopdir = 1, /* top level directory */
  36. Qtopbase,
  37. Qtopctl = Qtopbase,
  38. Qunitdir, /* directory per unit */
  39. Qunitbase,
  40. Qctl = Qunitbase,
  41. Qraw,
  42. Qpart,
  43. TypeLOG = 4,
  44. NType = (1<<TypeLOG),
  45. TypeMASK = (NType-1),
  46. TypeSHIFT = 0,
  47. PartLOG = 8,
  48. NPart = (1<<PartLOG),
  49. PartMASK = (NPart-1),
  50. PartSHIFT = TypeLOG,
  51. UnitLOG = 8,
  52. NUnit = (1<<UnitLOG),
  53. UnitMASK = (NUnit-1),
  54. UnitSHIFT = (PartLOG+TypeLOG),
  55. DevLOG = 8,
  56. NDev = (1 << DevLOG),
  57. DevMASK = (NDev-1),
  58. DevSHIFT = (UnitLOG+PartLOG+TypeLOG),
  59. Ncmd = 20,
  60. };
  61. #define TYPE(q) ((((uint32_t)(q).path)>>TypeSHIFT) & TypeMASK)
  62. #define PART(q) ((((uint32_t)(q).path)>>PartSHIFT) & PartMASK)
  63. #define UNIT(q) ((((uint32_t)(q).path)>>UnitSHIFT) & UnitMASK)
  64. #define DEV(q) ((((uint32_t)(q).path)>>DevSHIFT) & DevMASK)
  65. #define QID(d,u, p, t) (((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\
  66. ((p)<<PartSHIFT)|((t)<<TypeSHIFT))
  67. void
  68. sdaddpart(SDunit* unit, char* name, uint64_t start, uint64_t end)
  69. {
  70. SDpart *pp;
  71. int i, partno;
  72. /*
  73. * Check name not already used
  74. * and look for a free slot.
  75. */
  76. if(unit->part != nil){
  77. partno = -1;
  78. for(i = 0; i < unit->npart; i++){
  79. pp = &unit->part[i];
  80. if(!pp->valid){
  81. if(partno == -1)
  82. partno = i;
  83. break;
  84. }
  85. if(strcmp(name, pp->SDperm.name) == 0){
  86. if(pp->start == start && pp->end == end)
  87. return;
  88. error(Ebadctl);
  89. }
  90. }
  91. }
  92. else{
  93. if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil)
  94. error(Enomem);
  95. unit->npart = SDnpart;
  96. partno = 0;
  97. }
  98. /*
  99. * If no free slot found then increase the
  100. * array size (can't get here with unit->part == nil).
  101. */
  102. if(partno == -1){
  103. if(unit->npart >= NPart)
  104. error(Enomem);
  105. if((pp = malloc(sizeof(SDpart)*(unit->npart+SDnpart))) == nil)
  106. error(Enomem);
  107. memmove(pp, unit->part, sizeof(SDpart)*unit->npart);
  108. free(unit->part);
  109. unit->part = pp;
  110. partno = unit->npart;
  111. unit->npart += SDnpart;
  112. }
  113. /*
  114. * Check size and extent are valid.
  115. */
  116. if(start > end || end > unit->sectors)
  117. error(Eio);
  118. pp = &unit->part[partno];
  119. pp->start = start;
  120. pp->end = end;
  121. kstrdup(&pp->SDperm.name, name);
  122. kstrdup(&pp->SDperm.user, eve);
  123. pp->SDperm.perm = 0640;
  124. pp->valid = 1;
  125. }
  126. static void
  127. sddelpart(SDunit* unit, char* name)
  128. {
  129. Proc *up = externup();
  130. int i;
  131. SDpart *pp;
  132. /*
  133. * Look for the partition to delete.
  134. * Can't delete if someone still has it open.
  135. */
  136. pp = unit->part;
  137. for(i = 0; i < unit->npart; i++){
  138. if(strcmp(name, pp->SDperm.name) == 0)
  139. break;
  140. pp++;
  141. }
  142. if(i >= unit->npart)
  143. error(Ebadctl);
  144. if(strcmp(up->user, pp->SDperm.user) && !iseve())
  145. error(Eperm);
  146. pp->valid = 0;
  147. pp->vers++;
  148. }
  149. static void
  150. sdincvers(SDunit *unit)
  151. {
  152. int i;
  153. unit->vers++;
  154. if(unit->part){
  155. for(i = 0; i < unit->npart; i++){
  156. unit->part[i].valid = 0;
  157. unit->part[i].vers++;
  158. }
  159. }
  160. }
  161. static int
  162. sdinitpart(SDunit* unit)
  163. {
  164. #if 0
  165. Mach *m;
  166. int nf;
  167. uint64_t start, end;
  168. char *f[4], *p, *q, buf[10];
  169. m = machp();
  170. #endif
  171. if(unit->sectors > 0){
  172. unit->sectors = unit->secsize = 0;
  173. sdincvers(unit);
  174. }
  175. /* device must be connected or not; other values are trouble */
  176. if(unit->inquiry[0] & 0xC0) /* see SDinq0periphqual */
  177. return 0;
  178. switch(unit->inquiry[0] & SDinq0periphtype){
  179. case SDperdisk:
  180. case SDperworm:
  181. case SDpercd:
  182. case SDpermo:
  183. break;
  184. default:
  185. return 0;
  186. }
  187. if(unit->dev->ifc->online)
  188. unit->dev->ifc->online(unit);
  189. if(unit->sectors){
  190. sdincvers(unit);
  191. sdaddpart(unit, "data", 0, unit->sectors);
  192. /*
  193. * Use partitions passed from boot program,
  194. * e.g.
  195. * sdC0part=dos 63 123123/plan9 123123 456456
  196. * This happens before /boot sets hostname so the
  197. * partitions will have the null-string for user.
  198. * The gen functions patch it up.
  199. */
  200. #if 0
  201. snprint(buf, sizeof buf, "%spart", unit->SDperm.name);
  202. for(p = getconf(buf); p != nil; p = q){
  203. if(q = strchr(p, '/'))
  204. *q++ = '\0';
  205. nf = tokenize(p, f, nelem(f));
  206. if(nf < 3)
  207. continue;
  208. start = strtoull(f[1], 0, 0);
  209. end = strtoull(f[2], 0, 0);
  210. if(!waserror()){
  211. sdaddpart(unit, f[0], start, end);
  212. poperror();
  213. }
  214. }
  215. #endif
  216. }
  217. return 1;
  218. }
  219. static int
  220. sdindex(int idno)
  221. {
  222. char *p;
  223. p = strchr(devletters, idno);
  224. if(p == nil)
  225. return -1;
  226. return p-devletters;
  227. }
  228. static SDev*
  229. sdgetdev(int idno)
  230. {
  231. SDev *sdev;
  232. int i;
  233. if((i = sdindex(idno)) < 0)
  234. return nil;
  235. qlock(&devslock);
  236. if(sdev = devs[i])
  237. incref(&sdev->r);
  238. qunlock(&devslock);
  239. return sdev;
  240. }
  241. static SDunit*
  242. sdgetunit(SDev* sdev, int subno)
  243. {
  244. SDunit *unit;
  245. char buf[32];
  246. /*
  247. * Associate a unit with a given device and sub-unit
  248. * number on that device.
  249. * The device will be probed if it has not already been
  250. * successfully accessed.
  251. */
  252. qlock(&sdev->unitlock);
  253. if(subno > sdev->nunit){
  254. qunlock(&sdev->unitlock);
  255. return nil;
  256. }
  257. unit = sdev->unit[subno];
  258. if(unit == nil){
  259. /*
  260. * Probe the unit only once. This decision
  261. * may be a little severe and reviewed later.
  262. */
  263. if(sdev->unitflg[subno]){
  264. qunlock(&sdev->unitlock);
  265. return nil;
  266. }
  267. if((unit = malloc(sizeof(SDunit))) == nil){
  268. qunlock(&sdev->unitlock);
  269. return nil;
  270. }
  271. sdev->unitflg[subno] = 1;
  272. snprint(buf, sizeof(buf), "%s%d", sdev->name, subno);
  273. kstrdup(&unit->SDperm.name, buf);
  274. kstrdup(&unit->SDperm.user, eve);
  275. unit->SDperm.perm = 0555;
  276. unit->subno = subno;
  277. unit->dev = sdev;
  278. if(sdev->enabled == 0 && sdev->ifc->enable)
  279. sdev->ifc->enable(sdev);
  280. sdev->enabled = 1;
  281. /*
  282. * No need to lock anything here as this is only
  283. * called before the unit is made available in the
  284. * sdunit[] array.
  285. */
  286. if(unit->dev->ifc->verify(unit) == 0){
  287. qunlock(&sdev->unitlock);
  288. free(unit);
  289. return nil;
  290. }
  291. sdev->unit[subno] = unit;
  292. }
  293. qunlock(&sdev->unitlock);
  294. return unit;
  295. }
  296. static void
  297. sdreset(void)
  298. {
  299. int i;
  300. SDev *sdev;
  301. /*
  302. * Probe all known controller types and register any devices found.
  303. */
  304. for(i = 0; sdifc[i] != nil; i++){
  305. if(sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil)
  306. continue;
  307. sdadddevs(sdev);
  308. }
  309. }
  310. void
  311. sdadddevs(SDev *sdev)
  312. {
  313. int i, j, id;
  314. SDev *next;
  315. for(; sdev; sdev=next){
  316. next = sdev->next;
  317. sdev->unit = (SDunit**)malloc(sdev->nunit * sizeof(SDunit*));
  318. sdev->unitflg = (int*)malloc(sdev->nunit * sizeof(int));
  319. if(sdev->unit == nil || sdev->unitflg == nil){
  320. print("sdadddevs: out of memory\n");
  321. giveup:
  322. free(sdev->unit);
  323. free(sdev->unitflg);
  324. if(sdev->ifc->clear)
  325. sdev->ifc->clear(sdev);
  326. free(sdev);
  327. continue;
  328. }
  329. id = sdindex(sdev->idno);
  330. if(id == -1){
  331. print("sdadddevs: bad id number %d (%C)\n", id, id);
  332. goto giveup;
  333. }
  334. qlock(&devslock);
  335. for(i=0; i<nelem(devs); i++){
  336. if(devs[j = (id+i)%nelem(devs)] == nil){
  337. sdev->idno = devletters[j];
  338. devs[j] = sdev;
  339. snprint(sdev->name, sizeof sdev->name, "sd%c", devletters[j]);
  340. break;
  341. }
  342. }
  343. qunlock(&devslock);
  344. if(i == nelem(devs)){
  345. print("sdadddevs: out of device letters\n");
  346. goto giveup;
  347. }
  348. }
  349. }
  350. // void
  351. // sdrmdevs(SDev *sdev)
  352. // {
  353. // char buf[2];
  354. //
  355. // snprint(buf, sizeof buf, "%c", sdev->idno);
  356. // unconfigure(buf);
  357. // }
  358. void
  359. sdaddallconfs(void (*addconf)(SDunit *))
  360. {
  361. int i, u;
  362. SDev *sdev;
  363. for(i = 0; i < nelem(devs); i++) /* each controller */
  364. for(sdev = devs[i]; sdev; sdev = sdev->next)
  365. for(u = 0; u < sdev->nunit; u++) /* each drive */
  366. (*addconf)(sdev->unit[u]);
  367. }
  368. static int
  369. sd2gen(Chan* c, int i, Dir* dp)
  370. {
  371. Qid q;
  372. uint64_t l;
  373. SDpart *pp;
  374. SDperm *perm;
  375. SDunit *unit;
  376. SDev *sdev;
  377. int rv;
  378. sdev = sdgetdev(DEV(c->qid));
  379. assert(sdev);
  380. unit = sdev->unit[UNIT(c->qid)];
  381. rv = -1;
  382. switch(i){
  383. case Qctl:
  384. mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),
  385. unit->vers, QTFILE);
  386. perm = &unit->ctlperm;
  387. if(emptystr(perm->user)){
  388. kstrdup(&perm->user, eve);
  389. perm->perm = 0644; /* nothing secret in ctl */
  390. }
  391. devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);
  392. rv = 1;
  393. break;
  394. case Qraw:
  395. mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),
  396. unit->vers, QTFILE);
  397. perm = &unit->rawperm;
  398. if(emptystr(perm->user)){
  399. kstrdup(&perm->user, eve);
  400. perm->perm = DMEXCL|0600;
  401. }
  402. devdir(c, q, "raw", 0, perm->user, perm->perm, dp);
  403. rv = 1;
  404. break;
  405. case Qpart:
  406. pp = &unit->part[PART(c->qid)];
  407. l = (pp->end - pp->start) * unit->secsize;
  408. mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qpart),
  409. unit->vers+pp->vers, QTFILE);
  410. if(emptystr(pp->SDperm.user))
  411. kstrdup(&pp->SDperm.user, eve);
  412. devdir(c, q, pp->SDperm.name, l, pp->SDperm.user, pp->SDperm.perm, dp);
  413. rv = 1;
  414. break;
  415. }
  416. decref(&sdev->r);
  417. return rv;
  418. }
  419. static int
  420. sd1gen(Chan* c, int i, Dir* dp)
  421. {
  422. Qid q;
  423. switch(i){
  424. case Qtopctl:
  425. mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE);
  426. devdir(c, q, "sdctl", 0, eve, 0644, dp); /* no secrets */
  427. return 1;
  428. }
  429. return -1;
  430. }
  431. static int
  432. sdgen(Chan* c, char* d, Dirtab* dir, int j, int s, Dir* dp)
  433. {
  434. Proc *up = externup();
  435. Qid q;
  436. int64_t l;
  437. int i, r;
  438. SDpart *pp;
  439. SDunit *unit;
  440. SDev *sdev;
  441. switch(TYPE(c->qid)){
  442. case Qtopdir:
  443. if(s == DEVDOTDOT){
  444. mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
  445. sprint(up->genbuf, "#%C", sddevtab.dc);
  446. devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  447. return 1;
  448. }
  449. if(s+Qtopbase < Qunitdir)
  450. return sd1gen(c, s+Qtopbase, dp);
  451. s -= (Qunitdir-Qtopbase);
  452. qlock(&devslock);
  453. for(i=0; i<nelem(devs); i++){
  454. if(devs[i]){
  455. if(s < devs[i]->nunit)
  456. break;
  457. s -= devs[i]->nunit;
  458. }
  459. }
  460. if(i == nelem(devs)){
  461. /* Run off the end of the list */
  462. qunlock(&devslock);
  463. return -1;
  464. }
  465. if((sdev = devs[i]) == nil){
  466. qunlock(&devslock);
  467. return 0;
  468. }
  469. incref(&sdev->r);
  470. qunlock(&devslock);
  471. if((unit = sdev->unit[s]) == nil)
  472. if((unit = sdgetunit(sdev, s)) == nil){
  473. decref(&sdev->r);
  474. return 0;
  475. }
  476. mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);
  477. if(emptystr(unit->SDperm.user))
  478. kstrdup(&unit->SDperm.user, eve);
  479. devdir(c, q, unit->SDperm.name, 0, unit->SDperm.user, unit->SDperm.perm, dp);
  480. decref(&sdev->r);
  481. return 1;
  482. case Qunitdir:
  483. if(s == DEVDOTDOT){
  484. mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);
  485. sprint(up->genbuf, "#%C", sddevtab.dc);
  486. devdir(c, q, up->genbuf, 0, eve, 0555, dp);
  487. return 1;
  488. }
  489. if((sdev = sdgetdev(DEV(c->qid))) == nil){
  490. devdir(c, c->qid, "unavailable", 0, eve, 0, dp);
  491. return 1;
  492. }
  493. unit = sdev->unit[UNIT(c->qid)];
  494. qlock(&unit->ctl);
  495. /*
  496. * Check for media change.
  497. * If one has already been detected, sectors will be zero.
  498. * If there is one waiting to be detected, online
  499. * will return > 1.
  500. * Online is a bit of a large hammer but does the job.
  501. */
  502. if(unit->sectors == 0
  503. || (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))
  504. sdinitpart(unit);
  505. i = s+Qunitbase;
  506. if(i < Qpart){
  507. r = sd2gen(c, i, dp);
  508. qunlock(&unit->ctl);
  509. decref(&sdev->r);
  510. return r;
  511. }
  512. i -= Qpart;
  513. if(unit->part == nil || i >= unit->npart){
  514. qunlock(&unit->ctl);
  515. decref(&sdev->r);
  516. break;
  517. }
  518. pp = &unit->part[i];
  519. if(!pp->valid){
  520. qunlock(&unit->ctl);
  521. decref(&sdev->r);
  522. return 0;
  523. }
  524. l = (pp->end - pp->start) * (int64_t)unit->secsize;
  525. mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),
  526. unit->vers+pp->vers, QTFILE);
  527. if(emptystr(pp->SDperm.user))
  528. kstrdup(&pp->SDperm.user, eve);
  529. devdir(c, q, pp->SDperm.name, l, pp->SDperm.user, pp->SDperm.perm, dp);
  530. qunlock(&unit->ctl);
  531. decref(&sdev->r);
  532. return 1;
  533. case Qraw:
  534. case Qctl:
  535. case Qpart:
  536. if((sdev = sdgetdev(DEV(c->qid))) == nil){
  537. devdir(c, q, "unavailable", 0, eve, 0, dp);
  538. return 1;
  539. }
  540. unit = sdev->unit[UNIT(c->qid)];
  541. qlock(&unit->ctl);
  542. r = sd2gen(c, TYPE(c->qid), dp);
  543. qunlock(&unit->ctl);
  544. decref(&sdev->r);
  545. return r;
  546. case Qtopctl:
  547. return sd1gen(c, TYPE(c->qid), dp);
  548. default:
  549. break;
  550. }
  551. return -1;
  552. }
  553. static Chan*
  554. sdattach(char* spec)
  555. {
  556. Chan *c;
  557. char *p;
  558. SDev *sdev;
  559. int idno, subno;
  560. if(*spec == '\0'){
  561. c = devattach(sddevtab.dc, spec);
  562. mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR);
  563. return c;
  564. }
  565. if(spec[0] != 's' || spec[1] != 'd')
  566. error(Ebadspec);
  567. idno = spec[2];
  568. subno = strtol(&spec[3], &p, 0);
  569. if(p == &spec[3])
  570. error(Ebadspec);
  571. if((sdev=sdgetdev(idno)) == nil)
  572. error(Enonexist);
  573. if(sdgetunit(sdev, subno) == nil){
  574. decref(&sdev->r);
  575. error(Enonexist);
  576. }
  577. c = devattach(sddevtab.dc, spec);
  578. mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);
  579. c->devno = (sdev->idno << UnitLOG) + subno;
  580. decref(&sdev->r);
  581. return c;
  582. }
  583. static Walkqid*
  584. sdwalk(Chan* c, Chan* nc, char** name, int nname)
  585. {
  586. return devwalk(c, nc, name, nname, nil, 0, sdgen);
  587. }
  588. static int32_t
  589. sdstat(Chan* c, uint8_t* db, int32_t n)
  590. {
  591. return devstat(c, db, n, nil, 0, sdgen);
  592. }
  593. static Chan*
  594. sdopen(Chan* c, int omode)
  595. {
  596. Proc *up = externup();
  597. SDpart *pp;
  598. SDunit *unit;
  599. SDev *sdev;
  600. uint8_t tp;
  601. c = devopen(c, omode, 0, 0, sdgen);
  602. if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)
  603. return c;
  604. sdev = sdgetdev(DEV(c->qid));
  605. if(sdev == nil)
  606. error(Enonexist);
  607. unit = sdev->unit[UNIT(c->qid)];
  608. switch(TYPE(c->qid)){
  609. case Qctl:
  610. c->qid.vers = unit->vers;
  611. break;
  612. case Qraw:
  613. c->qid.vers = unit->vers;
  614. if(TAS(&unit->rawinuse) != 0){
  615. c->flag &= ~COPEN;
  616. decref(&sdev->r);
  617. error(Einuse);
  618. }
  619. unit->state = Rawcmd;
  620. break;
  621. case Qpart:
  622. qlock(&unit->ctl);
  623. if(waserror()){
  624. qunlock(&unit->ctl);
  625. c->flag &= ~COPEN;
  626. decref(&sdev->r);
  627. nexterror();
  628. }
  629. pp = &unit->part[PART(c->qid)];
  630. c->qid.vers = unit->vers+pp->vers;
  631. qunlock(&unit->ctl);
  632. poperror();
  633. break;
  634. }
  635. decref(&sdev->r);
  636. return c;
  637. }
  638. static void
  639. sdclose(Chan* c)
  640. {
  641. SDunit *unit;
  642. SDev *sdev;
  643. if(c->qid.type & QTDIR)
  644. return;
  645. if(!(c->flag & COPEN))
  646. return;
  647. switch(TYPE(c->qid)){
  648. default:
  649. break;
  650. case Qraw:
  651. sdev = sdgetdev(DEV(c->qid));
  652. if(sdev){
  653. unit = sdev->unit[UNIT(c->qid)];
  654. unit->rawinuse = 0;
  655. decref(&sdev->r);
  656. }
  657. break;
  658. }
  659. }
  660. static int32_t
  661. sdbio(Chan* c, int write, char* a, int32_t len, int64_t off)
  662. {
  663. Proc *up = externup();
  664. int nchange;
  665. uint8_t *b;
  666. SDpart *pp;
  667. SDunit *unit;
  668. SDev *sdev;
  669. int64_t bno;
  670. int32_t l, max, nb, offset;
  671. sdev = sdgetdev(DEV(c->qid));
  672. if(sdev == nil){
  673. decref(&sdev->r);
  674. error(Enonexist);
  675. }
  676. unit = sdev->unit[UNIT(c->qid)];
  677. if(unit == nil)
  678. error(Enonexist);
  679. nchange = 0;
  680. qlock(&unit->ctl);
  681. while(waserror()){
  682. /* notification of media change; go around again */
  683. if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){
  684. sdinitpart(unit);
  685. continue;
  686. }
  687. /* other errors; give up */
  688. qunlock(&unit->ctl);
  689. decref(&sdev->r);
  690. nexterror();
  691. }
  692. pp = &unit->part[PART(c->qid)];
  693. if(unit->vers+pp->vers != c->qid.vers)
  694. error(Echange);
  695. /*
  696. * Check the request is within bounds.
  697. * Removeable drives are locked throughout the I/O
  698. * in case the media changes unexpectedly.
  699. * Non-removeable drives are not locked during the I/O
  700. * to allow the hardware to optimise if it can; this is
  701. * a little fast and loose.
  702. * It's assumed that non-removeable media parameters
  703. * (sectors, secsize) can't change once the drive has
  704. * been brought online.
  705. */
  706. bno = (off/unit->secsize) + pp->start;
  707. nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;
  708. max = SDmaxio/unit->secsize;
  709. if(nb > max)
  710. nb = max;
  711. if(bno+nb > pp->end)
  712. nb = pp->end - bno;
  713. if(bno >= pp->end || nb == 0){
  714. if(write)
  715. error(Eio);
  716. qunlock(&unit->ctl);
  717. decref(&sdev->r);
  718. poperror();
  719. return 0;
  720. }
  721. if(!(unit->inquiry[1] & SDinq1removable)){
  722. qunlock(&unit->ctl);
  723. poperror();
  724. }
  725. b = sdmalloc(nb*unit->secsize);
  726. if(b == nil)
  727. error(Enomem);
  728. if(waserror()){
  729. sdfree(b);
  730. if(!(unit->inquiry[1] & SDinq1removable))
  731. decref(&sdev->r); /* gadverdamme! */
  732. nexterror();
  733. }
  734. offset = off%unit->secsize;
  735. if(offset+len > nb*unit->secsize)
  736. len = nb*unit->secsize - offset;
  737. if(write){
  738. if(offset || (len%unit->secsize)){
  739. l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
  740. if(l < 0)
  741. error(Eio);
  742. if(l < (nb*unit->secsize)){
  743. nb = l/unit->secsize;
  744. l = nb*unit->secsize - offset;
  745. if(len > l)
  746. len = l;
  747. }
  748. }
  749. memmove(b+offset, a, len);
  750. l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);
  751. if(l < 0)
  752. error(Eio);
  753. if(l < offset)
  754. len = 0;
  755. else if(len > l - offset)
  756. len = l - offset;
  757. }
  758. else{
  759. l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);
  760. if(l < 0)
  761. error(Eio);
  762. if(l < offset)
  763. len = 0;
  764. else if(len > l - offset)
  765. len = l - offset;
  766. memmove(a, b+offset, len);
  767. }
  768. sdfree(b);
  769. poperror();
  770. if(unit->inquiry[1] & SDinq1removable){
  771. qunlock(&unit->ctl);
  772. poperror();
  773. }
  774. decref(&sdev->r);
  775. return len;
  776. }
  777. static int32_t
  778. sdrio(SDreq* r, void* a, int32_t n)
  779. {
  780. Proc *up = externup();
  781. void *data;
  782. if(n >= SDmaxio || n < 0)
  783. error(Etoobig);
  784. data = nil;
  785. if(n){
  786. if((data = sdmalloc(n)) == nil)
  787. error(Enomem);
  788. if(r->write)
  789. memmove(data, a, n);
  790. }
  791. r->data = data;
  792. r->dlen = n;
  793. if(waserror()){
  794. sdfree(data);
  795. r->data = nil;
  796. nexterror();
  797. }
  798. if(r->unit->dev->ifc->rio(r) != SDok)
  799. error(Eio);
  800. if(!r->write && r->rlen > 0)
  801. memmove(a, data, r->rlen);
  802. sdfree(data);
  803. r->data = nil;
  804. poperror();
  805. return r->rlen;
  806. }
  807. /*
  808. * SCSI simulation for non-SCSI devices
  809. */
  810. int
  811. sdsetsense(SDreq *r, int status, int key, int asc, int ascq)
  812. {
  813. int len;
  814. SDunit *unit;
  815. unit = r->unit;
  816. unit->sense[2] = key;
  817. unit->sense[12] = asc;
  818. unit->sense[13] = ascq;
  819. r->status = status;
  820. if(status == SDcheck && !(r->flags & SDnosense)){
  821. /* request sense case from sdfakescsi */
  822. len = sizeof unit->sense;
  823. if(len > sizeof r->sense-1)
  824. len = sizeof r->sense-1;
  825. memmove(r->sense, unit->sense, len);
  826. unit->sense[2] = 0;
  827. unit->sense[12] = 0;
  828. unit->sense[13] = 0;
  829. r->flags |= SDvalidsense;
  830. return SDok;
  831. }
  832. return status;
  833. }
  834. int
  835. sdmodesense(SDreq *r, uint8_t *cmd, void *info, int ilen)
  836. {
  837. int len;
  838. uint8_t *data;
  839. /*
  840. * Fake a vendor-specific request with page code 0,
  841. * return the drive info.
  842. */
  843. if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
  844. return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
  845. len = (cmd[7]<<8)|cmd[8];
  846. if(len == 0)
  847. return SDok;
  848. if(len < 8+ilen)
  849. return sdsetsense(r, SDcheck, 0x05, 0x1A, 0);
  850. if(r->data == nil || r->dlen < len)
  851. return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
  852. data = r->data;
  853. memset(data, 0, 8);
  854. data[0] = ilen>>8;
  855. data[1] = ilen;
  856. if(ilen)
  857. memmove(data+8, info, ilen);
  858. r->rlen = 8+ilen;
  859. return sdsetsense(r, SDok, 0, 0, 0);
  860. }
  861. int
  862. sdfakescsi(SDreq *r, void *info, int ilen)
  863. {
  864. uint8_t *cmd, *p;
  865. uint64_t len;
  866. SDunit *unit;
  867. cmd = r->cmd;
  868. r->rlen = 0;
  869. unit = r->unit;
  870. /*
  871. * Rewrite read(6)/write(6) into read(10)/write(10).
  872. */
  873. switch(cmd[0]){
  874. case 0x08: /* read */
  875. case 0x0A: /* write */
  876. cmd[9] = 0;
  877. cmd[8] = cmd[4];
  878. cmd[7] = 0;
  879. cmd[6] = 0;
  880. cmd[5] = cmd[3];
  881. cmd[4] = cmd[2];
  882. cmd[3] = cmd[1] & 0x0F;
  883. cmd[2] = 0;
  884. cmd[1] &= 0xE0;
  885. cmd[0] |= 0x20;
  886. break;
  887. }
  888. /*
  889. * Map SCSI commands into ATA commands for discs.
  890. * Fail any command with a LUN except INQUIRY which
  891. * will return 'logical unit not supported'.
  892. */
  893. if((cmd[1]>>5) && cmd[0] != 0x12)
  894. return sdsetsense(r, SDcheck, 0x05, 0x25, 0);
  895. switch(cmd[0]){
  896. default:
  897. return sdsetsense(r, SDcheck, 0x05, 0x20, 0);
  898. case 0x00: /* test unit ready */
  899. return sdsetsense(r, SDok, 0, 0, 0);
  900. case 0x03: /* request sense */
  901. if(cmd[4] < sizeof unit->sense)
  902. len = cmd[4];
  903. else
  904. len = sizeof unit->sense;
  905. if(r->data && r->dlen >= len){
  906. memmove(r->data, unit->sense, len);
  907. r->rlen = len;
  908. }
  909. return sdsetsense(r, SDok, 0, 0, 0);
  910. case 0x12: /* inquiry */
  911. if(cmd[4] < sizeof unit->inquiry)
  912. len = cmd[4];
  913. else
  914. len = sizeof unit->inquiry;
  915. if(r->data && r->dlen >= len){
  916. memmove(r->data, unit->inquiry, len);
  917. r->rlen = len;
  918. }
  919. return sdsetsense(r, SDok, 0, 0, 0);
  920. case 0x1B: /* start/stop unit */
  921. /*
  922. * nop for now, can use power management later.
  923. */
  924. return sdsetsense(r, SDok, 0, 0, 0);
  925. case 0x25: /* read capacity */
  926. if((cmd[1] & 0x01) || cmd[2] || cmd[3])
  927. return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
  928. if(r->data == nil || r->dlen < 8)
  929. return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
  930. /*
  931. * Read capacity returns the LBA of the last sector.
  932. */
  933. len = unit->sectors - 1;
  934. p = r->data;
  935. *p++ = len>>24;
  936. *p++ = len>>16;
  937. *p++ = len>>8;
  938. *p++ = len;
  939. len = 512;
  940. *p++ = len>>24;
  941. *p++ = len>>16;
  942. *p++ = len>>8;
  943. *p++ = len;
  944. r->rlen = p - (uint8_t*)r->data;
  945. return sdsetsense(r, SDok, 0, 0, 0);
  946. case 0x9E: /* long read capacity */
  947. if((cmd[1] & 0x01) || cmd[2] || cmd[3])
  948. return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
  949. if(r->data == nil || r->dlen < 8)
  950. return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
  951. /*
  952. * Read capcity returns the LBA of the last sector.
  953. */
  954. len = unit->sectors - 1;
  955. p = r->data;
  956. *p++ = len>>56;
  957. *p++ = len>>48;
  958. *p++ = len>>40;
  959. *p++ = len>>32;
  960. *p++ = len>>24;
  961. *p++ = len>>16;
  962. *p++ = len>>8;
  963. *p++ = len;
  964. len = 512;
  965. *p++ = len>>24;
  966. *p++ = len>>16;
  967. *p++ = len>>8;
  968. *p++ = len;
  969. r->rlen = p - (uint8_t*)r->data;
  970. return sdsetsense(r, SDok, 0, 0, 0);
  971. case 0x5A: /* mode sense */
  972. return sdmodesense(r, cmd, info, ilen);
  973. case 0x28: /* read */
  974. case 0x2A: /* write */
  975. case 0x88: /* read16 */
  976. case 0x8a: /* write16 */
  977. return SDnostatus;
  978. }
  979. }
  980. static int32_t
  981. sdread(Chan *c, void *a, int32_t n, int64_t off)
  982. {
  983. Proc *up = externup();
  984. char *p, *e, *buf;
  985. SDpart *pp;
  986. SDunit *unit;
  987. SDev *sdev;
  988. int32_t offset;
  989. int i, l, mm, status;
  990. offset = off;
  991. switch(TYPE(c->qid)){
  992. default:
  993. error(Eperm);
  994. case Qtopctl:
  995. mm = 64*1024; /* room for register dumps */
  996. p = buf = malloc(mm);
  997. if(p == nil)
  998. error(Enomem);
  999. e = p + mm;
  1000. qlock(&devslock);
  1001. for(i = 0; i < nelem(devs); i++){
  1002. sdev = devs[i];
  1003. if(sdev && sdev->ifc->rtopctl)
  1004. p = sdev->ifc->rtopctl(sdev, p, e);
  1005. }
  1006. qunlock(&devslock);
  1007. n = readstr(offset, a, n, buf);
  1008. free(buf);
  1009. return n;
  1010. case Qtopdir:
  1011. case Qunitdir:
  1012. return devdirread(c, a, n, 0, 0, sdgen);
  1013. case Qctl:
  1014. sdev = sdgetdev(DEV(c->qid));
  1015. if(sdev == nil)
  1016. error(Enonexist);
  1017. unit = sdev->unit[UNIT(c->qid)];
  1018. mm = 16*1024; /* room for register dumps */
  1019. p = malloc(mm);
  1020. if(p == nil)
  1021. error(Enomem);
  1022. l = snprint(p, mm, "inquiry %.48s\n",
  1023. (char*)unit->inquiry+8);
  1024. qlock(&unit->ctl);
  1025. /*
  1026. * If there's a device specific routine it must
  1027. * provide all information pertaining to night geometry
  1028. * and the garscadden trains.
  1029. */
  1030. if(unit->dev->ifc->rctl)
  1031. l += unit->dev->ifc->rctl(unit, p+l, mm-l);
  1032. if(unit->sectors == 0)
  1033. sdinitpart(unit);
  1034. if(unit->sectors){
  1035. if(unit->dev->ifc->rctl == nil)
  1036. l += snprint(p+l, mm-l,
  1037. "geometry %llu %lu\n",
  1038. unit->sectors, unit->secsize);
  1039. pp = unit->part;
  1040. for(i = 0; i < unit->npart; i++){
  1041. if(pp->valid)
  1042. l += snprint(p+l, mm-l,
  1043. "part %s %llu %llu\n",
  1044. pp->SDperm.name, pp->start, pp->end);
  1045. pp++;
  1046. }
  1047. }
  1048. qunlock(&unit->ctl);
  1049. decref(&sdev->r);
  1050. l = readstr(offset, a, n, p);
  1051. free(p);
  1052. return l;
  1053. case Qraw:
  1054. sdev = sdgetdev(DEV(c->qid));
  1055. if(sdev == nil)
  1056. error(Enonexist);
  1057. unit = sdev->unit[UNIT(c->qid)];
  1058. qlock(&unit->raw);
  1059. if(waserror()){
  1060. qunlock(&unit->raw);
  1061. decref(&sdev->r);
  1062. nexterror();
  1063. }
  1064. if(unit->state == Rawdata){
  1065. unit->state = Rawstatus;
  1066. i = sdrio(unit->req, a, n);
  1067. }
  1068. else if(unit->state == Rawstatus){
  1069. status = unit->req->status;
  1070. unit->state = Rawcmd;
  1071. free(unit->req);
  1072. unit->req = nil;
  1073. i = readnum(0, a, n, status, NUMSIZE);
  1074. } else
  1075. i = 0;
  1076. qunlock(&unit->raw);
  1077. decref(&sdev->r);
  1078. poperror();
  1079. return i;
  1080. case Qpart:
  1081. return sdbio(c, 0, a, n, off);
  1082. }
  1083. }
  1084. static void legacytopctl(Cmdbuf*);
  1085. static int32_t
  1086. sdwrite(Chan* c, void* a, int32_t n, int64_t off)
  1087. {
  1088. Proc *up = externup();
  1089. char *f0;
  1090. int i;
  1091. uint64_t end, start;
  1092. Cmdbuf *cb;
  1093. SDifc *ifc;
  1094. SDreq *req;
  1095. SDunit *unit;
  1096. SDev *sdev;
  1097. switch(TYPE(c->qid)){
  1098. default:
  1099. error(Eperm);
  1100. case Qtopctl:
  1101. cb = parsecmd(a, n);
  1102. if(waserror()){
  1103. free(cb);
  1104. nexterror();
  1105. }
  1106. if(cb->nf == 0)
  1107. error("empty control message");
  1108. f0 = cb->f[0];
  1109. cb->f++;
  1110. cb->nf--;
  1111. if(strcmp(f0, "config") == 0){
  1112. /* wormhole into ugly legacy interface */
  1113. legacytopctl(cb);
  1114. poperror();
  1115. free(cb);
  1116. break;
  1117. }
  1118. /*
  1119. * "ata arg..." invokes sdifc[i]->wtopctl(nil, cb),
  1120. * where sdifc[i]->SDperm.name=="ata" and cb contains the args.
  1121. */
  1122. ifc = nil;
  1123. sdev = nil;
  1124. for(i=0; sdifc[i]; i++){
  1125. if(strcmp(sdifc[i]->name, f0) == 0){
  1126. ifc = sdifc[i];
  1127. sdev = nil;
  1128. goto subtopctl;
  1129. }
  1130. }
  1131. /*
  1132. * "sd1 arg..." invokes sdifc[i]->wtopctl(sdev, cb),
  1133. * where sdifc[i] and sdev match controller letter "1",
  1134. * and cb contains the args.
  1135. */
  1136. if(f0[0]=='s' && f0[1]=='d' && f0[2] && f0[3] == 0){
  1137. if((sdev = sdgetdev(f0[2])) != nil){
  1138. ifc = sdev->ifc;
  1139. goto subtopctl;
  1140. }
  1141. }
  1142. error("unknown interface");
  1143. subtopctl:
  1144. if(waserror()){
  1145. if(sdev)
  1146. decref(&sdev->r);
  1147. nexterror();
  1148. }
  1149. if(ifc->wtopctl)
  1150. ifc->wtopctl(sdev, cb);
  1151. else
  1152. error(Ebadctl);
  1153. poperror();
  1154. poperror();
  1155. if (sdev)
  1156. decref(&sdev->r);
  1157. free(cb);
  1158. break;
  1159. case Qctl:
  1160. cb = parsecmd(a, n);
  1161. sdev = sdgetdev(DEV(c->qid));
  1162. if(sdev == nil)
  1163. error(Enonexist);
  1164. unit = sdev->unit[UNIT(c->qid)];
  1165. qlock(&unit->ctl);
  1166. if(waserror()){
  1167. qunlock(&unit->ctl);
  1168. decref(&sdev->r);
  1169. free(cb);
  1170. nexterror();
  1171. }
  1172. if(unit->vers != c->qid.vers)
  1173. error(Echange);
  1174. if(cb->nf < 1)
  1175. error(Ebadctl);
  1176. if(strcmp(cb->f[0], "part") == 0){
  1177. if(cb->nf != 4)
  1178. error(Ebadctl);
  1179. if(unit->sectors == 0 && !sdinitpart(unit))
  1180. error(Eio);
  1181. start = strtoull(cb->f[2], 0, 0);
  1182. end = strtoull(cb->f[3], 0, 0);
  1183. sdaddpart(unit, cb->f[1], start, end);
  1184. }
  1185. else if(strcmp(cb->f[0], "delpart") == 0){
  1186. if(cb->nf != 2 || unit->part == nil)
  1187. error(Ebadctl);
  1188. sddelpart(unit, cb->f[1]);
  1189. }
  1190. else if(unit->dev->ifc->wctl)
  1191. unit->dev->ifc->wctl(unit, cb);
  1192. else
  1193. error(Ebadctl);
  1194. qunlock(&unit->ctl);
  1195. decref(&sdev->r);
  1196. poperror();
  1197. free(cb);
  1198. break;
  1199. case Qraw:
  1200. sdev = sdgetdev(DEV(c->qid));
  1201. if(sdev == nil)
  1202. error(Enonexist);
  1203. unit = sdev->unit[UNIT(c->qid)];
  1204. qlock(&unit->raw);
  1205. if(waserror()){
  1206. qunlock(&unit->raw);
  1207. decref(&sdev->r);
  1208. nexterror();
  1209. }
  1210. switch(unit->state){
  1211. case Rawcmd:
  1212. if(n < 6 || n > sizeof(req->cmd))
  1213. error(Ebadarg);
  1214. if((req = malloc(sizeof(SDreq))) == nil)
  1215. error(Enomem);
  1216. req->unit = unit;
  1217. memmove(req->cmd, a, n);
  1218. req->clen = n;
  1219. req->flags = SDnosense;
  1220. req->status = ~0;
  1221. unit->req = req;
  1222. unit->state = Rawdata;
  1223. break;
  1224. case Rawstatus:
  1225. unit->state = Rawcmd;
  1226. free(unit->req);
  1227. unit->req = nil;
  1228. error(Ebadusefd);
  1229. case Rawdata:
  1230. unit->state = Rawstatus;
  1231. unit->req->write = 1;
  1232. n = sdrio(unit->req, a, n);
  1233. }
  1234. qunlock(&unit->raw);
  1235. decref(&sdev->r);
  1236. poperror();
  1237. break;
  1238. case Qpart:
  1239. return sdbio(c, 1, a, n, off);
  1240. }
  1241. return n;
  1242. }
  1243. static int32_t
  1244. sdwstat(Chan* c, uint8_t* dp, int32_t n)
  1245. {
  1246. Proc *up = externup();
  1247. Dir *d;
  1248. SDpart *pp;
  1249. SDperm *perm;
  1250. SDunit *unit;
  1251. SDev *sdev;
  1252. if(c->qid.type & QTDIR)
  1253. error(Eperm);
  1254. sdev = sdgetdev(DEV(c->qid));
  1255. if(sdev == nil)
  1256. error(Enonexist);
  1257. unit = sdev->unit[UNIT(c->qid)];
  1258. qlock(&unit->ctl);
  1259. d = nil;
  1260. if(waserror()){
  1261. free(d);
  1262. qunlock(&unit->ctl);
  1263. decref(&sdev->r);
  1264. nexterror();
  1265. }
  1266. switch(TYPE(c->qid)){
  1267. default:
  1268. error(Eperm);
  1269. case Qctl:
  1270. perm = &unit->ctlperm;
  1271. break;
  1272. case Qraw:
  1273. perm = &unit->rawperm;
  1274. break;
  1275. case Qpart:
  1276. pp = &unit->part[PART(c->qid)];
  1277. if(unit->vers+pp->vers != c->qid.vers)
  1278. error(Enonexist);
  1279. perm = &pp->SDperm;
  1280. break;
  1281. }
  1282. if(strcmp(up->user, perm->user) && !iseve())
  1283. error(Eperm);
  1284. d = smalloc(sizeof(Dir)+n);
  1285. n = convM2D(dp, n, &d[0], (char*)&d[1]);
  1286. if(n == 0)
  1287. error(Eshortstat);
  1288. if(!emptystr(d[0].uid))
  1289. kstrdup(&perm->user, d[0].uid);
  1290. if(d[0].mode != (uint32_t)~0UL)
  1291. perm->perm = (perm->perm & ~0777) | (d[0].mode & 0777);
  1292. free(d);
  1293. qunlock(&unit->ctl);
  1294. decref(&sdev->r);
  1295. poperror();
  1296. return n;
  1297. }
  1298. static int
  1299. configure(char* spec, DevConf* cf)
  1300. {
  1301. SDev *s, *sdev;
  1302. char *p;
  1303. int i;
  1304. if(sdindex(*spec) < 0)
  1305. error("bad sd spec");
  1306. if((p = strchr(cf->type, '/')) != nil)
  1307. *p++ = '\0';
  1308. for(i = 0; sdifc[i] != nil; i++)
  1309. if(strcmp(sdifc[i]->name, cf->type) == 0)
  1310. break;
  1311. if(sdifc[i] == nil)
  1312. error("sd type not found");
  1313. if(p)
  1314. *(p-1) = '/';
  1315. if(sdifc[i]->probe == nil)
  1316. error("sd type cannot probe");
  1317. sdev = sdifc[i]->probe(cf);
  1318. for(s=sdev; s; s=s->next)
  1319. s->idno = *spec;
  1320. sdadddevs(sdev);
  1321. return 0;
  1322. }
  1323. static int
  1324. unconfigure(char* spec)
  1325. {
  1326. int i;
  1327. SDev *sdev;
  1328. SDunit *unit;
  1329. if((i = sdindex(*spec)) < 0)
  1330. error(Enonexist);
  1331. qlock(&devslock);
  1332. if((sdev = devs[i]) == nil){
  1333. qunlock(&devslock);
  1334. error(Enonexist);
  1335. }
  1336. if(sdev->r.ref){
  1337. qunlock(&devslock);
  1338. error(Einuse);
  1339. }
  1340. devs[i] = nil;
  1341. qunlock(&devslock);
  1342. /* make sure no interrupts arrive anymore before removing resources */
  1343. if(sdev->enabled && sdev->ifc->disable)
  1344. sdev->ifc->disable(sdev);
  1345. for(i = 0; i != sdev->nunit; i++){
  1346. if(unit = sdev->unit[i]){
  1347. free(unit->SDperm.name);
  1348. free(unit->SDperm.user);
  1349. free(unit);
  1350. }
  1351. }
  1352. if(sdev->ifc->clear)
  1353. sdev->ifc->clear(sdev);
  1354. free(sdev);
  1355. return 0;
  1356. }
  1357. static int
  1358. sdconfig(int on, char* spec, DevConf* cf)
  1359. {
  1360. if(on)
  1361. return configure(spec, cf);
  1362. return unconfigure(spec);
  1363. }
  1364. Dev sddevtab = {
  1365. .dc = 'S',
  1366. .name = "sd",
  1367. .reset = sdreset,
  1368. .init = devinit,
  1369. .shutdown = devshutdown,
  1370. .attach = sdattach,
  1371. .walk = sdwalk,
  1372. .stat = sdstat,
  1373. .open = sdopen,
  1374. .create = devcreate,
  1375. .close = sdclose,
  1376. .read = sdread,
  1377. .bread = devbread,
  1378. .write = sdwrite,
  1379. .bwrite = devbwrite,
  1380. .remove = devremove,
  1381. .wstat = sdwstat,
  1382. .power = devpower,
  1383. .config = sdconfig, /* probe; only called for pcmcia-like devices */
  1384. };
  1385. /*
  1386. * This is wrong for so many reasons. This code must go.
  1387. */
  1388. typedef struct Confdata Confdata;
  1389. struct Confdata {
  1390. int on;
  1391. char* spec;
  1392. DevConf cf;
  1393. };
  1394. static void
  1395. parseswitch(Confdata* cd, char* option)
  1396. {
  1397. if(!strcmp("on", option))
  1398. cd->on = 1;
  1399. else if(!strcmp("off", option))
  1400. cd->on = 0;
  1401. else
  1402. error(Ebadarg);
  1403. }
  1404. static void
  1405. parsespec(Confdata* cd, char* option)
  1406. {
  1407. if(strlen(option) > 1)
  1408. error(Ebadarg);
  1409. cd->spec = option;
  1410. }
  1411. static Devport*
  1412. getnewport(DevConf* dc)
  1413. {
  1414. Devport *p;
  1415. p = (Devport *)malloc((dc->nports + 1) * sizeof(Devport));
  1416. if(p == nil)
  1417. error(Enomem);
  1418. if(dc->nports > 0){
  1419. memmove(p, dc->ports, dc->nports * sizeof(Devport));
  1420. free(dc->ports);
  1421. }
  1422. dc->ports = p;
  1423. p = &dc->ports[dc->nports++];
  1424. p->size = -1;
  1425. p->port = (uint32_t)-1;
  1426. return p;
  1427. }
  1428. static void
  1429. parseport(Confdata* cd, char* option)
  1430. {
  1431. char *e;
  1432. Devport *p;
  1433. if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].port != (uint32_t)-1)
  1434. p = getnewport(&cd->cf);
  1435. else
  1436. p = &cd->cf.ports[cd->cf.nports-1];
  1437. p->port = strtol(option, &e, 0);
  1438. if(e == nil || *e != '\0')
  1439. error(Ebadarg);
  1440. }
  1441. static void
  1442. parsesize(Confdata* cd, char* option)
  1443. {
  1444. char *e;
  1445. Devport *p;
  1446. if(cd->cf.nports == 0 || cd->cf.ports[cd->cf.nports-1].size != -1)
  1447. p = getnewport(&cd->cf);
  1448. else
  1449. p = &cd->cf.ports[cd->cf.nports-1];
  1450. p->size = (int)strtol(option, &e, 0);
  1451. if(e == nil || *e != '\0')
  1452. error(Ebadarg);
  1453. }
  1454. static void
  1455. parseirq(Confdata* cd, char* option)
  1456. {
  1457. char *e;
  1458. cd->cf.intnum = strtoul(option, &e, 0);
  1459. if(e == nil || *e != '\0')
  1460. error(Ebadarg);
  1461. }
  1462. static void
  1463. parsetype(Confdata* cd, char* option)
  1464. {
  1465. cd->cf.type = option;
  1466. }
  1467. static struct {
  1468. char *name;
  1469. void (*parse)(Confdata*, char*);
  1470. } options[] = {
  1471. "switch", parseswitch,
  1472. "spec", parsespec,
  1473. "port", parseport,
  1474. "size", parsesize,
  1475. "irq", parseirq,
  1476. "type", parsetype,
  1477. };
  1478. static void
  1479. legacytopctl(Cmdbuf *cb)
  1480. {
  1481. char *opt;
  1482. int i, j;
  1483. Confdata cd;
  1484. memset(&cd, 0, sizeof cd);
  1485. cd.on = -1;
  1486. for(i=0; i<cb->nf; i+=2){
  1487. if(i+2 > cb->nf)
  1488. error(Ebadarg);
  1489. opt = cb->f[i];
  1490. for(j=0; j<nelem(options); j++)
  1491. if(strcmp(opt, options[j].name) == 0){
  1492. options[j].parse(&cd, cb->f[i+1]);
  1493. break;
  1494. }
  1495. if(j == nelem(options))
  1496. error(Ebadarg);
  1497. }
  1498. /* this has been rewritten to accomodate sdaoe */
  1499. if(cd.on < 0 || cd.spec == 0)
  1500. error(Ebadarg);
  1501. if(cd.on && cd.cf.type == nil)
  1502. error(Ebadarg);
  1503. sdconfig(cd.on, cd.spec, &cd.cf);
  1504. }