this sidebar in the sd stuff should be retired by now, but it's not. so make sure that it handles 64-bit lbas. Reference: /n/atom/patch/applied/nixscsi64bitlba Date: Thu Mar 27 05:43:22 CET 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/port/devsd.c Thu Mar 27 05:42:38 2014 +++ /sys/src/nix/port/devsd.c Thu Mar 27 05:42:39 2014 @@ -524,7 +524,7 @@ case Qtopdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); + snprint(up->genbuf, sizeof up->genbuf, "#%C", sddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } @@ -572,7 +572,7 @@ case Qunitdir: if(s == DEVDOTDOT){ mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR); - sprint(up->genbuf, "#%C", sddevtab.dc); + snprint(up->genbuf, sizeof up->genbuf, "#%C", sddevtab.dc); devdir(c, q, up->genbuf, 0, eve, 0555, dp); return 1; } --- /sys/src/nix/port/sdscsi.c Thu Mar 27 05:42:41 2014 +++ /sys/src/nix/port/sdscsi.c Thu Mar 27 05:42:42 2014 @@ -113,6 +113,74 @@ return 0; } +static void +cap10(SDreq *r) +{ + r->cmd[0] = 0x25; + r->cmd[1] = r->lun<<5; + r->clen = 10; + r->dlen = 8; +} + +static void +cap16(SDreq *r) +{ + uint i; + + i = 32; + r->cmd[0] = 0x9e; + r->cmd[1] = 0x10; + r->cmd[10] = i>>24; + r->cmd[11] = i>>16; + r->cmd[12] = i>>8; + r->cmd[13] = i; + r->clen = 16; + r->dlen = i; +} + +static uint +belong(uchar *u) +{ + return u[0]<<24 | u[1]<<16 | u[2]<<8 | u[3]; +} + +static uvlong +capreply(SDreq *r, ulong *secsize) +{ + uchar *u; + ulong ss; + uvlong s; + + *secsize = 0; + u = r->data; + if(r->clen == 16){ + s = (uvlong)belong(u)<<32 | belong(u + 4); + ss = belong(u + 8); + }else{ + s = belong(u); + ss = belong(u + 4); + } + /* + * Some ATAPI CD readers lie about the block size. + * Since we don't read audio via this interface + * it's okay to always fudge this. + */ + if(ss == 2352) + ss = 2048; + /* + * Devices with removable media may return 0 sectors + * when they have empty media (e.g. sata dvd writers); + * if so, keep the count zero. + * + * Read-capacity returns the LBA of the last sector, + * therefore the number of sectors must be incremented. + */ + if(s != 0) + s++; + *secsize = ss; + return s; +} + static int scsirio(SDreq* r) { @@ -151,7 +219,8 @@ /* * If no medium present, bail out. * If unit is becoming ready, rather than not - * not ready, wait a little then poke it again. */ + * not ready, wait a little then poke it again. + */ if(r->sense[12] == 0x3A) break; if(r->sense[12] != 0x04 || r->sense[13] != 0x01) @@ -179,16 +248,17 @@ SDreq *r; uchar *p; int ok, retries; + void (*cap)(SDreq*); - if((r = malloc(sizeof(SDreq))) == nil) + if((r = malloc(sizeof *r)) == nil) return 0; - if((p = sdmalloc(8)) == nil){ + if((p = sdmalloc(32)) == nil){ free(r); return 0; } ok = 0; - + cap = cap10; r->unit = unit; r->lun = 0; /* ??? */ for(retries = 0; retries < 10; retries++){ @@ -199,39 +269,21 @@ * plain slow getting their act together after a reset. */ r->write = 0; - memset(r->cmd, 0, sizeof(r->cmd)); - r->cmd[0] = 0x25; - r->cmd[1] = r->lun<<5; - r->clen = 10; r->data = p; - r->dlen = 8; r->flags = 0; + memset(r->cmd, 0, sizeof r->cmd); + cap(r); r->status = ~0; switch(scsirio(r)){ default: break; case 0: - unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; - unit->secsize = (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7]; - - /* - * Some ATAPI CD readers lie about the block size. - * Since we don't read audio via this interface - * it's okay to always fudge this. - */ - if(unit->secsize == 2352) - unit->secsize = 2048; - /* - * Devices with removable media may return 0 sectors - * when they have empty media (e.g. sata dvd writers); - * if so, keep the count zero. - * - * Read-capacity returns the LBA of the last sector, - * therefore the number of sectors must be incremented. - */ - if(unit->sectors != 0) - unit->sectors++; + unit->sectors = capreply(r, &unit->secsize); + if(unit->sectors == 0xffffffff && cap == cap10){ + cap = cap16; + continue; + } ok = 1; break; case 1: