Search
lxdream.org :: lxdream :: r237:6f1a429c9d12
lxdream 0.9.1
released Jun 29
Download Now
changeset237:6f1a429c9d12
parent236:581a9f8bf6a6
child238:6af4cc93b137
authornkeynes
dateThu Dec 14 12:31:38 2006 +0000 (13 years ago)
Add preliminary linux native CD driver support
src/Makefile.am
src/Makefile.in
src/gdrom/gdrom.c
src/gdrom/gdrom.h
src/gdrom/linux.c
1.1 --- a/src/Makefile.am Thu Dec 14 11:58:18 2006 +0000
1.2 +++ b/src/Makefile.am Thu Dec 14 12:31:38 2006 +0000
1.3 @@ -14,7 +14,7 @@
1.4 asic.c asic.h \
1.5 syscall.c syscall.h bios.c dcload.c \
1.6 gdrom/ide.c gdrom/ide.h gdrom/packet.h \
1.7 - gdrom/gdrom.c gdrom/gdrom.h gdrom/nrg.c gdrom/cdi.c \
1.8 + gdrom/gdrom.c gdrom/gdrom.h gdrom/nrg.c gdrom/cdi.c gdrom/linux.c \
1.9 dreamcast.c dreamcast.h \
1.10 sh4/intc.c sh4/intc.h sh4/sh4mem.c sh4/timer.c sh4/dmac.c \
1.11 sh4/sh4core.c sh4/sh4core.h sh4/sh4dasm.c sh4/sh4dasm.h \
2.1 --- a/src/Makefile.in Thu Dec 14 11:58:18 2006 +0000
2.2 +++ b/src/Makefile.in Thu Dec 14 12:31:38 2006 +0000
2.3 @@ -62,6 +62,7 @@
2.4 GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
2.5 GMOFILES = @GMOFILES@
2.6 GMSGFMT = @GMSGFMT@
2.7 +GREP = @GREP@
2.8 INSTALL_DATA = @INSTALL_DATA@
2.9 INSTALL_PROGRAM = @INSTALL_PROGRAM@
2.10 INSTALL_SCRIPT = @INSTALL_SCRIPT@
2.11 @@ -100,8 +101,6 @@
2.12 VERSION = @VERSION@
2.13 XGETTEXT = @XGETTEXT@
2.14 ac_ct_CC = @ac_ct_CC@
2.15 -ac_ct_STRIP = @ac_ct_STRIP@
2.16 -ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
2.17 am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
2.18 am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
2.19 am__include = @am__include@
2.20 @@ -110,18 +109,25 @@
2.21 bindir = @bindir@
2.22 build_alias = @build_alias@
2.23 datadir = @datadir@
2.24 +datarootdir = @datarootdir@
2.25 +docdir = @docdir@
2.26 +dvidir = @dvidir@
2.27 exec_prefix = @exec_prefix@
2.28 host_alias = @host_alias@
2.29 +htmldir = @htmldir@
2.30 includedir = @includedir@
2.31 infodir = @infodir@
2.32 install_sh = @install_sh@
2.33 libdir = @libdir@
2.34 libexecdir = @libexecdir@
2.35 +localedir = @localedir@
2.36 localstatedir = @localstatedir@
2.37 mandir = @mandir@
2.38 oldincludedir = @oldincludedir@
2.39 +pdfdir = @pdfdir@
2.40 prefix = @prefix@
2.41 program_transform_name = @program_transform_name@
2.42 +psdir = @psdir@
2.43 sbindir = @sbindir@
2.44 sharedstatedir = @sharedstatedir@
2.45 sysconfdir = @sysconfdir@
2.46 @@ -142,7 +148,7 @@
2.47 asic.c asic.h \
2.48 syscall.c syscall.h bios.c dcload.c \
2.49 gdrom/ide.c gdrom/ide.h gdrom/packet.h \
2.50 - gdrom/gdrom.c gdrom/gdrom.h gdrom/nrg.c gdrom/cdi.c \
2.51 + gdrom/gdrom.c gdrom/gdrom.h gdrom/nrg.c gdrom/cdi.c gdrom/linux.c \
2.52 dreamcast.c dreamcast.h \
2.53 sh4/intc.c sh4/intc.h sh4/sh4mem.c sh4/timer.c sh4/dmac.c \
2.54 sh4/sh4core.c sh4/sh4core.h sh4/sh4dasm.c sh4/sh4dasm.h \
2.55 @@ -180,8 +186,8 @@
2.56 am_lxdream_OBJECTS = main.$(OBJEXT) mem.$(OBJEXT) watch.$(OBJEXT) \
2.57 asic.$(OBJEXT) syscall.$(OBJEXT) bios.$(OBJEXT) \
2.58 dcload.$(OBJEXT) ide.$(OBJEXT) gdrom.$(OBJEXT) nrg.$(OBJEXT) \
2.59 - cdi.$(OBJEXT) dreamcast.$(OBJEXT) intc.$(OBJEXT) \
2.60 - sh4mem.$(OBJEXT) timer.$(OBJEXT) dmac.$(OBJEXT) \
2.61 + cdi.$(OBJEXT) linux.$(OBJEXT) dreamcast.$(OBJEXT) \
2.62 + intc.$(OBJEXT) sh4mem.$(OBJEXT) timer.$(OBJEXT) dmac.$(OBJEXT) \
2.63 sh4core.$(OBJEXT) sh4dasm.$(OBJEXT) sh4mmio.$(OBJEXT) \
2.64 scif.$(OBJEXT) armcore.$(OBJEXT) armdasm.$(OBJEXT) \
2.65 armmem.$(OBJEXT) aica.$(OBJEXT) audio.$(OBJEXT) pvr2.$(OBJEXT) \
2.66 @@ -212,19 +218,20 @@
2.67 @AMDEP_TRUE@ ./$(DEPDIR)/dump_win.Po ./$(DEPDIR)/gdrom.Po \
2.68 @AMDEP_TRUE@ ./$(DEPDIR)/gui.Po ./$(DEPDIR)/ide.Po \
2.69 @AMDEP_TRUE@ ./$(DEPDIR)/intc.Po ./$(DEPDIR)/interface.Po \
2.70 -@AMDEP_TRUE@ ./$(DEPDIR)/loader.Po ./$(DEPDIR)/main.Po \
2.71 -@AMDEP_TRUE@ ./$(DEPDIR)/maple.Po ./$(DEPDIR)/mem.Po \
2.72 -@AMDEP_TRUE@ ./$(DEPDIR)/mmr_win.Po ./$(DEPDIR)/nrg.Po \
2.73 -@AMDEP_TRUE@ ./$(DEPDIR)/pvr2.Po ./$(DEPDIR)/rendbkg.Po \
2.74 -@AMDEP_TRUE@ ./$(DEPDIR)/rendcore.Po ./$(DEPDIR)/render.Po \
2.75 -@AMDEP_TRUE@ ./$(DEPDIR)/rendsort.Po ./$(DEPDIR)/scif.Po \
2.76 -@AMDEP_TRUE@ ./$(DEPDIR)/sh4core.Po ./$(DEPDIR)/sh4dasm.Po \
2.77 -@AMDEP_TRUE@ ./$(DEPDIR)/sh4mem.Po ./$(DEPDIR)/sh4mmio.Po \
2.78 -@AMDEP_TRUE@ ./$(DEPDIR)/support.Po ./$(DEPDIR)/syscall.Po \
2.79 -@AMDEP_TRUE@ ./$(DEPDIR)/tacore.Po ./$(DEPDIR)/texcache.Po \
2.80 -@AMDEP_TRUE@ ./$(DEPDIR)/timer.Po ./$(DEPDIR)/util.Po \
2.81 -@AMDEP_TRUE@ ./$(DEPDIR)/video_gtk.Po ./$(DEPDIR)/video_null.Po \
2.82 -@AMDEP_TRUE@ ./$(DEPDIR)/video_x11.Po ./$(DEPDIR)/watch.Po
2.83 +@AMDEP_TRUE@ ./$(DEPDIR)/linux.Po ./$(DEPDIR)/loader.Po \
2.84 +@AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/maple.Po \
2.85 +@AMDEP_TRUE@ ./$(DEPDIR)/mem.Po ./$(DEPDIR)/mmr_win.Po \
2.86 +@AMDEP_TRUE@ ./$(DEPDIR)/nrg.Po ./$(DEPDIR)/pvr2.Po \
2.87 +@AMDEP_TRUE@ ./$(DEPDIR)/rendbkg.Po ./$(DEPDIR)/rendcore.Po \
2.88 +@AMDEP_TRUE@ ./$(DEPDIR)/render.Po ./$(DEPDIR)/rendsort.Po \
2.89 +@AMDEP_TRUE@ ./$(DEPDIR)/scif.Po ./$(DEPDIR)/sh4core.Po \
2.90 +@AMDEP_TRUE@ ./$(DEPDIR)/sh4dasm.Po ./$(DEPDIR)/sh4mem.Po \
2.91 +@AMDEP_TRUE@ ./$(DEPDIR)/sh4mmio.Po ./$(DEPDIR)/support.Po \
2.92 +@AMDEP_TRUE@ ./$(DEPDIR)/syscall.Po ./$(DEPDIR)/tacore.Po \
2.93 +@AMDEP_TRUE@ ./$(DEPDIR)/texcache.Po ./$(DEPDIR)/timer.Po \
2.94 +@AMDEP_TRUE@ ./$(DEPDIR)/util.Po ./$(DEPDIR)/video_gtk.Po \
2.95 +@AMDEP_TRUE@ ./$(DEPDIR)/video_null.Po ./$(DEPDIR)/video_x11.Po \
2.96 +@AMDEP_TRUE@ ./$(DEPDIR)/watch.Po
2.97 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
2.98 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
2.99 CCLD = $(CC)
2.100 @@ -300,6 +307,7 @@
2.101 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ide.Po@am__quote@
2.102 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intc.Po@am__quote@
2.103 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface.Po@am__quote@
2.104 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux.Po@am__quote@
2.105 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loader.Po@am__quote@
2.106 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
2.107 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maple.Po@am__quote@
2.108 @@ -437,6 +445,28 @@
2.109 @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.110 @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdi.obj `if test -f 'gdrom/cdi.c'; then $(CYGPATH_W) 'gdrom/cdi.c'; else $(CYGPATH_W) '$(srcdir)/gdrom/cdi.c'; fi`
2.111
2.112 +linux.o: gdrom/linux.c
2.113 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT linux.o -MD -MP -MF "$(DEPDIR)/linux.Tpo" \
2.114 +@am__fastdepCC_TRUE@ -c -o linux.o `test -f 'gdrom/linux.c' || echo '$(srcdir)/'`gdrom/linux.c; \
2.115 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/linux.Tpo" "$(DEPDIR)/linux.Po"; \
2.116 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/linux.Tpo"; exit 1; \
2.117 +@am__fastdepCC_TRUE@ fi
2.118 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gdrom/linux.c' object='linux.o' libtool=no @AMDEPBACKSLASH@
2.119 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/linux.Po' tmpdepfile='$(DEPDIR)/linux.TPo' @AMDEPBACKSLASH@
2.120 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.121 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o linux.o `test -f 'gdrom/linux.c' || echo '$(srcdir)/'`gdrom/linux.c
2.122 +
2.123 +linux.obj: gdrom/linux.c
2.124 +@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT linux.obj -MD -MP -MF "$(DEPDIR)/linux.Tpo" \
2.125 +@am__fastdepCC_TRUE@ -c -o linux.obj `if test -f 'gdrom/linux.c'; then $(CYGPATH_W) 'gdrom/linux.c'; else $(CYGPATH_W) '$(srcdir)/gdrom/linux.c'; fi`; \
2.126 +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/linux.Tpo" "$(DEPDIR)/linux.Po"; \
2.127 +@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/linux.Tpo"; exit 1; \
2.128 +@am__fastdepCC_TRUE@ fi
2.129 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gdrom/linux.c' object='linux.obj' libtool=no @AMDEPBACKSLASH@
2.130 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/linux.Po' tmpdepfile='$(DEPDIR)/linux.TPo' @AMDEPBACKSLASH@
2.131 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
2.132 +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o linux.obj `if test -f 'gdrom/linux.c'; then $(CYGPATH_W) 'gdrom/linux.c'; else $(CYGPATH_W) '$(srcdir)/gdrom/linux.c'; fi`
2.133 +
2.134 intc.o: sh4/intc.c
2.135 @am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT intc.o -MD -MP -MF "$(DEPDIR)/intc.Tpo" \
2.136 @am__fastdepCC_TRUE@ -c -o intc.o `test -f 'sh4/intc.c' || echo '$(srcdir)/'`sh4/intc.c; \
3.1 --- a/src/gdrom/gdrom.c Thu Dec 14 11:58:18 2006 +0000
3.2 +++ b/src/gdrom/gdrom.c Thu Dec 14 12:31:38 2006 +0000
3.3 @@ -1,5 +1,5 @@
3.4 /**
3.5 - * $Id: gdrom.c,v 1.9 2006-06-26 10:30:42 nkeynes Exp $
3.6 + * $Id: gdrom.c,v 1.10 2006-12-14 12:31:38 nkeynes Exp $
3.7 *
3.8 * GD-Rom access functions.
3.9 *
3.10 @@ -17,6 +17,7 @@
3.11 */
3.12
3.13 #include <stdio.h>
3.14 +#include <fcntl.h>
3.15 #include <errno.h>
3.16 #include "gdrom/ide.h"
3.17 #include "gdrom/gdrom.h"
3.18 @@ -26,7 +27,7 @@
3.19 static void gdrom_image_destroy( gdrom_disc_t );
3.20 static gdrom_error_t gdrom_image_read_sectors( gdrom_disc_t, uint32_t, uint32_t, int, char *, uint32_t * );
3.21
3.22 -gdrom_image_class_t gdrom_image_classes[] = { &nrg_image_class, &cdi_image_class, NULL };
3.23 +gdrom_image_class_t gdrom_image_classes[] = { &linux_device_class, &nrg_image_class, &cdi_image_class, NULL };
3.24
3.25 gdrom_disc_t gdrom_disc = NULL;
3.26
3.27 @@ -37,20 +38,26 @@
3.28 {
3.29 const gchar *ext = strrchr(filename, '.');
3.30 gdrom_disc_t disc = NULL;
3.31 - FILE *f = fopen(filename, "ro");
3.32 +
3.33 + int fd = open( filename, O_RDONLY | O_NONBLOCK );
3.34 + FILE *f;
3.35 int i,j;
3.36 gdrom_image_class_t extclz = NULL;
3.37
3.38 - if( f == NULL ) {
3.39 + if( fd == -1 ) {
3.40 ERROR("Unable to open file '%s': %s", filename, strerror(errno));
3.41 return NULL;
3.42 }
3.43
3.44 + f = fdopen(fd, "ro");
3.45 +
3.46 +
3.47 /* try extensions */
3.48 if( ext != NULL ) {
3.49 ext++; /* Skip the '.' */
3.50 for( i=0; gdrom_image_classes[i] != NULL; i++ ) {
3.51 - if( strcasecmp( gdrom_image_classes[i]->extension, ext ) == 0 ) {
3.52 + if( gdrom_image_classes[i]->extension != NULL &&
3.53 + strcasecmp( gdrom_image_classes[i]->extension, ext ) == 0 ) {
3.54 extclz = gdrom_image_classes[i];
3.55 if( extclz->is_valid_file(f) ) {
3.56 disc = extclz->open_image_file(filename, f);
3.57 @@ -63,15 +70,20 @@
3.58 }
3.59
3.60 /* Okay, fall back to magic */
3.61 + gboolean recognized = FALSE;
3.62 for( i=0; gdrom_image_classes[i] != NULL; i++ ) {
3.63 if( gdrom_image_classes[i] != extclz &&
3.64 gdrom_image_classes[i]->is_valid_file(f) ) {
3.65 + recognized = TRUE;
3.66 disc = gdrom_image_classes[i]->open_image_file(filename, f);
3.67 if( disc != NULL )
3.68 return disc;
3.69 }
3.70 }
3.71
3.72 + if( !recognized ) {
3.73 + ERROR( "Unable to open disc %s: Unsupported format", filename );
3.74 + }
3.75 fclose(f);
3.76 return NULL;
3.77 }
4.1 --- a/src/gdrom/gdrom.h Thu Dec 14 11:58:18 2006 +0000
4.2 +++ b/src/gdrom/gdrom.h Thu Dec 14 12:31:38 2006 +0000
4.3 @@ -1,5 +1,5 @@
4.4 /**
4.5 - * $Id: gdrom.h,v 1.7 2006-06-26 10:30:42 nkeynes Exp $
4.6 + * $Id: gdrom.h,v 1.8 2006-12-14 12:31:38 nkeynes Exp $
4.7 *
4.8 * This file defines the structures and functions used by the GD-Rom
4.9 * disc driver. (ie, the modules that supply a CD image to be used by the
4.10 @@ -95,6 +95,7 @@
4.11
4.12 extern struct gdrom_image_class nrg_image_class;
4.13 extern struct gdrom_image_class cdi_image_class;
4.14 +extern struct gdrom_image_class linux_device_class;
4.15
4.16 /**
4.17 * Construct a new image file using the default methods.
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/src/gdrom/linux.c Thu Dec 14 12:31:38 2006 +0000
5.3 @@ -0,0 +1,256 @@
5.4 +/**
5.5 + * $Id: linux.c,v 1.1 2006-12-14 12:31:38 nkeynes Exp $
5.6 + *
5.7 + * Linux cd-rom device driver
5.8 + *
5.9 + * Copyright (c) 2005 Nathan Keynes.
5.10 + *
5.11 + * This program is free software; you can redistribute it and/or modify
5.12 + * it under the terms of the GNU General Public License as published by
5.13 + * the Free Software Foundation; either version 2 of the License, or
5.14 + * (at your option) any later version.
5.15 + *
5.16 + * This program is distributed in the hope that it will be useful,
5.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.19 + * GNU General Public License for more details.
5.20 + */
5.21 +#include <stdlib.h>
5.22 +#include <stdio.h>
5.23 +#include <string.h>
5.24 +#include <errno.h>
5.25 +#include <linux/cdrom.h>
5.26 +#include <sys/stat.h>
5.27 +#include <sys/ioctl.h>
5.28 +
5.29 +#include "gdrom/gdrom.h"
5.30 +#include "gdrom/packet.h"
5.31 +#include "dream.h"
5.32 +
5.33 +#define MAXTOCENTRIES 600 /* This is a fairly generous overestimate really */
5.34 +#define MAXTOCSIZE 4 + (MAXTOCENTRIES*11)
5.35 +
5.36 +#define MSFTOLBA( m,s,f ) (f + (s*CD_FRAMES) + (m*CD_FRAMES*CD_SECS))
5.37 +
5.38 +static uint32_t inline lbatomsf( uint32_t lba ) {
5.39 + union cdrom_addr addr;
5.40 + lba = lba + CD_MSF_OFFSET;
5.41 + addr.msf.frame = lba % CD_FRAMES;
5.42 + int seconds = lba / CD_FRAMES;
5.43 + addr.msf.second = seconds % CD_SECS;
5.44 + addr.msf.minute = seconds / CD_SECS;
5.45 + return addr.lba;
5.46 +}
5.47 +
5.48 +#define LBATOMSF( lba ) lbatomsf(lba)
5.49 +
5.50 +
5.51 +static gboolean linux_image_is_valid( FILE *f );
5.52 +static gdrom_disc_t linux_open_device( const gchar *filename, FILE *f );
5.53 +static gdrom_error_t linux_read_disc_toc( gdrom_disc_t disc );
5.54 +static gdrom_error_t linux_read_sectors( gdrom_disc_t disc, uint32_t sector,
5.55 + uint32_t sector_count, int mode, char *buf,
5.56 + uint32_t *length );
5.57 +static gdrom_error_t linux_send_command( int fd, char *cmd, char *buffer, size_t buflen,
5.58 + int direction );
5.59 +
5.60 +
5.61 +struct gdrom_image_class linux_device_class = { "Linux", NULL,
5.62 + linux_image_is_valid, linux_open_device };
5.63 +
5.64 +static gboolean linux_image_is_valid( FILE *f )
5.65 +{
5.66 + struct stat st;
5.67 + struct cdrom_tochdr tochdr;
5.68 +
5.69 + if( fstat(fileno(f), &st) == -1 ) {
5.70 + return FALSE; /* can't stat device? */
5.71 + }
5.72 + if( !S_ISBLK(st.st_mode) ) {
5.73 + return FALSE; /* Not a block device */
5.74 + }
5.75 +
5.76 + if( ioctl(fileno(f), CDROMREADTOCHDR, &tochdr) == -1 ) {
5.77 + /* Quick check that this is really a CD */
5.78 + return FALSE;
5.79 + }
5.80 +
5.81 + return TRUE;
5.82 +}
5.83 +
5.84 +static gdrom_disc_t linux_open_device( const gchar *filename, FILE *f )
5.85 +{
5.86 + gdrom_disc_t disc;
5.87 + int fd = fileno(f);
5.88 +
5.89 + disc = gdrom_image_new(f);
5.90 + if( disc == NULL ) {
5.91 + ERROR("Unable to allocate memory!");
5.92 + return NULL;
5.93 + }
5.94 +
5.95 + gdrom_error_t status = linux_read_disc_toc( disc );
5.96 + if( status != 0 ) {
5.97 + free(disc);
5.98 + if( status == 0xFFFF ) {
5.99 + ERROR("Unable to load disc table of contents (%s)", strerror(errno));
5.100 + } else {
5.101 + ERROR("Unable to load disc table of contents (sense %d,%d)",
5.102 + status &0xFF, status >> 8 );
5.103 + }
5.104 + return NULL;
5.105 + }
5.106 + disc->read_sectors = linux_read_sectors;
5.107 + disc->disc_type = IDE_DISC_CDROM;
5.108 + return disc;
5.109 +}
5.110 +
5.111 +/**
5.112 + * Read the full table of contents into the disc from the device.
5.113 + */
5.114 +static gdrom_error_t linux_read_disc_toc( gdrom_disc_t disc )
5.115 +{
5.116 + int fd = fileno(disc->file);
5.117 + unsigned char buf[MAXTOCSIZE];
5.118 + char cmd[12] = { 0x43, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5.119 +
5.120 + cmd[7] = (sizeof(buf))>>8;
5.121 + cmd[8] = (sizeof(buf))&0xFF;
5.122 + memset( buf, 0, sizeof(buf) );
5.123 + gdrom_error_t status = linux_send_command( fd, cmd, buf, sizeof(buf), CGC_DATA_READ );
5.124 + if( status != 0 ) {
5.125 + return status;
5.126 + }
5.127 +
5.128 + int max_track = 0;
5.129 + int last_track = -1;
5.130 + int leadout = -1;
5.131 + int len = (buf[0] << 8) | buf[1];
5.132 + int session_type = GDROM_MODE1;
5.133 + int i;
5.134 + for( i = 4; i<len; i+=11 ) {
5.135 + int session = buf[i];
5.136 + int adr = buf[i+1] >> 4;
5.137 + int point = buf[i+3];
5.138 + if( adr == 0x01 && point > 0 && point < 100 ) {
5.139 + /* Track info */
5.140 + int trackno = point-1;
5.141 + if( point > max_track ) {
5.142 + max_track = point;
5.143 + }
5.144 + disc->track[trackno].flags = (buf[i+1] & 0x0F) << 4;
5.145 + disc->track[trackno].session = session - 1;
5.146 + disc->track[trackno].lba = MSFTOLBA(buf[i+8],buf[i+9],buf[i+10]);
5.147 + if( disc->track[trackno].flags & TRACK_DATA ) {
5.148 + disc->track[trackno].mode = GDROM_MODE1;
5.149 + } else {
5.150 + disc->track[trackno].mode = GDROM_CDDA;
5.151 + }
5.152 + if( last_track != -1 ) {
5.153 + disc->track[last_track].sector_count = disc->track[trackno].lba -
5.154 + disc->track[last_track].lba;
5.155 + }
5.156 + last_track = trackno;
5.157 + } else switch( (adr << 8) | point ) {
5.158 + case 0x1A0: /* session info */
5.159 + if( buf[i+9] == 0x20 ) {
5.160 + session_type = GDROM_MODE2;
5.161 + } else {
5.162 + session_type = GDROM_MODE1;
5.163 + }
5.164 + case 0x1A2: /* leadout */
5.165 + leadout = MSFTOLBA(buf[i+8], buf[i+9], buf[i+10]);
5.166 + break;
5.167 + }
5.168 + }
5.169 + disc->track_count = max_track;
5.170 +
5.171 + if( leadout != -1 && last_track != -1 ) {
5.172 + disc->track[last_track].sector_count = leadout - disc->track[last_track].lba;
5.173 + }
5.174 + return 0;
5.175 +}
5.176 +
5.177 +static gdrom_error_t linux_read_sectors_ioctl( gdrom_disc_t disc, uint32_t sector,
5.178 + uint32_t sector_count, int mode, char *buf,
5.179 + uint32_t *length )
5.180 +{
5.181 + int fd = fileno(disc->file);
5.182 + int call;
5.183 + struct cdrom_read read;
5.184 + read.cdread_lba = LBATOMSF(sector);
5.185 + read.cdread_bufaddr = buf;
5.186 + switch(mode) {
5.187 + case GDROM_MODE1:
5.188 + call = CDROMREADMODE1;
5.189 + read.cdread_buflen = sector_count * 2048;
5.190 + break;
5.191 + case GDROM_MODE2:
5.192 + call = CDROMREADMODE2;
5.193 + read.cdread_buflen = sector_count * 2336;
5.194 + break;
5.195 + default:
5.196 + return PKT_ERR_BADREADMODE;
5.197 + }
5.198 +
5.199 + if( ioctl( fd, call, &read ) == -1 ) {
5.200 + ERROR( "Error reading disc (%s)", strerror(errno) );
5.201 + return PKT_ERR_BADREAD;
5.202 + }
5.203 + *length = read.cdread_buflen;
5.204 + return PKT_ERR_OK;
5.205 +}
5.206 +
5.207 +static gdrom_error_t linux_read_sectors( gdrom_disc_t disc, uint32_t sector,
5.208 + uint32_t sector_count, int mode, char *buf,
5.209 + uint32_t *length )
5.210 +{
5.211 + int fd = fileno(disc->file);
5.212 + uint32_t real_sector = sector - CD_MSF_OFFSET;
5.213 + int buflen = sector_count * 2048;
5.214 + char cmd[12] = { 0xBE, 0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5.215 + cmd[2] = (real_sector >> 24) & 0xFF;
5.216 + cmd[3] = (real_sector >> 16) & 0xFF;
5.217 + cmd[4] = (real_sector >> 8) & 0xFF;
5.218 + cmd[5] = real_sector & 0xFF;
5.219 + cmd[6] = (sector_count >> 16) & 0xFF;
5.220 + cmd[7] = (sector_count >> 8) & 0xFF;
5.221 + cmd[8] = sector_count & 0xFF;
5.222 + cmd[9] = 0x10;
5.223 +
5.224 + gdrom_error_t status = linux_send_command( fd, cmd, buf, buflen, CGC_DATA_READ );
5.225 + if( status == 0 ) {
5.226 + *length = buflen;
5.227 + }
5.228 + return status;
5.229 +}
5.230 +
5.231 +/**
5.232 + * Send a packet command to the device and wait for a response.
5.233 + * @return 0 on success, -1 on an operating system error, or a sense error
5.234 + * code on a device error.
5.235 + */
5.236 +static gdrom_error_t linux_send_command( int fd, char *cmd, char *buffer, size_t buflen,
5.237 + int direction )
5.238 +{
5.239 + struct request_sense sense;
5.240 + struct cdrom_generic_command cgc;
5.241 +
5.242 + memset( &cgc, 0, sizeof(cgc) );
5.243 + memset( &sense, 0, sizeof(sense) );
5.244 + memcpy( cgc.cmd, cmd, 12 );
5.245 + cgc.buffer = buffer;
5.246 + cgc.buflen = buflen;
5.247 + cgc.sense = &sense;
5.248 + cgc.data_direction = direction;
5.249 +
5.250 + if( ioctl(fd, CDROM_SEND_PACKET, &cgc) == -1 ) {
5.251 + if( sense.sense_key == 0 ) {
5.252 + return -1;
5.253 + } else {
5.254 + return sense.sense_key | (sense.asc<<8);
5.255 + }
5.256 + } else {
5.257 + return 0;
5.258 + }
5.259 +}
.