$NetBSD: patch-ce,v 1.7 2009/08/14 15:51:06 drochner Exp $ --- interface/cooked_interface.c.orig 2008-08-26 11:55:22.000000000 +0200 +++ interface/cooked_interface.c @@ -1,6 +1,8 @@ /****************************************************************** * CopyPolicy: GNU Lesser General Public License 2.1 applies * Copyright (C) Monty xiphmont@mit.edu + * FreeBSD porting (c) 2003 + * Simon 'corecode' Schubert * * CDROM code specific to the cooked ioctl interface * @@ -24,6 +26,7 @@ static int timed_ioctl(cdrom_drive *d, i return ret2; } +#if !defined(__FreeBSD__) && !defined(__DragonFly__) static int cooked_readtoc (cdrom_drive *d){ int i; int tracks; @@ -156,6 +159,141 @@ static long cooked_read (cdrom_drive *d, if(p==NULL && buffer)free(buffer); return ret; } +#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; +/* CDIOCREADAUDIO has been removed in FreeBSD 5.1-CURRENT */ +#if __FreeBSD_version >= 501106 + int bsize = CD_FRAMESIZE_RAW; +#else + 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; +#endif + +#if __FreeBSD_version >= 501106 + if (ioctl(d->ioctl_fd, CDRIOCSETBLOCKSIZE, &bsize) == -1) { + return -7; + } +#endif + for (;;) { +#if __FreeBSD_version >= 501106 + if (pread(d->ioctl_fd, p, sectors*bsize, begin*bsize) != sectors*bsize) { +#else + arg.nframes = sectors; + if (ioctl(d->ioctl_fd, CDIOCREADAUDIO, &arg) == -1) { +#endif + 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){ @@ -221,6 +359,7 @@ static void check_exceptions(cdrom_drive int cooked_init_drive (cdrom_drive *d){ int ret; +#ifdef __linux__ switch(d->drive_type){ case MATSUSHITA_CDROM_MAJOR: /* sbpcd 1 */ case MATSUSHITA_CDROM2_MAJOR: /* sbpcd 2 */ @@ -271,6 +410,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->read_toc = cooked_readtoc;