2 #include "../port/lib.h"
8 #include "../port/error.h"
10 #include "../port/sd.h"
15 typedef struct Ctlr Ctlr;
61 u32int mps; /* mps = 1<<mpsshift */
71 /* controller registers */
92 qcmd(WS *ws, Ctlr *ctlr, int adm, u32int opc, u32int nsid, void *mptr, void *data, ulong len)
101 sq = &ctlr->sq[1+m->machno];
106 ws->sleep = &up->sleep;
108 ws->link = &sq->wait[sq->tail & sq->mask];
109 while(*ws->link != nil){
112 /* should be very rare */
118 e = &sq->base[((cid = sq->tail++) & sq->mask)<<4];
119 e[0] = opc | cid<<16;
135 if(len > ctlr->mps - (pa & ctlr->mps-1))
136 pa += ctlr->mps - (pa & ctlr->mps-1);
150 nvmeintr(Ureg *, void *arg)
152 u32int phaseshift, *e;
163 ctlr->reg[IntMs] = ctlr->ints;
164 for(cq = &ctlr->cq[nelem(ctlr->cq)-1]; cq >= ctlr->cq; cq--){
167 phaseshift = 16 - cq->shift;
169 e = &cq->base[(cq->head & cq->mask)<<2];
170 if(((e[3] ^ (cq->head << phaseshift)) & 0x10000) == 0)
173 if(0) iprint("nvmeintr: cq%d [%.4ux] %.8ux %.8ux %.8ux %.8ux\n",
174 (int)(cq - ctlr->cq), cq->head & cq->mask,
175 e[0], e[1], e[2], e[3]);
177 sq = &ctlr->sq[e[2] >> 16];
178 wp = &sq->wait[e[3] & sq->mask];
179 if((ws = *wp) != nil && ws->link == wp){
180 Rendez *z = ws->sleep;
182 ws->status = e[3]>>17;
186 ctlr->reg[DBell + ((cq-ctlr->cq)*2+1 << ctlr->dstrd)] = ++cq->head & cq->mask;
189 ctlr->reg[IntMc] = ctlr->ints;
190 iunlock(&ctlr->intr);
197 return *ws->link != ws;
204 Ctlr *ctlr = sq->ctlr;
207 ctlr->reg[DBell + ((sq-ctlr->sq)*2+0 << ctlr->dstrd)] = sq->tail & sq->mask;
209 assert(sq == &ctlr->sq[1+m->machno]);
215 tsleep(ws->sleep, wdone, ws, 5);
218 tsleep(ws->sleep, wdone, ws, 10);
225 checkstatus(u32int status, char *info)
229 snprint(up->genbuf, sizeof(up->genbuf), "%s: status %ux", info, status);
234 nvmebio(SDunit *u, int lun, int write, void *a, long count, uvlong lba)
236 u32int nsid, s, n, m, *e;
244 nsid = ctlr->nsid[u->subno];
248 m = (2*ctlr->mps - ((uintptr)p & ctlr->mps-1)) / s;
251 e = qcmd(&ws, ctlr, 0, write ? 0x01 : 0x02, nsid, nil, p, n*s);
255 e[13] = (count>n)<<6; /* sequential request */
258 checkstatus(wcmd(&ws), write ? "write" : "read");
263 return p - (uchar*)a;
274 if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91)
275 return sdsetsense(r, SDok, 0, 0, 0);
276 if((i = sdfakescsi(r)) != SDnostatus)
277 return r->status = i;
278 if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
280 r->rlen = nvmebio(u, r->lun, rw == SDwrite, r->data, count, lba);
281 return r->status = SDok;
285 nvmeverify(SDunit *u)
287 Ctlr *ctlr = u->dev->ctlr;
288 return u->subno < ctlr->nnsid;
292 nvmeonline(SDunit *u)
303 if((info = mallocalign(0x1000, ctlr->mps, 0, 0)) == nil)
306 e = qcmd(&ws, ctlr, 1, 0x06, ctlr->nsid[u->subno], nil, info, 0x1000);
307 e[10] = 0; // identify namespace
313 u->sectors = p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24
318 p = &info[128 + 4*(info[26]&15)];
319 lbaf = p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24;
320 u->secsize = 1<<((lbaf>>16)&0xFF);
323 memset(u->inquiry, 0, sizeof u->inquiry);
326 u->inquiry[4] = sizeof u->inquiry - 4;
327 memmove(u->inquiry+8, ctlr->ident+24, 20);
333 nvmerctl(SDunit *u, char *p, int l)
338 if((ctlr = u->dev->ctlr) == nil || ctlr->ident == nil)
344 p = seprint(p, e, "model\t%.20s\n", (char*)ctlr->ident+24);
345 p = seprint(p, e, "serial\t%.10s\n", (char*)ctlr->ident+4);
346 p = seprint(p, e, "firm\t%.6s\n", (char*)ctlr->ident+64);
347 p = seprint(p, e, "geometry %llud %lud\n", u->sectors, u->secsize);
353 cqalloc(Ctlr *ctlr, CQ *cq, u32int lgsize)
357 cq->shift = lgsize-4;
358 cq->mask = (1<<cq->shift)-1;
359 if((cq->base = mallocalign(1<<lgsize, ctlr->mps, 0, 0)) == nil)
361 memset(cq->base, 0, 1<<lgsize);
366 sqalloc(Ctlr *ctlr, SQ *sq, u32int lgsize)
370 sq->shift = lgsize-6;
371 sq->mask = (1<<sq->shift)-1;
372 if((sq->base = mallocalign(1<<lgsize, ctlr->mps, 0, 0)) == nil)
374 if((sq->wait = mallocz(sizeof(WS*)*(sq->mask+1), 1)) == nil)
376 memset(sq->base, 0, 1<<lgsize);
381 setupqueues(Ctlr *ctlr)
391 while(lgsize < 16+4 && lgsize < ctlr->mpsshift && 1<<lgsize < conf.nmach<<12-6+4)
394 /* CQID1: shared completion queue */
396 cqalloc(ctlr, cq, lgsize);
397 e = qcmd(&ws, ctlr, 1, 0x05, 0, nil, cq->base, 1<<lgsize);
398 e[10] = (cq - ctlr->cq) | cq->mask<<16;
399 e[11] = 3; /* IEN | PC */
400 checkstatus(wcmd(&ws), "create completion queue");
402 /* SQID[1..nmach]: submission queue per cpu */
403 for(i=1; i<=conf.nmach; i++){
405 sqalloc(ctlr, sq, 12);
406 e = qcmd(&ws, ctlr, 1, 0x01, 0, nil, sq->base, 0x1000);
407 e[10] = i | sq->mask<<16;
408 e[11] = (cq - ctlr->cq)<<16 | 1; /* CQID<<16 | PC */
409 checkstatus(wcmd(&ws), "create submission queue");
413 ctlr->ints |= 1<<(cq - ctlr->cq);
414 ctlr->reg[IntMc] = ctlr->ints;
415 iunlock(&ctlr->intr);
424 if(ctlr->ident == nil)
425 if((ctlr->ident = mallocalign(0x1000, ctlr->mps, 0, 0)) == nil)
427 if(ctlr->nsid == nil)
428 if((ctlr->nsid = mallocalign(0x1000, ctlr->mps, 0, 0)) == nil)
431 e = qcmd(&ws, ctlr, 1, 0x06, 0, nil, ctlr->ident, 0x1000);
432 e[10] = 1; // identify controller
433 checkstatus(wcmd(&ws), "identify controller");
435 e = qcmd(&ws, ctlr, 1, 0x06, 0, nil, ctlr->nsid, 0x1000);
436 e[10] = 2; // namespace list
437 checkstatus(wcmd(&ws), "namespace list");
440 while(ctlr->nnsid < 1024 && ctlr->nsid[ctlr->nnsid] != 0)
445 nvmedisable(SDev *sd)
453 /* mask interrupts */
456 ctlr->reg[IntMs] = ~ctlr->ints;
457 iunlock(&ctlr->intr);
459 /* disable controller */
462 for(i = 0; i < 10; i++){
463 if((ctlr->reg[CSts] & 1) == 0)
465 tsleep(&up->sleep, return0, nil, 100);
468 snprint(name, sizeof(name), "%s (%s)", sd->name, sd->ifc->name);
469 intrdisable(ctlr->pci->intl, nvmeintr, ctlr, ctlr->pci->tbdf, name);
471 pciclrbme(ctlr->pci); /* dma disable */
473 for(i=0; i<nelem(ctlr->sq); i++){
474 free(ctlr->sq[i].base);
475 free(ctlr->sq[i].wait);
477 for(i=0; i<nelem(ctlr->cq); i++)
478 free(ctlr->cq[i].base);
480 memset(ctlr->sq, 0, sizeof(ctlr->sq));
481 memset(ctlr->cq, 0, sizeof(ctlr->cq));
502 snprint(name, sizeof(name), "%s (%s)", sd->name, sd->ifc->name);
503 intrenable(ctlr->pci->intl, nvmeintr, ctlr, ctlr->pci->tbdf, name);
506 print("%s: %s\n", name, up->errstr);
508 sd->nunit = 0; /* hack: prevent further probing */
512 pa = PADDR(cqalloc(ctlr, &ctlr->cq[0], ctlr->mpsshift));
513 ctlr->reg[ACQBase0] = pa;
514 ctlr->reg[ACQBase1] = pa>>32;
516 pa = PADDR(sqalloc(ctlr, &ctlr->sq[0], ctlr->mpsshift));
517 ctlr->reg[ASQBase0] = pa;
518 ctlr->reg[ASQBase1] = pa>>32;
520 ctlr->reg[AQAttr] = ctlr->sq[0].mask | ctlr->cq[0].mask<<16;
523 pcisetbme(ctlr->pci);
525 /* enable interrupt */
528 ctlr->reg[IntMc] = ctlr->ints;
529 iunlock(&ctlr->intr);
531 /* enable controller */
532 ctlr->reg[CCfg] = 1 | (ctlr->mpsshift-12)<<7 | 6<<16 | 4<<20;
534 for(to = (ctlr->cap>>24) & 255; to >= 0; to--){
535 tsleep(&up->sleep, return0, nil, 500);
536 if((ctlr->reg[CSts] & 3) == 1)
539 if(ctlr->reg[CSts] & 2)
540 error("fatal controller status during initialization");
541 error("controller initialization timeout");
559 for(p = nil; p = pcimatch(p, 0, 0);){
560 if(p->ccrb != 1 || p->ccru != 8 || p->ccrp != 2)
562 if(p->mem[0].size == 0)
564 if((ctlr = malloc(sizeof(*ctlr))) == nil){
565 print("nvme: no memory for Ctlr\n");
569 ctlr->reg = vmap(p->mem[0].bar & ~0xF, p->mem[0].size);
570 if(ctlr->reg == nil){
571 print("nvme: can't vmap bar0\n");
574 vunmap(ctlr->reg, p->mem[0].size);
578 ctlr->cap = ctlr->reg[Cap0];
579 ctlr->cap |= (u64int)ctlr->reg[Cap1]<<32;
581 /* mask interrupts */
583 ctlr->reg[IntMs] = ~ctlr->ints;
585 /* disable controller */
588 if((ctlr->cap&(1ULL<<37)) == 0){
589 print("nvme: doesnt support NVM commactlr set: %ux\n",
590 (u32int)(ctlr->cap>>37) & 0xFF);
594 /* use 64K page size when possible */
595 ctlr->dstrd = (ctlr->cap >> 32) & 15;
596 for(i = (ctlr->cap >> 48) & 15; i < ((ctlr->cap >> 52) & 15); i++){
597 if(i >= 16-12) /* 64K */
600 ctlr->mpsshift = i+12;
601 ctlr->mps = 1 << ctlr->mpsshift;
625 for(ctlr = nvmepnpctlrs(); ctlr != nil; ctlr = ctlr->next){
626 if((s = malloc(sizeof(*s))) == nil)
647 nvmeenable, /* enable */
648 nvmedisable, /* disable */
650 nvmeverify, /* verify */
651 nvmeonline, /* online */