summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-07-11 03:03:47 +0000
committerjkh <jkh@FreeBSD.org>1995-07-11 03:03:47 +0000
commit66148ceb44672cde4778f7a1e86d0a7be46cebea (patch)
tree3628fb950686ab6ba6661cb4bece3ce4c49c5ffe /sys/i386/isa
parent919efb0db9f1afbda0d6ea3f2a40b3ce5a4fb566 (diff)
downloadFreeBSD-src-66148ceb44672cde4778f7a1e86d0a7be46cebea.zip
FreeBSD-src-66148ceb44672cde4778f7a1e86d0a7be46cebea.tar.gz
Release summary: (detailed descriptions in Edit History in matcd.c)
Adds support for non-Sound Blaster host adapters, including those distributed by Reveal, Lasermate, IBM, Media Vision, Crystal and others. The driver automatically senses the correct adapter type and you can have both in the system at the same time. (This change should eliminate a few complaints.) Corrected bit-masking problem that prevented use on SB Vibra-16 boards. Declared some internal data and functions static that should have been that way all along. Documentation changes reflect the new hardware support and change the appearance version to 2.0.5 (was 2.1). Nice and tidy. :-) Beta testers have verified functionality on SB16, Vibra-16, Media Vision and Reveal adapters. -Wall still shows no warnings. Frank Durda IV uhclem%nemesis@fw.ast.com Submitted by: Frank Durda IV <uhclem%nemesis@fw.ast.com>
Diffstat (limited to 'sys/i386/isa')
-rw-r--r--sys/i386/isa/matcd/TODO22
-rw-r--r--sys/i386/isa/matcd/creative.h1
-rw-r--r--sys/i386/isa/matcd/matcd.c195
3 files changed, 150 insertions, 68 deletions
diff --git a/sys/i386/isa/matcd/TODO b/sys/i386/isa/matcd/TODO
index 62035fc..138f470 100644
--- a/sys/i386/isa/matcd/TODO
+++ b/sys/i386/isa/matcd/TODO
@@ -1,43 +1,35 @@
-Things to do for the matcd driver 6-Apr-95
+Things to do for the matcd driver 4-Jul-95
-1. Just as I was finishing Edit 16, I discovered that there
- may be a way to cause a drive to go "offline", allowing the host
- to send a command to one or more other drives on the same
- interface, similar to the SCSI disconnect mechanism. The changes
- to the driver to take advantage of this aren't huge, but will have
- to wait until after 2.1. Too much risk of breaking something.
- Unless you have multiple drives, you won't see a difference.
-
-2. Someone wants to switch all drivers from disklabel and
+1. Someone wants to switch all drivers from disklabel and
its assorted mechanisms over to disk slicing and its mechanisms,
but I was unable to find any useful documentation on how to
implement the changes for a read-only, single-partition,
removable (ie, partition can change size) device.
So this will have to wait until after 2.1.
-3. Support for reading R-W subcodes while playing audio. This would be
+2. Support for reading R-W subcodes while playing audio. This would be
useful if you have any CD+G or CD+MIDI discs, but the demand for this
is pretty low, unless you like Karaoke. Someone will also have to
write a CD+G viewer for X. The code for the driver to add this is
pretty minor but there aren't any precedents on how to handle the
data transfer to the application.
-4. Support for reading the ISBN and UPC labels. The ioctl structures
+3. Support for reading the ISBN and UPC labels. The ioctl structures
for these appear to be defined but no other driver seems to do this.
-5. Multi-session support. There are two forms of this; what
+4. Multi-session support. There are two forms of this; what
Philips defined and what Kodak uses. This will be quite
complicated and will probably require changes in the filesystem
layer. The drive support for Kodak multi-session is known to work.
-6. Multiple data tracks. My vision here was to add an ioctl
+5. Multiple data tracks. My vision here was to add an ioctl
that caused a track offset to be inserted into block requests,
effectively shifting the base to the specified track. Very
easy to add but not a big deal since I have only two discs
in my collection that have multiple data tracks and I mastered
one of them.
-7. A curses-based CD-Player app (ie, not X). I will probably do this
+6. A curses-based CD-Player app (ie, not X). I will probably do this
mainly for its value as a debugging tool. It was pretty annoying
not finding a single application that actually issued all the
defined ioctls, let alone any new ones.
diff --git a/sys/i386/isa/matcd/creative.h b/sys/i386/isa/matcd/creative.h
index b918e48..0877a78 100644
--- a/sys/i386/isa/matcd/creative.h
+++ b/sys/i386/isa/matcd/creative.h
@@ -102,6 +102,7 @@ See matcd.c for Edit History
#define STATUS 1 /*Read - bus status*/
#define RESET 2 /*Write - reset all attached drives*/
/*Any value written will reset*/
+#define ALTDATA 2 /*<20>Read - data on non Creative bds.*/
#define SELECT 3 /*Write - drive select*/
diff --git a/sys/i386/isa/matcd/matcd.c b/sys/i386/isa/matcd/matcd.c
index e57f387..1b18b4d 100644
--- a/sys/i386/isa/matcd/matcd.c
+++ b/sys/i386/isa/matcd/matcd.c
@@ -220,10 +220,59 @@ Edit number code marking begins here - earlier edits were during development.
under FreeBSD 1.1.5.1 as well as 2.0 and early 2.1.
4-Apr-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+<17> The function matcd_toc_entries which is executed in response to
+ the CDIOREADTOCENTRYS ioctl didn't cope with programs that only
+ requested part of the TOC. This change is based on code submitted
+ by Doug Robson (dfr@render.com).
+ (This change was introduced out of order and exists in FreeBSD
+ 2.0.5 without the version stamp being updated. I.N.M.F.)
+ 1-Jun-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
+<18> While working on the TEAC CD-ROM driver (teaccd) that is reusing
+ chunks of code from this driver, I discovered several functions,
+ arrays and other things that should have been declared 'static'.
+ These changes are necessary if the TEAC CD-ROM driver is to be
+ present at the same time as matcd.
+ Also fixed the residual buss vs bus symbols and strings.
+ There are no functional code changes in this edit.
+ 2-May-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
+<19> Creative has changed the Status port slightly in their
+ sound boards based on the Vibra-16 (and probably the Vibra-16S)
+ chipset. This change masks some unused bits that were formally
+ on all the time and are doing different things in this design.
+ The changes are transparent to all other supported boards.
+ 20-Jun-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
+<20> Code was added to detect non-Creative (SoundBlaster) host
+ interfaces, and the driver will switch to code compatible with the
+ detected host interface. This should add support for MediaVision,
+ IBM, Reveal, and other compatible adapters with split
+ data/status-ports. This code allows a mix of SoundBlaster (Type 0)
+ and non-SoundBlaster (Type 1) boards in the same system with no
+ special configuration.
+
+ I also updated the attach code to display the interface type and
+ changed the host interface probe messages to reflect the "c" for
+ controller in controller-specific messages as the existing messages
+ were confusing when a second card was in place . The kernel -c
+ tables have been updated accordingly, so you now have a matcdc%d
+ controller to change settings on.
+ 24-Jun-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
+<21> Added interface handling code in two of those "this should not
+ happen" routines, draincmd and get_stat. Since these routines are
+ called by functions during probing that may not know what type
+ interface is out there, the code assumes that a given adapter is
+ both a type 0 and a type 1 adapter at the same time. Plus,
+ this code gets executed once in a very long time so the cost of
+ assuming both host adapter types is not significant.
+ 4-Jul-95 Frank Durda IV bsdmail@nemesis.lonestar.org
+
---------------------------------------------------------------------------*/
/*Match this format: Version_dc(d)__dd-mmm-yy */
-static char MATCDVERSION[]="Version 1(16) 4-Apr-95";
+static char MATCDVERSION[]="Version 1(21) 4-Jul-95";
/* The following strings may not be changed*/
static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank Durda IV";
@@ -274,7 +323,7 @@ static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank
#define DIAGOUT outb /*<10>*/
#endif /*DIAGPORT*/ /*<10>*/
#ifdef DIAGPORT
-int diagloop; /*Used to show looping*/
+static int diagloop; /*<18>Used to show looping*/
#endif /*DIAGPORT*/
@@ -309,6 +358,7 @@ struct matcd_mbx {
short ldrive;
short partition;
short port;
+ short iftype; /*<20>Host interface type*/
short retry;
short nblk;
int sz;
@@ -318,14 +368,15 @@ struct matcd_mbx {
short count;
};
-struct matcd_data {
+static struct matcd_data { /*<18>*/
short config;
short drivemode; /*Last state drive was set to*/
short flags;
short status; /*Last audio-related function*/
int blksize;
u_long disksize;
- int iobase;
+ short iobase; /*<20>*/
+ short iftype; /*<20>Host interface type*/
struct disklabel dlabel;
int partflags[MAXPARTITIONS];
int openflags;
@@ -357,16 +408,17 @@ struct matcd_data {
#define ERR_FATAL 3 /*This cannot be recovered from*/
-struct buf request_head[NUMCTRLRS]; /*A queue for each host interface*/
- int nextcontroller=0; /*Number of interface units found*/
- int drivepresent=0; /*Don't change this - see license*/
+static struct buf request_head[NUMCTRLRS]; /*<18>A queue for each host interface*/
+static int nextcontroller=0; /*<18>Number of interface units found*/
+static int drivepresent=0; /*<18>Don't change this - see license*/
+static int iftype; /*<20>Probe/Attach i.f. type relay*/
-unsigned char if_state[4]={0,0,0,0}; /*State of the host I/F and bus*/
+static unsigned char if_state[4]={0,0,0,0}; /*<18>State of the host I/F and bus*/
/* Flags in the if_state array
*/
-#define BUSSBUSY 0x01 /*Buss is already busy*/
+#define BUSBUSY 0x01 /*<18>Bus is already busy*/
struct matcd_read2 {
@@ -382,7 +434,7 @@ struct matcd_read2 {
#ifdef FREE2
static struct kern_devconf kdc_matcd[TOTALDRIVES] = { { /*<12>*/
0,0,0, /*Filled in by dev_attach*/
- "matcd",0,{MDDT_ISA,0,"bio"}, /*<12>*/
+ "matcdc",0,{MDDT_ISA,0,"bio"}, /*<20>*/
isa_generic_externalize,0,0,ISA_EXTERNALLEN, /*<12>*/
&kdc_isa0, /*<12>Parent*/
0, /*<12>Parent Data*/
@@ -434,7 +486,7 @@ extern int hz;
extern int matcd_probe(struct isa_device *dev);
extern int matcd_attach(struct isa_device *dev);
struct isa_driver matcddriver={matcd_probe, matcd_attach, /*<16>*/
- "matcd"}; /*<16>*/
+ "matcdc"}; /*<20>*/
/*---------------------------------------------------------------------------
@@ -610,7 +662,7 @@ int matcdopen(dev_t dev)
i=matcdsize(dev);
unlockbus(controller, ldrive); /*Release bus lock*/
#ifdef DEBUGOPEN
- printf("matcd%d: Buss unlocked in open\n",ldrive);
+ printf("matcd%d: Bus unlocked in open\n",ldrive);/*<18>*/
#endif /*DEBUGOPEN*/
if (i < 0) {
printf("matcd%d: Could not read the disc size\n",ldrive);
@@ -863,7 +915,7 @@ static void matcd_start(struct buf *dp)
printf("matcd%d: In start controller %d\n",ldrive,controller);
#endif /*DEBUGIO*/
- if (if_state[controller] & BUSSBUSY) {
+ if (if_state[controller] & BUSBUSY) { /*<18>*/
#ifdef DEBUGIO
printf("matcd%d: Dropping thread in start, controller %d\n",
ldrive,controller);
@@ -884,11 +936,12 @@ static void matcd_start(struct buf *dp)
part=matcd_partition(bp->b_dev);
p=cd->dlabel.d_partitions + part;
- if_state[controller] |= BUSSBUSY;/*Mark bus as busy*/
+ if_state[controller] |= BUSBUSY;/*<18>Mark bus as busy*/
cd->mbx.ldrive=ldrive; /*Save current logical drive*/
cd->mbx.controller=controller; /*and controller*/
cd->mbx.partition=part; /*and partition (2048 vs 2532)*/
cd->mbx.port=cd->iobase; /*and port#*/
+ cd->mbx.iftype=cd->iftype; /*<20>interface type*/
cd->mbx.retry=MATCD_RETRYS; /*and the retry count*/
cd->mbx.bp=bp; /*and the bp*/
cd->mbx.p_offset=p->p_offset; /*and where the data will go*/
@@ -1185,7 +1238,7 @@ int matcd_probe(struct isa_device *dev)
}
#else /*AUTOHUNT*/
if (port==-1) {
- printf("matcd%d: AUTOHUNT disabled but port? specified in config\n",
+ printf("matcdc%d: AUTOHUNT disabled but port? specified in config\n",
nextcontroller);
return(0);
}
@@ -1197,11 +1250,17 @@ int matcd_probe(struct isa_device *dev)
/*---------------------------------------------------------------------------
doprobe - Common probe code that actually checks the ports we
have decided to test.
+
+<20> Edit 20 changes adds code to determine if the host interface
+ is one that behaves like the Creative SoundBlaster cards,
+ or whether the host interface like those used by some boards
+ made by Media Vision and a version known as Lasermate.
---------------------------------------------------------------------------*/
int doprobe(int port,int cdrive)
{
unsigned char cmd[MAXCMDSIZ];
+ int i; /*<20>*/
#ifdef RESETONBOOT
doreset(port,cdrive); /*Reset what might be our device*/
@@ -1214,11 +1273,20 @@ int doprobe(int port,int cdrive)
#ifdef RESETONBOOT
if (((inb(port+STATUS) & (DTEN|STEN)) != (DTEN|STEN)) || /*<16>*/
(inb(port+DATA) != 0xff)) /*<16>*/
- return(1); /*<16>Something detected but it isn't
+ return(-1); /*<20>Something detected but it isn't
the device we wanted*/
#endif /*RESETONBOOT*/
if (matcd_fastcmd(port,0,0,cmd)==0) {/*Issue command*/
- inb(port+CMD); /*Read status byte*/
+ outb(port+PHASE,1); /*<20>Switch to Creative Data phase*/
+ i=inb(port+CMD); /*<20>Read a byte in data phase*/
+ outb(port+PHASE,0); /*<20>Switch to Creative Status phase*/
+ if ((inb(port+STATUS) & (DTEN|STEN))
+ == (DTEN|STEN)) { /*<20>Drive went idle*/
+ iftype=1; /*<20>It is not a Creative interface.*/
+ } else { /*<20>Status byte still available*/
+ iftype=0; /*<20>*/
+ inb(port+CMD); /*<20>Read status byte*/
+ }
#ifdef DEBUGPROBE
printf("matcdc%d: Probe found something\n",nextcontroller);
#endif /*DEBUGPROBE*/
@@ -1237,7 +1305,7 @@ int doprobe(int port,int cdrive)
#ifdef DEBUGPROBE
printf("matcdc%d: Probe DID NOT find something\n",nextcontroller);
#endif /*DEBUGPROBE*/
- return(1); /*Nothing detected*/
+ return(1);
}
@@ -1287,6 +1355,8 @@ int matcd_attach(struct isa_device *dev)
printf("matcdc: Attach dev %x id_unit %d\n",
(unsigned int)dev,dev->id_unit);
#endif /*DEBUGPROBE*/
+ printf("matcdc%d Host interface type %d\n", /*<20>*/
+ nextcontroller,iftype); /*<20>*/
for (cdrive=0; cdrive<4; cdrive++) { /*We're hunting drives...*/
zero_cmd(cmd);
cmd[0]=NOP; /*A reasonably harmless command.
@@ -1317,6 +1387,7 @@ int matcd_attach(struct isa_device *dev)
cd=&matcd_data[i];
cd->flags |= MATCDINIT;
cd->iobase=dev->id_iobase;
+ cd->iftype=iftype; /*<20>*/
cd->openflags=0;
cd->volume[0]=cd->volume[1]=DEFVOL; /*<12>*/
/*<12>Match volume drive resets to*/
@@ -1496,7 +1567,7 @@ void draincmd(int port,int cdrive,int ldrive)
int i,z;
i=inb(port+STATUS);
- if (i==0xff) return;
+ if ((i & (DTEN|STEN)) == (DTEN|STEN)) return; /*<19>*/
printf("matcd%d: in draincmd: bus not idle %x - trying to fix\n",
ldrive,inb(port+STATUS));
@@ -1507,7 +1578,8 @@ void draincmd(int port,int cdrive,int ldrive)
i=0;
outb(port+PHASE,1); /*<16>Enable data read*/
while ((inb(port+STATUS) & (DTEN|STEN)) == STEN) {
- inb(port+DATA);
+ inb(port+DATA); /*<21>Ok for Creative*/
+ inb(port+ALTDATA); /*<21>Ok for others*/
i++;
}
outb(port+PHASE,0); /*<16>*/
@@ -1523,8 +1595,8 @@ void draincmd(int port,int cdrive,int ldrive)
#ifdef DEBUGCMD
printf("Data byte %x and status is now %x\n",i,z);
#endif /*DEBUGCMD*/
- if (z!=0xff) {
- printf("matcd%d: Buss not idle %x - resetting\n",
+ if ((z & (DTEN|STEN)) != (DTEN|STEN)) { /*<19>*/
+ printf("matcd%d: Bus not idle %x - resetting\n",/*<18>*/
cdrive,inb(port+STATUS));
doreset(port,cdrive);
}
@@ -1765,6 +1837,7 @@ static void matcd_blockread(int state)
struct matcd_mbx *mbx;
int ldrive,cdrive;
int port;
+ short iftype; /*<20>*/
struct buf *bp;
struct buf *dp;
struct matcd_data *cd;
@@ -1784,6 +1857,7 @@ static void matcd_blockread(int state)
ldrive=mbx->ldrive; /*ldrive is logical drive #*/
cdrive=ldrive & 0x03; /*cdrive is drive # on a controller*/
port=mbx->port; /*port is base port for i/f*/
+ iftype=mbx->iftype; /*<20>*/
bp= mbx->bp;
cd=&matcd_data[ldrive];
@@ -1883,21 +1957,34 @@ nextblock:
#ifdef DEBUGIO
printf("matcd%d: Data Phase\n",ldrive);
#endif /*DEBUGIO*/
- outb(port+PHASE,1); /*Enable data read*/
addr=bp->b_un.b_addr + mbx->skip;
#ifdef DEBUGIO
printf("matcd%d: Xfer Addr %x size %x",
ldrive,(unsigned int)addr,mbx->sz);
+ i=0; /*<20>Reset read count*/
#endif /*DEBUGIO*/
- i=0;
- while(inb(port+STATUS)==0xfd) {
- *addr++=inb(port+DATA);
- i++;
- }
+ if (iftype==0) { /*<20>Creative host I/F*/
+ outb(port+PHASE,1); /*Enable data read*/
+ while((inb(port+STATUS) &
+ (DTEN|STEN))==STEN) {/*<19>*/
+ *addr++=inb(port+DATA);
+#ifdef DEBUGIO
+ i++;
+#endif /*DEBUGIO*/
+ }
+ outb(port+PHASE,0); /*Disable read*/
+ } else { /*<20>Not Creative interface*/
+ while((inb(port+STATUS) & /*<20>*/
+ (DTEN|STEN))==STEN) { /*<20>*/
+ *addr++=inb(port+ALTDATA);/*<20>*/
+#ifdef DEBUGIO
+ i++; /*<20>*/
+#endif /*DEBUGIO*/
+ } /*<20>*/
+ } /*<20>*/
#ifdef DEBUGIO
printf("matcd%d: Read %d bytes\n",ldrive,i);
#endif /*DEBUGIO*/
- outb(port+PHASE,0); /*Disable data read*/
/* Now, wait for the Status phase to arrive. This will also
@@ -2102,7 +2189,7 @@ int get_stat(int port,int ldrive)
int status,busstat; /*<16>*/
status=inb(port+DATA); /*Read status byte, last step of cmd*/
busstat=inb(port+STATUS); /*<16>Get bus status - should be 0xff*/
- while (busstat!=0xff) { /*<16>*/
+ while ((busstat & (DTEN|STEN)) != (DTEN|STEN)) { /*<19>*/
printf("matcd%d: get_stat: After reading status byte, bus didn't go idle %x %x %x\n",ldrive,status,busstat,port); /*<16>*/
if (( busstat & (DTEN|STEN)) == STEN) { /*<16>*/
int k;
@@ -2113,6 +2200,7 @@ int get_stat(int port,int ldrive)
outb(port+PHASE,1); /*Enable data read*/
while ((inb(port+STATUS) & (DTEN|STEN)) == STEN) {
inb(port+DATA);
+ inb(port+ALTDATA); /*<21>*/
/* printf("%2x ",inb(port+DATA));*/
k++;
}
@@ -2192,7 +2280,7 @@ static void watchdog(int state, char * foo)
void lockbus(int controller, int ldrive)
{
- while ((if_state[controller] & BUSSBUSY)) {
+ while ((if_state[controller] & BUSBUSY)) { /*<18>*/
#ifdef DEBUGSLEEP
printf("matcd%d: Can't do it now - going to sleep\n",
ldrive);
@@ -2203,12 +2291,12 @@ void lockbus(int controller, int ldrive)
tsleep((caddr_t)&matcd_data->status, PRIBIO,
"matcdopen", 0);
}
- if_state[controller] |= BUSSBUSY; /*It's ours NOW*/
+ if_state[controller] |= BUSBUSY; /*<18>It's ours NOW*/
#ifdef DIAGPORT
DIAGOUT(DIAGPORT,0xF2); /*Show where we are*/
#endif /*DIAGPORT*/
#ifdef DEBUGSLEEP
- printf("matcd%d: BUSS locked in lockbus\n",ldrive);
+ printf("matcd%d: BUS locked in lockbus\n",ldrive); /*<18>*/
#endif /*DEBUGSLEEP*/
}
@@ -2224,9 +2312,9 @@ void unlockbus(int controller, int ldrive)
#ifdef DIAGPORT
DIAGOUT(DIAGPORT,0xF4); /*Show where we are*/
#endif /*DIAGPORT*/
- if_state[controller] &= ~BUSSBUSY;
+ if_state[controller] &= ~BUSBUSY; /*<18>*/
#ifdef DEBUGSLEEP
- printf("matcd%d: busunlocked\n",ldrive);
+ printf("matcd%d: bus unlocked\n",ldrive); /*<18>*/
#endif /*DEBUGSLEEP*/
wakeup((caddr_t)&matcd_data->status); /*Wakeup other users*/
matcd_start(&request_head[controller]); /*Wake up any block I/O*/
@@ -2349,8 +2437,10 @@ static int matcd_toc_entries(int ldrive, int cdrive, int controller,
struct ioc_read_toc_entry * ioc_entry)
{
struct matcd_data *cd;
- struct cd_toc_entry entries[MAXTRKS];
- int trk,i,z,port;
+ struct cd_toc_entry entries[MAXTRKS];
+ struct cd_toc_entry *from; /*<17>*/
+ struct cd_toc_entry *to; /*<17>*/
+ int len,trk,i,z,port; /*<17>*/
unsigned char cmd[MAXCMDSIZ];
unsigned char data[5];
@@ -2405,22 +2495,21 @@ static int matcd_toc_entries(int ldrive, int cdrive, int controller,
array from the kernel address space into the user address space
*/
- {
- int len = ioc_entry->data_len;
- int i = ioc_entry->starting_track - 1;
- struct cd_toc_entry* from = &entries[i];
- struct cd_toc_entry* to = ioc_entry->data;
-
- while (i < trk && len >= sizeof(struct cd_toc_entry)) {
- if (copyout(from, to, sizeof(struct cd_toc_entry)) != 0) {
- return (EFAULT);
- }
- i++;
- len -= sizeof(struct cd_toc_entry);
- from++;
- to++;
- }
- }
+ len=ioc_entry->data_len; /*<17>*/
+ i=ioc_entry->starting_track - 1;/*<17>*/
+ from = &entries[i]; /*<17>*/
+ to = ioc_entry->data; /*<17>*/
+
+ while (i < trk && len >= sizeof(struct cd_toc_entry)) { /*<17>*/
+ if (copyout(from,to,sizeof(struct cd_toc_entry))/*<17>*/
+ != 0) { /*<17>*/
+ return (EFAULT);/*<17>*/
+ } /*<17>*/
+ i++; /*<17>*/
+ len -= sizeof(struct cd_toc_entry); /*<17>*/
+ from++; /*<17>*/
+ to++; /*<17>*/
+ } /*<17>*/
return(0);
}
OpenPOWER on IntegriCloud