📄 mmc.c
字号:
#include <u.h>#include <libc.h>#include <disk.h>#include "dat.h"#include "fns.h"enum{ Pagesz = 255,};static Dev mmcdev;typedef struct Mmcaux Mmcaux;struct Mmcaux { uchar page05[Pagesz]; int page05ok; int pagecmdsz; ulong mmcnwa; int nropen; int nwopen; long ntotby; long ntotbk;};static ulongbige(void *p){ uchar *a; a = p; return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);}static ushortbiges(void *p){ uchar *a; a = p; return (a[0]<<8) | a[1];}static voidhexdump(void *v, int n){ int i; uchar *p; p = v; for(i=0; i<n; i++){ print("%.2ux ", p[i]); if((i%8) == 7) print("\n"); } if(i%8) print("\n");}static intmmcgetpage10(Drive *drive, int page, void *v){ uchar cmd[10], resp[512]; int n, r; memset(cmd, 0, sizeof(cmd)); cmd[0] = 0x5A; cmd[2] = page; cmd[8] = 255; n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread); if(n < 8) return -1; r = (resp[6]<<8) | resp[7]; n -= 8+r; if(n < 0) return -1; if(n > Pagesz) n = Pagesz; memmove(v, &resp[8+r], n); return n;}static intmmcgetpage6(Drive *drive, int page, void *v){ uchar cmd[6], resp[512]; int n; memset(cmd, 0, sizeof(cmd)); cmd[0] = 0x1A; cmd[2] = page; cmd[4] = 255; n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread); if(n < 4) return -1; n -= 4+resp[3]; if(n < 0) return -1; if(n > Pagesz) n = Pagesz; memmove(v, &resp[4+resp[3]], n); return n;}static intmmcsetpage10(Drive *drive, int page, void *v){ uchar cmd[10], *p, *pagedata; int len, n; pagedata = v; assert(pagedata[0] == page); len = 8+2+pagedata[1]; p = emalloc(len); memmove(p+8, pagedata, pagedata[1]); memset(cmd, 0, sizeof(cmd)); cmd[0] = 0x55; cmd[1] = 0x10; cmd[8] = len;// print("cmd\n");// hexdump(cmd, 10);// print("page\n");// hexdump(p, len); n = scsi(drive, cmd, sizeof(cmd), p, len, Swrite); free(p); if(n < len) return -1; return 0;}static intmmcsetpage6(Drive *drive, int page, void *v){ uchar cmd[6], *p, *pagedata; int len, n; pagedata = v; assert(pagedata[0] == page); len = 4+2+pagedata[1]; p = emalloc(len); memmove(p+4, pagedata, pagedata[1]); memset(cmd, 0, sizeof(cmd)); cmd[0] = 0x15; cmd[1] = 0x10; cmd[4] = len; n = scsi(drive, cmd, sizeof(cmd), p, len, Swrite); free(p); if(n < len) return -1; return 0;}static intmmcgetpage(Drive *drive, int page, void *v){ Mmcaux *aux; aux = drive->aux; switch(aux->pagecmdsz) { case 10: return mmcgetpage10(drive, page, v); case 6: return mmcgetpage6(drive, page, v); default: assert(0); } return -1;}static intmmcsetpage(Drive *drive, int page, void *v){ Mmcaux *aux; aux = drive->aux; switch(aux->pagecmdsz) { case 10: return mmcsetpage10(drive, page, v); case 6: return mmcsetpage6(drive, page, v); default: assert(0); } return -1;}intmmcstatus(Drive *drive){ uchar cmd[12]; memset(cmd, 0, sizeof(cmd)); cmd[0] = 0xBD; return scsi(drive, cmd, sizeof(cmd), nil, 0, Sread);}voidmmcgetspeed(Drive *drive){ int n, maxread, curread, maxwrite, curwrite; uchar buf[Pagesz]; n = mmcgetpage(drive, 0x2A, buf); maxread = (buf[8]<<8)|buf[9]; curread = (buf[14]<<8)|buf[15]; maxwrite = (buf[18]<<8)|buf[19]; curwrite = (buf[20]<<8)|buf[21]; if(n < 22 || (maxread && maxread < 170) || (curread && curread < 170)) return; /* bogus data */ drive->readspeed = curread; drive->writespeed = curwrite; drive->maxreadspeed = maxread; drive->maxwritespeed = maxwrite;}Drive*mmcprobe(Scsi *scsi){ Mmcaux *aux; Drive *drive; uchar buf[Pagesz]; int cap; /* BUG: confirm mmc better? */ drive = emalloc(sizeof(Drive)); drive->Scsi = *scsi; drive->Dev = mmcdev; aux = emalloc(sizeof(Mmcaux)); drive->aux = aux; /* attempt to read CD capabilities page */ if(mmcgetpage10(drive, 0x2A, buf) >= 0) aux->pagecmdsz = 10; else if(mmcgetpage6(drive, 0x2A, buf) >= 0) aux->pagecmdsz = 6; else { werrstr("not an mmc device"); free(drive); return nil; } cap = 0; if(buf[3] & 3) /* 2=cdrw, 1=cdr */ cap |= Cwrite; if(buf[5] & 1) cap |= Ccdda;// 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 page 05 (write parameter page) */ if((cap & Cwrite) && mmcgetpage(drive, 0x05, aux->page05) >= 0) aux->page05ok = 1; else cap &= ~Cwrite; drive->cap = cap; mmcgetspeed(drive); return drive;}static intmmctrackinfo(Drive *drive, int t, int i){ uchar cmd[10], resp[255]; int n, type, bs; uchar tmode; ulong beg, size; Mmcaux *aux; aux = drive->aux; memset(cmd, 0, sizeof(cmd)); cmd[0] = 0x52; /* get track info */ cmd[1] = 1; cmd[2] = t>>24; cmd[3] = t>>16; cmd[4] = t>>8; cmd[5] = t; cmd[7] = sizeof(resp)>>8; cmd[8] = sizeof(resp); n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread); if(n < 28) { if(vflag) print("trackinfo %d fails n=%d %r\n", t, n); return -1; } beg = bige(&resp[8]); size = bige(&resp[24]); tmode = resp[5] & 0x0D;// dmode = resp[6] & 0x0F; if(vflag) print("track %d type 0x%x\n", t, tmode); type = TypeNone; bs = BScdda; switch(tmode){ case 0: type = TypeAudio; bs = BScdda; break; case 1: /* 2 audio channels, with pre-emphasis 50/15 μs */ if(vflag) print("audio channels with preemphasis on track %d (u%.3d)\n", t, i); type = TypeNone; break; case 4: /* data track, recorded uninterrupted */ type = TypeData; bs = BScdrom; break; case 5: /* data track, recorded interrupted */ default: if(vflag) print("unknown track type %d\n", tmode); } drive->track[i].mtime = drive->changetime; drive->track[i].beg = beg; drive->track[i].end = beg+size; drive->track[i].type = type; drive->track[i].bs = bs; drive->track[i].size = (vlong)(size-2)*bs; /* -2: skip lead out */ if(resp[6] & (1<<6)) { drive->track[i].type = TypeBlank; drive->writeok = 1; } if(t == 0xFF) aux->mmcnwa = bige(&resp[12]); return 0;}static intmmcreadtoc(Drive *drive, int type, int track, void *data, int nbytes){ uchar cmd[10]; memset(cmd, 0, sizeof(cmd)); cmd[0] = 0x43; cmd[1] = type; cmd[6] = track; cmd[7] = nbytes>>8; cmd[8] = nbytes; return scsi(drive, cmd, sizeof(cmd), data, nbytes, Sread);}static intmmcreaddiscinfo(Drive *drive, void *data, int nbytes){ uchar cmd[10]; int n; memset(cmd, 0, sizeof(cmd)); cmd[0] = 0x51; cmd[7] = nbytes>>8; cmd[8] = nbytes; n = scsi(drive, cmd, sizeof(cmd), data, nbytes, Sread); if(n < 24) { if(n >= 0) werrstr("rdiscinfo returns %d", n); return -1; } return n;}static Msfrdmsf(uchar *p){ Msf msf; msf.m = p[0]; msf.s = p[1]; msf.f = p[2]; return msf;}static intmmcgettoc(Drive *drive){ uchar resp[1024]; int i, n, first, last; ulong tot; Track *t; /* * if someone has swapped the cd, * mmcreadtoc will get ``medium changed'' and the * scsi routines will set nchange and changetime in the * scsi device. */ mmcreadtoc(drive, 0, 0, resp, sizeof(resp)); if(drive->Scsi.changetime == 0) { /* no media present */ drive->ntrack = 0; return 0; } if(drive->nchange == drive->Scsi.nchange && drive->changetime != 0) return 0; drive->ntrack = 0; drive->nameok = 0; drive->nchange = drive->Scsi.nchange; drive->changetime = drive->Scsi.changetime; drive->writeok = 0; for(i=0; i<nelem(drive->track); i++){ memset(&drive->track[i].mbeg, 0, sizeof(Msf)); memset(&drive->track[i].mend, 0, sizeof(Msf)); } /* * find number of tracks */ if((n=mmcreadtoc(drive, 0x02, 0, resp, sizeof(resp))) < 4) { /* * on a blank disc in a cd-rw, use readdiscinfo * to find the track info. */ if(mmcreaddiscinfo(drive, resp, sizeof(resp)) < 0) return -1; if(resp[4] != 1) print("multi-session disc %d\n", resp[4]); first = resp[3]; last = resp[6]; if(vflag) print("blank disc %d %d\n", first, last); drive->writeok = 1; } else { first = resp[2]; last = resp[3]; if(n >= 4+8*(last-first+2)) { for(i=0; i<=last-first+1; i++) /* <=: track[last-first+1] = end */ drive->track[i].mbeg = rdmsf(resp+4+i*8+5); for(i=0; i<last-first+1; i++) drive->track[i].mend = drive->track[i+1].mbeg; } } if(vflag) print("first %d last %d\n", first, last); if(first == 0 && last == 0) first = 1; if(first <= 0 || first >= Maxtrack) { werrstr("first table %d not in range", first); return -1; } if(last <= 0 || last >= Maxtrack) { werrstr("last table %d not in range", last); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -