$NetBSD: patch-ce,v 1.3 2006/03/07 06:29:03 joerg Exp $ --- interface/cooked_interface.c.orig 2000-04-20 08:41:04.000000000 +1000 +++ interface/cooked_interface.c @@ -10,9 +10,11 @@ #include "common_interface.h" #include "utils.h" +#if !defined(__FreeBSD__) && !defined(__DragonFly__) static int cooked_readtoc (cdrom_drive *d){ int i; int tracks; +#ifdef __linux__ struct cdrom_tochdr hdr; struct cdrom_tocentry entry; @@ -52,6 +54,45 @@ static int cooked_readtoc (cdrom_drive * d->disc_toc[i].dwStartSector = entry.cdte_addr.lba; tracks=hdr.cdth_trk1+1; +#endif + +#ifdef __NetBSD__ + struct ioc_read_toc_entry hdr; + struct cd_toc_entry entries[MAXTRK + 1]; /* + 1 for leadout */ + + hdr.address_format = CD_LBA_FORMAT; + hdr.starting_track = 1; + hdr.data_len = sizeof entries; + hdr.data = entries; + memset(entries, 0, sizeof entries); + + /* get all TOC entries at once */ +#ifndef CDIOREADTOCENTRIES +#define CDIOREADTOCENTRIES CDIOREADTOCENTRYS +#endif + if(ioctl(d->ioctl_fd, CDIOREADTOCENTRIES, &hdr)) + switch(errno){ + case EPERM: + cderror(d,"102: Permision denied on cdrom (ioctl) device\n"); + return(-102); + default: + cderror(d,"004: Unable to read table of contents header\n"); + return(-4); + } + + for(i = 0; i < MAXTRK + 1; i++) { + d->disc_toc[i].bFlags = (entries[i].addr_type << 4) | (entries[i].control & 0x0f); + d->disc_toc[i].bTrack = entries[i].track; + d->disc_toc[i].dwStartSector = entries[i].addr.lba; + if (entries[i].track == 0) { + cderror(d,"005: Unable to read table of contents entry\n"); + return(-5); + } + if (entries[i].track >= 100) + break; /* leadout */ + } + tracks = i; +#endif d->cd_extra=FixupTOC(d,tracks); return(--tracks); /* without lead-out */ } @@ -60,10 +101,15 @@ static int cooked_readtoc (cdrom_drive * /* Set operating speed */ static int cooked_setspeed(cdrom_drive *d, int speed) { +#ifdef __linux__ if(d->ioctl_fd!=-1) return ioctl(d->ioctl_fd, CDROM_SELECT_SPEED, speed); else return 0; +#endif +#ifdef __NetBSD__ + errx(1, "cooked_setspeed: not implemented"); +#endif } @@ -72,6 +118,7 @@ static int cooked_setspeed(cdrom_drive * */ static long cooked_read (cdrom_drive *d, void *p, long begin, long sectors){ +#ifdef __linux__ int retry_count,err; struct cdrom_read_audio arg; char *buffer=(char *)p; @@ -127,7 +174,133 @@ static long cooked_read (cdrom_drive *d, } while (err); return(sectors); +#endif +#ifdef __NetBSD__ + errx(1, "cooked_read: not implemented"); +#endif +} +#elif defined(__FreeBSD__) || defined(__DragonFly__) +static int +cooked_readtoc(cdrom_drive *d) +{ + int i; + struct ioc_toc_header hdr; + struct ioc_read_toc_single_entry entry; + + if (ioctl(d->ioctl_fd, CDIOREADTOCHEADER, &hdr) == -1) { + int ret; + + if (errno == EPERM) { + ret = -102; + cderror(d, "102: "); + } else { + ret = -4; + cderror(d, "004: Unable to read table of contents header: "); + } + cderror(d, strerror(errno)); + cderror(d, "\n"); + return ret; + } + + entry.address_format = CD_LBA_FORMAT; + for (i = hdr.starting_track; i <= hdr.ending_track; ++i) { + entry.track = i; + + if (ioctl(d->ioctl_fd, CDIOREADTOCENTRY, &entry) == -1) { + cderror(d, "005: Unable to read table of contents entry\n"); + return -5; + } + + d->disc_toc[i - hdr.starting_track].bFlags = entry.entry.control; + d->disc_toc[i - hdr.starting_track].bTrack = entry.entry.track; + d->disc_toc[i - hdr.starting_track].dwStartSector = be32_to_cpu(entry.entry.addr.lba); + } + + entry.track = 0xaa; /* leadout */ + + if (ioctl(d->ioctl_fd, CDIOREADTOCENTRY, &entry) == -1) { + cderror(d, "005: Unable to read table of contents entry\n"); + return -5; + } + + d->disc_toc[i - hdr.starting_track].bFlags = entry.entry.control; + d->disc_toc[i - hdr.starting_track].bTrack = entry.entry.track; + d->disc_toc[i - hdr.starting_track].dwStartSector = be32_to_cpu(entry.entry.addr.lba); + + d->cd_extra = FixupTOC(d, hdr.ending_track - hdr.starting_track + 2); /* with TOC */ + + return hdr.ending_track - hdr.starting_track + 1; +} + +static int +cooked_setspeed(cdrom_drive *d, int speed) +{ +#ifdef CDRIOCREADSPEED + speed *= 177; + return ioctl(d->ioctl_fd, CDRIOCREADSPEED, &speed); +#else + return -1; +#endif +} + + +static long +cooked_read(cdrom_drive *d, void *p, long begin, long sectors) +{ + int retry_count = 0; + struct ioc_read_audio arg; + + if (sectors > d->nsectors) + sectors = d->nsectors; + + arg.address_format = CD_LBA_FORMAT; + arg.address.lba = begin; + arg.buffer = p; + + for (;;) { + arg.nframes = sectors; + if (ioctl(d->ioctl_fd, CDIOCREADAUDIO, &arg) == -1) { + if (!d->error_retry) + return -7; + + switch (errno) { + case ENOMEM: + if (sectors == 1) { + cderror(d, "300: Kernel memory error\n"); + return -300; + } + /* FALLTHROUGH */ + default: + if (sectors == 1) { + if (retry_count > MAX_RETRIES - 1) { + char b[256]; + snprintf(b, sizeof(b), + "010: Unable to access sector %ld; " + "skipping...\n", begin); + cderror(d, b); + return -10; + } + break; + } + } + + if (retry_count > 4 && sectors > 1) + sectors = sectors * 3 / 4; + + ++retry_count; + + if (retry_count > MAX_RETRIES) { + cderror(d, "007: Unknown, unrecoverable error reading data\n"); + return -7; + } + } else + break; + } + + return sectors; } +#endif + /* hook */ static int Dummy (cdrom_drive *d,int Switch){ @@ -191,8 +364,11 @@ static void check_exceptions(cdrom_drive /* set function pointers to use the ioctl routines */ int cooked_init_drive (cdrom_drive *d){ +#ifdef __NetBSD__ + errx(1, "cooked_init_drive: not implemented"); +#else int ret; - +#ifdef __linux__ switch(d->drive_type){ case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */ case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */ @@ -243,6 +419,9 @@ int cooked_init_drive (cdrom_drive *d){ default: d->nsectors=40; } +#elif defined(__FreeBSD__) || defined(__DragonFly__) + d->nsectors = 26; /* FreeBSD only supports 64K I/O transfer size */ +#endif d->enable_cdda = Dummy; d->read_audio = cooked_read; d->set_speed = cooked_setspeed; @@ -255,5 +434,6 @@ int cooked_init_drive (cdrom_drive *d){ if((ret=verify_read_command(d)))return(ret); d->error_retry=1; return(0); +#endif }