enum { Maxtrack = 200, Ntrack = Maxtrack+1, BScdrom = 2048, /* mmc data block size */ BScdda = 2352, BScdxa = 2336, BSmax = 2352, Maxfeatures = 512, /* scsi peripheral device types, SPC-3 §6.4.2 */ TypeDA = 0, /* Direct Access (SBC) */ TypeSA = 1, /* Sequential Access (SSC) */ TypeWO = 4, /* Worm (SBC)*/ TypeCD = 5, /* CD/DVD/BD (MMC) */ TypeMO = 7, /* rewriteable Magneto-Optical (SBC) */ TypeMC = 8, /* Medium Changer (SMC) */ /* MMC device types */ Mmcnone = 0, Mmccd, Mmcdvdminus, Mmcdvdplus, Mmcbd, /* disc or track types */ TypeNone = 0, TypeAudio, TypeAwritable, TypeData, TypeDwritable, TypeDisk, TypeBlank, /* disc writability classes */ Readonly = 0, /* -ROM */ Write1, /* -R: write once only */ Erasewrite, /* -R[WE]: erase then write */ Ram, /* -RAM: read & write unrestricted */ /* tri-state flags */ Unset = -1, No, Yes, /* offsets in Pagcapmechsts mode page; see MMC-3 §5.5.10 */ Capread = 2, Capwrite = 3, Capmisc = 5, /* device capabilities in Pagcapmechsts mode page */ Capcdr = 1<<0, /* bytes 2 & 3 */ Capcdrw = 1<<1, Captestwr = 1<<2, Capdvdrom = 1<<3, Capdvdr = 1<<4, Capdvdram = 1<<5, Capcdda = 1<<0, /* Capmisc bits */ Caprw = 1<<2, /* Pagwrparams mode page offsets */ Wpwrtype = 2, /* write type */ Wptrkmode, /* track mode */ Wpdatblktype, Wpsessfmt = 8, Wppktsz = 10, /* BE ulong: # user data blks/fixed pkt */ /* Pagwrparams bits */ Bufe = 1<<6, /* Wpwrtype: buffer under-run free recording enable */ /* Wptrkmode */ Msbits = 3<<6, /* multisession field */ Msnonext= 0<<6, /* no next border nor session */ Mscdnonext= 1<<6, /* cd special: no next session */ Msnext = 3<<6, /* next session or border allowed */ Fp = 1<<5, /* pay attention to Wppktsz */ /* close track session cdb bits */ Closetrack = 1, Closesessfinal = 2, /* close session / finalize disc */ Closefinaldvdrw = 3, /* dvd-rw special: finalize */ /* dvd+r dl special: close session, write extended lead-out */ Closesessextdvdrdl = 4, Closefinal30mm = 5, /* dvd+r special: finalize with ≥30mm radius */ Closedvdrbdfinal= 6, /* dvd+r, bd-r special: finalize */ /* read toc format values */ Tocfmttoc = 0, Tocfmtsessnos = 1, Tocfmtqleadin = 2, Tocfmtqpma = 3, Tocfmtatip = 4, Tocfmtcdtext = 5, /* read toc cdb[1] bit */ Msfbit = 1<<1, /* write types, MMC-6 §7.5.4.9 */ Wtpkt = 0, /* a.k.a. incremental */ Wttrackonce, Wtsessonce, /* a.k.a. disc-at-once */ Wtraw, Wtlayerjump, /* track modes (determine: are these also track types?) */ Tmcdda = 0, /* audio cdda */ Tm2audio, /* 2 audio channels */ Tmunintr = 4, /* data, recorded uninterrupted */ Tmintr, /* data, recorded interrupted (dvd default) */ /* data block types */ Dbraw = 0, /* 2352 bytes */ Db2kdata = 8, /* mode 1: 2K of user data */ Db2336, /* mode 2: 2336 bytes of user data */ /* session formats */ Sfdata = 0, Sfcdi = 0x10, Sfcdxa = 0x20, /* Cache control bits in mode page 8 byte 2 */ Ccrcd = 1<<0, /* read cache disabled */ Ccmf = 1<<1, /* multiplication factor */ Ccwce = 1<<2, /* writeback cache enabled */ Ccsize = 1<<3, /* use `cache segment size', not `# of cache segments' */ Ccdisc = 1<<4, /* discontinuity */ Cccap = 1<<5, /* caching analysis permitted */ Ccabpf = 1<<6, /* abort pre-fetch */ Ccic = 1<<7, /* initiator control */ /* drive->cap bits */ Cwrite = 1<<0, Ccdda = 1<<1, CDNblock = 12, /* chosen for CD */ DVDNblock = 16, /* DVD ECC block is 16 sectors */ BDNblock = 32, /* BD ECC block (`cluster') is 32 sectors */ /* BD-R are write-once in increments of 64KB */ /* * make a single transfer fit in a 9P rpc. if we don't do this, * remote access (e.g., via /mnt/term/dev/sd*) fails mysteriously. */ Readblock = 8192/BScdrom, }; typedef struct Buf Buf; typedef struct Dev Dev; typedef struct Drive Drive; typedef struct Msf Msf; /* minute, second, frame */ typedef struct Otrack Otrack; typedef struct Track Track; typedef schar Tristate; struct Msf { int m; int s; int f; }; struct Track { /* initialized while obtaining the toc (gettoc) */ vlong size; /* total size in bytes */ long bs; /* block size in bytes */ ulong beg; /* beginning block number */ ulong end; /* ending block number */ int type; Msf mbeg; Msf mend; /* initialized by fs */ char name[32]; int mode; ulong mtime; }; struct DTrack /* not used */ { uchar name[32]; uchar beg[4]; /* msf value; only used for audio */ uchar end[4]; /* msf value; only used for audio */ uchar size[8]; uchar magic[4]; }; struct Otrack { Track *track; Drive *drive; int nchange; int omode; Buf *buf; int nref; /* kept by file server */ }; struct Dev { Otrack* (*openrd)(Drive *d, int trackno); Otrack* (*create)(Drive *d, int bs); long (*read)(Otrack *t, void *v, long n, vlong off); long (*write)(Otrack *t, void *v, long n); void (*close)(Otrack *t); int (*gettoc)(Drive*); int (*fixate)(Drive *d); char* (*ctl)(Drive *d, int argc, char **argv); char* (*setspeed)(Drive *d, int r, int w); }; struct Drive { QLock; Scsi; int type; /* scsi peripheral device type: Type?? */ /* disc characteristics */ int mmctype; /* cd, dvd, or bd */ char *dvdtype; /* name of dvd flavour */ char *laysfx; /* layer suffix (e.g., -dl) */ int firsttrack; int invistrack; int ntrack; int nchange; /* compare with the members in Scsi */ ulong changetime; /* " */ int relearn; /* need to re-learn the disc? */ int nameok; int writeok; /* writable disc? */ /* * we could combine these attributes into a single variable except * that we discover them separately sometimes. */ Tristate recordable; /* writable by burning? */ Tristate erasable; /* writable after erasing? */ Track track[Ntrack]; ulong end; /* # of blks on current disc */ ulong cap; /* drive capabilities */ uchar blkbuf[BScdda]; int maxreadspeed; int maxwritespeed; int readspeed; int writespeed; Dev; uchar features[Maxfeatures/8]; void *aux; /* kept by driver */ }; struct Buf { uchar *data; /* buffer */ vlong off; /* data[0] at offset off in file */ int bs; /* block size */ long ndata; /* no. valid bytes in data */ int nblock; /* total buffer size in blocks */ int omode; /* OREAD, OWRITE */ long (*fn)(Buf*, void*, long, ulong); /* read, write */ /* used only by client */ Otrack *otrack; }; extern int vflag;