Change to 'safe' copy variant

This commit is contained in:
Ben Gras 2006-06-20 08:54:22 +00:00
parent ad6d8a53c8
commit 3ca26c812d
2 changed files with 58 additions and 26 deletions

View file

@ -14,7 +14,7 @@ MAKE = exec make
CC = exec cc CC = exec cc
CFLAGS = -I$i CFLAGS = -I$i
LDFLAGS = -i LDFLAGS = -i
LIBS = -lsys -lsysutil -ltimers LIBS = -lsysutil -lsys -ltimers
OBJ = floppy.o OBJ = floppy.o
LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o

View file

@ -248,7 +248,7 @@ FORWARD _PROTOTYPE( struct device *f_prepare, (int device) );
FORWARD _PROTOTYPE( char *f_name, (void) ); FORWARD _PROTOTYPE( char *f_name, (void) );
FORWARD _PROTOTYPE( void f_cleanup, (void) ); FORWARD _PROTOTYPE( void f_cleanup, (void) );
FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, off_t position, FORWARD _PROTOTYPE( int f_transfer, (int proc_nr, int opcode, off_t position,
iovec_t *iov, unsigned nr_req) ); iovec_t *iov, unsigned nr_req, int) );
FORWARD _PROTOTYPE( int dma_setup, (int opcode) ); FORWARD _PROTOTYPE( int dma_setup, (int opcode) );
FORWARD _PROTOTYPE( void start_motor, (void) ); FORWARD _PROTOTYPE( void start_motor, (void) );
FORWARD _PROTOTYPE( int seek, (void) ); FORWARD _PROTOTYPE( int seek, (void) );
@ -433,21 +433,24 @@ PRIVATE void f_cleanup()
/*===========================================================================* /*===========================================================================*
* f_transfer * * f_transfer *
*===========================================================================*/ *===========================================================================*/
PRIVATE int f_transfer(proc_nr, opcode, position, iov, nr_req) PRIVATE int f_transfer(proc_nr, opcode, position, iov, nr_req, safe)
int proc_nr; /* process doing the request */ int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER or DEV_SCATTER */ int opcode; /* DEV_GATHER or DEV_SCATTER */
off_t position; /* offset on device to read or write */ off_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */ iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */ unsigned nr_req; /* length of request vector */
int safe;
{ {
#define NO_OFFSET -1
struct floppy *fp = f_fp; struct floppy *fp = f_fp;
iovec_t *iop, *iov_end = iov + nr_req; iovec_t *iop, *iov_end = iov + nr_req;
int s, r, errors; int s, r, errors, nr;
unsigned block; /* Seen any 32M floppies lately? */ unsigned block; /* Seen any 32M floppies lately? */
unsigned nbytes, count, chunk, sector; unsigned nbytes, count, chunk, sector;
unsigned long dv_size = cv64ul(f_dv->dv_size); unsigned long dv_size = cv64ul(f_dv->dv_size);
vir_bytes user_addr; vir_bytes user_offset, iov_offset = 0, iop_offset;
vir_bytes uaddrs[MAX_SECTORS], *up; signed long uoffsets[MAX_SECTORS], *up;
cp_grant_id_t ugrants[MAX_SECTORS], *ug;
u8_t cmd[3]; u8_t cmd[3];
/* Check disk address. */ /* Check disk address. */
@ -478,10 +481,19 @@ unsigned nr_req; /* length of request vector */
if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param)) if (iov->iov_size < SECTOR_SIZE + sizeof(fmt_param))
return(EINVAL); return(EINVAL);
if ((s=sys_datacopy(proc_nr, iov->iov_addr + SECTOR_SIZE, if(safe) {
s=sys_safecopyfrom(proc_nr, iov->iov_addr,
SECTOR_SIZE + iov_offset, (vir_bytes) &fmt_param,
(phys_bytes) sizeof(fmt_param), D);
} else {
s=sys_datacopy(proc_nr, iov->iov_addr +
SECTOR_SIZE + iov_offset,
SELF, (vir_bytes) &fmt_param, SELF, (vir_bytes) &fmt_param,
(phys_bytes) sizeof(fmt_param))) != OK) (phys_bytes) sizeof(fmt_param));
panic("FLOPPY", "Sys_vircopy failed", s); }
if(s != OK)
panic("FLOPPY", "Sys_*copy failed", s);
/* Check that the number of sectors in the data is reasonable, /* Check that the number of sectors in the data is reasonable,
* to avoid division by 0. Leave checking of other data to * to avoid division by 0. Leave checking of other data to
@ -504,23 +516,28 @@ unsigned nr_req; /* length of request vector */
/* For each sector on this track compute the user address it is to /* For each sector on this track compute the user address it is to
* go or to come from. * go or to come from.
*/ */
for (up = uaddrs; up < uaddrs + MAX_SECTORS; up++) *up = 0; for (up = uoffsets; up < uoffsets + MAX_SECTORS; up++) *up = NO_OFFSET;
count = 0; count = 0;
iop = iov; iop = iov;
sector = block % f_sectors; sector = block % f_sectors;
nr = 0;
iop_offset = iov_offset;
for (;;) { for (;;) {
user_addr = iop->iov_addr; nr++;
user_offset = iop_offset;
chunk = iop->iov_size; chunk = iop->iov_size;
if ((chunk & SECTOR_MASK) != 0) return(EINVAL); if ((chunk & SECTOR_MASK) != 0) return(EINVAL);
while (chunk > 0) { while (chunk > 0) {
uaddrs[sector++] = user_addr; ugrants[sector] = iop->iov_addr;
uoffsets[sector++] = user_offset;
chunk -= SECTOR_SIZE; chunk -= SECTOR_SIZE;
user_addr += SECTOR_SIZE; user_offset += SECTOR_SIZE;
count += SECTOR_SIZE; count += SECTOR_SIZE;
if (sector == f_sectors || count == nbytes) if (sector == f_sectors || count == nbytes)
goto track_set_up; goto track_set_up;
} }
iop_offset = 0;
iop++; iop++;
} }
track_set_up: track_set_up:
@ -557,24 +574,32 @@ unsigned nr_req; /* length of request vector */
if (r == OK && read_id() != OK) r = read_id(); if (r == OK && read_id() != OK) r = read_id();
} }
/* Look for the next job in uaddrs[] */ /* Look for the next job in uoffsets[] */
if (r == OK) { if (r == OK) {
for (;;) { for (;;) {
if (fp->fl_sector >= f_sectors) if (fp->fl_sector >= f_sectors)
fp->fl_sector = 0; fp->fl_sector = 0;
up = &uaddrs[fp->fl_sector]; up = &uoffsets[fp->fl_sector];
if (*up != 0) break; ug = &ugrants[fp->fl_sector];
if (*up != NO_OFFSET) break;
fp->fl_sector++; fp->fl_sector++;
} }
} }
if (r == OK && opcode == DEV_SCATTER) { if (r == OK && opcode == DEV_SCATTER) {
/* Copy the user bytes to the DMA buffer. */ /* Copy the user bytes to the DMA buffer. */
if ((s=sys_datacopy(proc_nr, *up, SELF, if(safe) {
s=sys_safecopyfrom(proc_nr, *ug, *up,
(vir_bytes) tmp_buf, (vir_bytes) tmp_buf,
(phys_bytes) SECTOR_SIZE)) != OK) (phys_bytes) SECTOR_SIZE, D);
panic("FLOPPY", "Sys_vircopy failed", s); } else {
s=sys_datacopy(proc_nr, *ug + *up, SELF,
(vir_bytes) tmp_buf,
(phys_bytes) SECTOR_SIZE);
}
if(s != OK)
panic("FLOPPY", "Sys_vircopy failed", s);
} }
/* Set up the DMA chip and perform the transfer. */ /* Set up the DMA chip and perform the transfer. */
@ -591,10 +616,17 @@ unsigned nr_req; /* length of request vector */
if (r == OK && opcode == DEV_GATHER) { if (r == OK && opcode == DEV_GATHER) {
/* Copy the DMA buffer to user space. */ /* Copy the DMA buffer to user space. */
if ((s=sys_datacopy(SELF, (vir_bytes) tmp_buf, if(safe) {
proc_nr, *up, s=sys_safecopyto(proc_nr, *ug, *up,
(phys_bytes) SECTOR_SIZE)) != OK) (vir_bytes) tmp_buf,
panic("FLOPPY", "Sys_vircopy failed", s); (phys_bytes) SECTOR_SIZE, D);
} else {
s=sys_datacopy(SELF, (vir_bytes) tmp_buf,
proc_nr, *ug + *up,
(phys_bytes) SECTOR_SIZE);
}
if(s != OK)
panic("FLOPPY", "Sys_vircopy failed", s);
} }
if (r != OK) { if (r != OK) {
@ -617,12 +649,12 @@ unsigned nr_req; /* length of request vector */
for (;;) { for (;;) {
if (nbytes < iov->iov_size) { if (nbytes < iov->iov_size) {
/* Not done with this one yet. */ /* Not done with this one yet. */
iov->iov_addr += nbytes; iov_offset += nbytes;
iov->iov_size -= nbytes; iov->iov_size -= nbytes;
break; break;
} }
iov_offset = 0;
nbytes -= iov->iov_size; nbytes -= iov->iov_size;
iov->iov_addr += iov->iov_size;
iov->iov_size = 0; iov->iov_size = 0;
if (nbytes == 0) { if (nbytes == 0) {
/* The rest is optional, so we return to give FS a /* The rest is optional, so we return to give FS a
@ -1275,7 +1307,7 @@ int density;
position = (off_t) f_dp->test << SECTOR_SHIFT; position = (off_t) f_dp->test << SECTOR_SHIFT;
iovec1.iov_addr = (vir_bytes) tmp_buf; iovec1.iov_addr = (vir_bytes) tmp_buf;
iovec1.iov_size = SECTOR_SIZE; iovec1.iov_size = SECTOR_SIZE;
result = f_transfer(SELF, DEV_GATHER, position, &iovec1, 1); result = f_transfer(SELF, DEV_GATHER, position, &iovec1, 1, 0);
if (iovec1.iov_size != 0) return(EIO); if (iovec1.iov_size != 0) return(EIO);