static int setcaching(Drive *drive) { int n; uint8_t buf[Pagesz]; /* * we can't actually control caching much. * see SBC-2 §6.3.3 but also MMC-6 §7.6. * * should set read ahead, MMC-6 §6.37; seems to control caching. */ n = mmcgetpage(drive, Pagcache, buf); if (n < 3) return -1; /* n == 255; buf[1] == 10 (10 bytes after buf[1]) */ buf[0] &= 077; /* clear reserved bits, MMC-6 §7.2.3 */ assert(buf[0] == Pagcache); assert(buf[1] >= 10); buf[2] = Ccwce; if (mmcsetpage(drive, Pagcache, buf) < 0) { if (vflag) print("mmcprobe: cache control NOT set\n"); return -1; } return 0; }
/* * set read-write error recovery mode page 1 (10 bytes), mmc-6 §7.3. * * requires defect management feature (0x24) mmc-6 §5.3.13 (mandatory on bd, * but has to be enabled by allocating spares with FORMAT UNIT command) * or enhanced defect reporting feature (0x29) mmc-6 §5.3.17, * and they are mutually exclusive. */ static int seterrrecov(Drive *drive) { int n; uint8_t buf[Pagesz]; if (!isbitset(Featdfctmgmt, drive->features) && !isbitset(Featedfctrpt, drive->features)) { fprint(2, "defect mgmt. and enhanced defect reporting disabled!\n"); return -1; } n = mmcgetpage(drive, Pagerrrecov, buf); if (n < 3) return -1; /* n == 255; buf[1] == 10 (10 bytes after buf[1]) */ /* * error recovery page as read: * 0: 01 (page: error recovery) * 1: 0a (length: 10) * 2: c0 (error control bits: 0300 == Erawre|Erarre) * 3: 20 (read retry count: 32) * 4: 00 * 5: 00 * 6: 00 * 7: 00 * 8: 01 (write retry count: 1) * 9: 00 00 00 (error reporting window size) */ buf[0] &= ~(1<<6); /* clear reserved bit */ assert((buf[0] & 077) == Pagerrrecov); assert(buf[1] >= 10); buf[2] = Erawre | Erarre; /* default: Erawre; can't set Ertb */ if (isbitset(Featedfctrpt, drive->features)) buf[7] = 1; /* emcdr: 1==recover, don't tell us; default 0 */ // buf[3] = 32; /* rd retry count; default 32; arbitrary */ // buf[8] = 1; /* wr retry count; default 1; arbitrary */ // memset(buf+9, 0, 3); /* err reporting win siz: 0 == no tsr; default 0 */ if (mmcsetpage(drive, Pagerrrecov, buf) < 0) { if (vflag) fprint(2, "error recovery NOT set\n"); return -1; } if (vflag) fprint(2, "error recovery set\n"); return 0; }
/* * this uses page 5, which is optional. */ static int mmcsetbs(Drive *drive, int bs) { uchar *p; Mmcaux *aux; aux = drive->aux; if (!aux->page05ok) return 0; /* harmless; assume 2k */ p = aux->page05; /* * establish defaults. */ p[0] &= 077; /* clear reserved bits, MMC-6 §7.2.3 */ p[Wpwrtype] = Bufe | Wttrackonce; // if(testonlyflag) // p[Wpwrtype] |= 0x10; /* test-write */ /* assume dvd values as defaults */ settrkmode(p, Tmintr); p[Wptrkmode] |= Msnext; p[Wpdatblktype] = Db2kdata; p[Wpsessfmt] = Sfdata; switch(drive->mmctype) { case Mmcdvdplus: case Mmcbd: break; case Mmcdvdminus: /* dvd-r can only do disc-at-once or incremental */ p[Wpwrtype] = Bufe | Wtsessonce; break; case Mmccd: settrkmode(p, Tmunintr); /* data track, uninterrupted */ switch(bs){ case BScdda: /* 2 audio channels without pre-emphasis */ settrkmode(p, Tmcdda); /* TODO: should be Tm2audio? */ p[Wpdatblktype] = Dbraw; break; case BScdrom: break; case BScdxa: p[Wpdatblktype] = Db2336; p[Wpsessfmt] = Sfcdxa; break; default: fprint(2, "%s: unknown CD type; bs %d\n", argv0, bs); assert(0); } break; default: fprint(2, "%s: unknown disc sub-type %d\n", argv0, drive->mmctype); break; } if(mmcsetpage(drive, Pagwrparams, p) < 0) { if (vflag) fprint(2, "mmcsetbs: could NOT set write parameters page\n"); return -1; } return 0; }
Drive* mmcprobe(Scsi *scsi) { Mmcaux *aux; Drive *drive; uchar buf[Pagesz]; int cap, n; if (vflag) print("mmcprobe: inquiry: %s\n", scsi->inquire); drive = emalloc(sizeof(Drive)); drive->Scsi = *scsi; drive->Dev = mmcdev; aux = emalloc(sizeof(Mmcaux)); drive->aux = aux; scsiready(drive); drive->type = getdevtype(drive); if (drive->type != TypeCD) { werrstr("not an mmc device"); free(aux); free(drive); return nil; } /* * drive is an mmc device; learn what we can about it * (as opposed to the disc in it). */ start(drive, 1); /* attempt to read CD capabilities page, but it's now legacy */ if(mmcgetpage10(drive, Pagcapmechsts, buf) >= 0) aux->pagecmdsz = 10; else if(mmcgetpage6(drive, Pagcapmechsts, buf) >= 0) aux->pagecmdsz = 6; else { if (vflag) fprint(2, "no Pagcapmechsts mode page!\n"); werrstr("can't read mode page %d!", Pagcapmechsts); free(aux); free(drive); return nil; } cap = 0; if(buf[Capwrite] & (Capcdr|Capcdrw|Capdvdr|Capdvdram) || buf[Capmisc] & Caprw) cap |= Cwrite; if(buf[Capmisc] & Capcdda) /* CD-DA commands supported? */ cap |= Ccdda; /* not used anywhere else */ // print("read %d max %d\n", biges(buf+14), biges(buf+8)); // print("write %d max %d\n", biges(buf+20), biges(buf+18)); /* cache optional page 05 (write parameter page) */ if(/* (cap & Cwrite) && */ mmcgetpage(drive, Pagwrparams, aux->page05) >= 0) { aux->page05ok = 1; cap |= Cwrite; if (vflag) fprint(2, "mmcprobe: got page 5, assuming drive can write\n"); } else { if (vflag) fprint(2, "no Pagwrparams mode page!\n"); cap &= ~Cwrite; } drive->cap = cap; mmcgetspeed(drive); /* * we can't actually control caching much. * see SBC-2 §6.3.3 but also MMC-6 §7.6. */ n = mmcgetpage(drive, Pagcache, buf); if (n >= 3) { /* n == 255; buf[1] == 10 (10 bytes after buf[1]) */ buf[0] &= 077; /* clear reserved bits, MMC-6 §7.2.3 */ assert(buf[0] == Pagcache); assert(buf[1] >= 10); buf[2] = Ccwce; if (mmcsetpage(drive, Pagcache, buf) < 0) if (vflag) print("mmcprobe: cache control NOT set\n"); } return drive; }