static int mcdx_transfer(struct s_drive_stuff *stuffp, char *p, int sector, int nr_sectors) /* This seems to do the actually transfer. But it does more. It keeps track of errors occurred and will (if possible) fall back to single speed on error. Return: -1 on timeout or other error else status byte (as in stuff->st) */ { int ans; ans = mcdx_xfer(stuffp, p, sector, nr_sectors); return ans; #ifdef FALLBACK if (-1 == ans) stuffp->readerrs++; else return ans; if (stuffp->readerrs && stuffp->readcmd == READ1X) { xwarn("XXX Already reading 1x -- no chance\n"); return -1; } xwarn("XXX Fallback to 1x\n"); stuffp->readcmd = READ1X; return mcdx_transfer(stuffp, p, sector, nr_sectors); #endif }
static int mcdx_open(struct cdrom_device_info *cdi, int purpose) { struct s_drive_stuff *stuffp; xtrace(OPENCLOSE, "open()\n"); stuffp = cdi->handle; if (!stuffp->present) return -ENXIO; /* Make the modules looking used ... (thanx bjorn). * But we shouldn't forget to decrement the module counter * on error return */ /* this is only done to test if the drive talks with us */ if (-1 == mcdx_getstatus(stuffp, 1)) return -EIO; if (stuffp->xxx) { xtrace(OPENCLOSE, "open() media changed\n"); stuffp->audiostatus = CDROM_AUDIO_INVALID; stuffp->readcmd = 0; xtrace(OPENCLOSE, "open() Request multisession info\n"); if (-1 == mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6)) xinfo("No multidiskinfo\n"); } else { /* multisession ? */ if (!stuffp->multi.multi) stuffp->multi.msf_last.second = 2; xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n", stuffp->multi.multi, stuffp->multi.msf_last.minute, stuffp->multi.msf_last.second, stuffp->multi.msf_last.frame); {; } /* got multisession information */ /* request the disks table of contents (aka diskinfo) */ if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { stuffp->lastsector = -1; } else { stuffp->lastsector = (CD_FRAMESIZE / 512) * msf2log(&stuffp->di.msf_leadout) - 1; xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n", stuffp->di.n_first, stuffp->di.msf_first.minute, stuffp->di.msf_first.second, stuffp->di.msf_first.frame, msf2log(&stuffp->di.msf_first)); xtrace(OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n", stuffp->di.n_last, stuffp->di.msf_leadout.minute, stuffp->di.msf_leadout.second, stuffp->di.msf_leadout.frame, msf2log(&stuffp->di.msf_leadout)); } if (stuffp->toc) { xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc); kfree(stuffp->toc); stuffp->toc = NULL; } xtrace(OPENCLOSE, "open() init irq generation\n"); if (-1 == mcdx_config(stuffp, 1)) return -EIO; #ifdef FALLBACK /* Set the read speed */ xwarn("AAA %x AAA\n", stuffp->readcmd); if (stuffp->readerrs) stuffp->readcmd = READ1X; else stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X; xwarn("XXX %x XXX\n", stuffp->readcmd); #else stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X; #endif /* try to get the first sector, iff any ... */ if (stuffp->lastsector >= 0) { char buf[512]; int ans; int tries; stuffp->xa = 0; stuffp->audio = 0; for (tries = 6; tries; tries--) { stuffp->introk = 1; xtrace(OPENCLOSE, "open() try as %s\n", stuffp->xa ? "XA" : "normal"); /* set data mode */ if (-1 == (ans = mcdx_setdatamode(stuffp, stuffp-> xa ? MODE2 : MODE1, 1))) { /* return -EIO; */ stuffp->xa = 0; break; } if ((stuffp->audio = e_audio(ans))) break; while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1))); if (ans == 1) break; stuffp->xa = !stuffp->xa; } } /* xa disks will be read in raw mode, others not */ if (-1 == mcdx_setdrivemode(stuffp, stuffp->xa ? RAW : COOKED, 1)) return -EIO; if (stuffp->audio) { xinfo("open() audio disk found\n"); } else if (stuffp->lastsector >= 0) { xinfo("open() %s%s disk found\n", stuffp->xa ? "XA / " : "", stuffp->multi. multi ? "Multi Session" : "Single Session"); } } stuffp->xxx = 0; stuffp->users++; return 0; }
static void do_mcdx_request(request_queue_t * q) { struct s_drive_stuff *stuffp; struct request *req; again: req = elv_next_request(q); if (!req) return; stuffp = req->rq_disk->private_data; if (!stuffp->present) { xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name); xtrace(REQUEST, "end_request(0): bad device\n"); end_request(req, 0); return; } if (stuffp->audio) { xwarn("do_request() attempt to read from audio cd\n"); xtrace(REQUEST, "end_request(0): read from audio\n"); end_request(req, 0); return; } xtrace(REQUEST, "do_request() (%lu + %lu)\n", req->sector, req->nr_sectors); if (req->cmd != READ) { xwarn("do_request(): non-read command to cd!!\n"); xtrace(REQUEST, "end_request(0): write\n"); end_request(req, 0); return; } else { stuffp->status = 0; while (req->nr_sectors) { int i; i = mcdx_transfer(stuffp, req->buffer, req->sector, req->nr_sectors); if (i == -1) { end_request(req, 0); goto again; } req->sector += i; req->nr_sectors -= i; req->buffer += (i * 512); } end_request(req, 1); goto again; xtrace(REQUEST, "end_request(1)\n"); end_request(req, 1); } goto again; }