Change at driver to understand 'safe' transfers and ioctls; do corresponding

safe copy and safe sys_insw and sys_outsw calls.
This commit is contained in:
Ben Gras 2006-06-20 08:51:24 +00:00
parent e929676268
commit 3bd3c2cee1

View File

@ -347,15 +347,15 @@ FORWARD _PROTOTYPE( char *w_name, (void) );
FORWARD _PROTOTYPE( int w_specify, (void) ); FORWARD _PROTOTYPE( int w_specify, (void) );
FORWARD _PROTOTYPE( int w_io_test, (void) ); FORWARD _PROTOTYPE( int w_io_test, (void) );
FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position, FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
iovec_t *iov, unsigned nr_req) ); iovec_t *iov, unsigned nr_req, int safe));
FORWARD _PROTOTYPE( int com_out, (struct command *cmd) ); FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
FORWARD _PROTOTYPE( int com_out_ext, (struct command *cmd) ); FORWARD _PROTOTYPE( int com_out_ext, (struct command *cmd) );
FORWARD _PROTOTYPE( void setup_dma, (unsigned *sizep, int proc_nr, FORWARD _PROTOTYPE( void setup_dma, (unsigned *sizep, int proc_nr,
iovec_t *iov, int do_write, int *do_copyoutp) ); iovec_t *iov, int do_write, int *do_copyoutp, int safe) );
FORWARD _PROTOTYPE( void w_need_reset, (void) ); FORWARD _PROTOTYPE( void w_need_reset, (void) );
FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) ); FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) );
FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) ); FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) ); FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr, int));
FORWARD _PROTOTYPE( int w_hw_int, (struct driver *dp, message *m_ptr) ); FORWARD _PROTOTYPE( int w_hw_int, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) ); FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) );
FORWARD _PROTOTYPE( void w_timeout, (void) ); FORWARD _PROTOTYPE( void w_timeout, (void) );
@ -371,7 +371,7 @@ FORWARD _PROTOTYPE( int atapi_intr_wait, (void) );
FORWARD _PROTOTYPE( int atapi_open, (void) ); FORWARD _PROTOTYPE( int atapi_open, (void) );
FORWARD _PROTOTYPE( void atapi_close, (void) ); FORWARD _PROTOTYPE( void atapi_close, (void) );
FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode, FORWARD _PROTOTYPE( int atapi_transfer, (int proc_nr, int opcode,
off_t position, iovec_t *iov, unsigned nr_req) ); off_t position, iovec_t *iov, unsigned nr_req, int safe));
#endif #endif
/* Entry points to this driver. */ /* Entry points to this driver. */
@ -1045,7 +1045,7 @@ PRIVATE int w_io_test(void)
if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV) if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV)
panic(w_name(), "Couldn't switch devices", NO_NUM); panic(w_name(), "Couldn't switch devices", NO_NUM);
r = w_transfer(SELF, DEV_GATHER, 0, &iov, 1); r = w_transfer(SELF, DEV_GATHER, 0, &iov, 1, 0);
/* Switch back. */ /* Switch back. */
if (w_prepare(save_dev) == NIL_DEV) if (w_prepare(save_dev) == NIL_DEV)
@ -1185,12 +1185,13 @@ PRIVATE int do_transfer(struct wini *wn, unsigned int precomp,
/*===========================================================================* /*===========================================================================*
* w_transfer * * w_transfer *
*===========================================================================*/ *===========================================================================*/
PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req) PRIVATE int w_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; /* iov contains addresses (0) or grants? */
{ {
struct wini *wn = w_wn; struct wini *wn = w_wn;
iovec_t *iop, *iov_end = iov + nr_req; iovec_t *iop, *iov_end = iov + nr_req;
@ -1199,15 +1200,14 @@ unsigned nr_req; /* length of request vector */
unsigned long dv_size = cv64ul(w_dv->dv_size); unsigned long dv_size = cv64ul(w_dv->dv_size);
unsigned cylinder, head, sector, nbytes; unsigned cylinder, head, sector, nbytes;
unsigned dma_buf_offset; unsigned dma_buf_offset;
size_t addr_offset = 0;
#if ENABLE_ATAPI #if ENABLE_ATAPI
if (w_wn->state & ATAPI) { if (w_wn->state & ATAPI) {
return atapi_transfer(proc_nr, opcode, position, iov, nr_req); return atapi_transfer(proc_nr, opcode, position, iov, nr_req, safe);
} }
#endif #endif
/* Check disk address. */ /* Check disk address. */
if ((position & SECTOR_MASK) != 0) return(EINVAL); if ((position & SECTOR_MASK) != 0) return(EINVAL);
@ -1237,7 +1237,7 @@ unsigned nr_req; /* length of request vector */
if (do_dma) if (do_dma)
{ {
setup_dma(&nbytes, proc_nr, iov, do_write, &do_copyout); setup_dma(&nbytes, proc_nr, iov, do_write, &do_copyout, safe);
#if 0 #if 0
printf("nbytes = %d\n", nbytes); printf("nbytes = %d\n", nbytes);
#endif #endif
@ -1314,9 +1314,16 @@ unsigned nr_req; /* length of request vector */
if (do_copyout) if (do_copyout)
{ {
s= sys_vircopy(SELF, D, if(safe) {
s= sys_safecopyto(proc_nr, iov->iov_addr,
addr_offset,
(vir_bytes)dma_buf+dma_buf_offset, n, D);
} else {
s= sys_vircopy(SELF, D,
(vir_bytes)dma_buf+dma_buf_offset, (vir_bytes)dma_buf+dma_buf_offset,
proc_nr, D, iov->iov_addr, n); proc_nr, D,
iov->iov_addr + addr_offset, n);
}
if (s != OK) if (s != OK)
{ {
panic(w_name(), panic(w_name(),
@ -1328,9 +1335,9 @@ unsigned nr_req; /* length of request vector */
/* Book the bytes successfully transferred. */ /* Book the bytes successfully transferred. */
nbytes -= n; nbytes -= n;
position += n; position += n;
iov->iov_addr += n; if ((iov->iov_size -= n) == 0) {
if ((iov->iov_size -= n) == 0) iov++; nr_req--; addr_offset = 0;
{ iov++; nr_req--; } }
dma_buf_offset += n; dma_buf_offset += n;
} }
} }
@ -1367,18 +1374,33 @@ unsigned nr_req; /* length of request vector */
/* Copy bytes to or from the device's buffer. */ /* Copy bytes to or from the device's buffer. */
if (opcode == DEV_GATHER) { if (opcode == DEV_GATHER) {
if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, if(safe) {
(void *) iov->iov_addr, SECTOR_SIZE)) != OK) s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr,
{ (void *) (iov->iov_addr), addr_offset,
panic(w_name(),"Call to sys_insw() failed", s); SECTOR_SIZE);
} } else {
s=sys_insw(wn->base_cmd + REG_DATA, proc_nr,
(void *) (iov->iov_addr + addr_offset),
SECTOR_SIZE);
}
if(s != OK) {
panic(w_name(),"Call to sys_insw() failed", s);
}
} else { } else {
if ((s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr, if(safe) {
(void *) iov->iov_addr, SECTOR_SIZE)) != OK) s=sys_safe_outsw(wn->base_cmd + REG_DATA, proc_nr,
{ (void *) (iov->iov_addr), addr_offset,
panic(w_name(),"Call to sys_outsw() failed", SECTOR_SIZE);
s); } else {
} s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr,
(void *) (iov->iov_addr + addr_offset),
SECTOR_SIZE);
}
if(s != OK) {
panic(w_name(),"Call to sys_outsw() failed",
s);
}
/* Data sent, wait for an interrupt. */ /* Data sent, wait for an interrupt. */
if ((r = at_intr_wait()) != OK) break; if ((r = at_intr_wait()) != OK) break;
@ -1387,8 +1409,12 @@ unsigned nr_req; /* length of request vector */
/* Book the bytes successfully transferred. */ /* Book the bytes successfully transferred. */
nbytes -= SECTOR_SIZE; nbytes -= SECTOR_SIZE;
position += SECTOR_SIZE; position += SECTOR_SIZE;
iov->iov_addr += SECTOR_SIZE; addr_offset += SECTOR_SIZE;
if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; } if ((iov->iov_size -= SECTOR_SIZE) == 0) {
iov++;
nr_req--;
addr_offset = 0;
}
} }
/* Any errors? */ /* Any errors? */
@ -1518,12 +1544,13 @@ struct command *cmd; /* Command block */
/*===========================================================================* /*===========================================================================*
* setup_dma * * setup_dma *
*===========================================================================*/ *===========================================================================*/
PRIVATE void setup_dma(sizep, proc_nr, iov, do_write, do_copyoutp) PRIVATE void setup_dma(sizep, proc_nr, iov, do_write, do_copyoutp, safe)
unsigned *sizep; unsigned *sizep;
int proc_nr; int proc_nr;
iovec_t *iov; iovec_t *iov;
int do_write; int do_write;
int *do_copyoutp; int *do_copyoutp;
int safe;
{ {
phys_bytes phys, user_phys; phys_bytes phys, user_phys;
unsigned n, offset, size; unsigned n, offset, size;
@ -1555,7 +1582,12 @@ int *do_copyoutp;
n= size; n= size;
if (n == 0 || (n & 1)) if (n == 0 || (n & 1))
panic("at_wini", "bad size in iov", iov[i].iov_size); panic("at_wini", "bad size in iov", iov[i].iov_size);
r= sys_umap(proc_nr, D, iov[i].iov_addr+offset, n, &user_phys); if(safe) {
r= sys_umap(proc_nr, GRANT_SEG, iov[i].iov_addr, n,&user_phys);
user_phys += offset;
} else {
r= sys_umap(proc_nr, D, iov[i].iov_addr+offset, n, &user_phys);
}
if (r != 0) if (r != 0)
panic("at_wini", "can't map user buffer", r); panic("at_wini", "can't map user buffer", r);
if (user_phys & 1) if (user_phys & 1)
@ -1635,9 +1667,14 @@ int *do_copyoutp;
if (n > iov->iov_size) if (n > iov->iov_size)
n= iov->iov_size; n= iov->iov_size;
r= sys_vircopy(proc_nr, D, iov->iov_addr, if(safe) {
r= sys_safecopyfrom(proc_nr, iov->iov_addr,
0, (vir_bytes)dma_buf+offset, n, D);
} else {
r= sys_vircopy(proc_nr, D, iov->iov_addr,
SELF, D, (vir_bytes)dma_buf+offset, SELF, D, (vir_bytes)dma_buf+offset,
n); n);
}
if (r != OK) if (r != OK)
{ {
panic(w_name(), panic(w_name(),
@ -2069,12 +2106,13 @@ void sense_request(void)
/*===========================================================================* /*===========================================================================*
* atapi_transfer * * atapi_transfer *
*===========================================================================*/ *===========================================================================*/
PRIVATE int atapi_transfer(proc_nr, opcode, position, iov, nr_req) PRIVATE int atapi_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; /* use safecopies? */
{ {
struct wini *wn = w_wn; struct wini *wn = w_wn;
iovec_t *iop, *iov_end = iov + nr_req; iovec_t *iop, *iov_end = iov + nr_req;
@ -2084,6 +2122,7 @@ unsigned nr_req; /* length of request vector */
unsigned long dv_size = cv64ul(w_dv->dv_size); unsigned long dv_size = cv64ul(w_dv->dv_size);
unsigned nbytes, nblocks, count, before, chunk; unsigned nbytes, nblocks, count, before, chunk;
static u8_t packet[ATAPI_PACKETSIZE]; static u8_t packet[ATAPI_PACKETSIZE];
size_t addr_offset = 0;
errors = fresh = 0; errors = fresh = 0;
@ -2161,17 +2200,25 @@ unsigned nr_req; /* length of request vector */
chunk = nbytes; chunk = nbytes;
if (chunk > count) chunk = count; if (chunk > count) chunk = count;
if (chunk > iov->iov_size) chunk = iov->iov_size; if (chunk > iov->iov_size) chunk = iov->iov_size;
if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, chunk)) != OK) if(safe) {
panic(w_name(),"Call to sys_insw() failed", s); s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr,
(void *) iov->iov_addr, addr_offset, chunk);
} else {
s=sys_insw(wn->base_cmd + REG_DATA, proc_nr,
(void *) (iov->iov_addr + addr_offset), chunk);
}
if (s != OK)
panic(w_name(),"Call to sys_insw() failed", s);
position += chunk; position += chunk;
nbytes -= chunk; nbytes -= chunk;
count -= chunk; count -= chunk;
iov->iov_addr += chunk; addr_offset += chunk;
fresh = 0; fresh = 0;
if ((iov->iov_size -= chunk) == 0) { if ((iov->iov_size -= chunk) == 0) {
iov++; iov++;
nr_req--; nr_req--;
fresh = 1; /* new element is optional */ fresh = 1; /* new element is optional */
addr_offset = 0;
} }
} }
@ -2273,20 +2320,28 @@ unsigned cnt;
/*===========================================================================* /*===========================================================================*
* w_other * * w_other *
*===========================================================================*/ *===========================================================================*/
PRIVATE int w_other(dr, m) PRIVATE int w_other(dr, m, safe)
struct driver *dr; struct driver *dr;
message *m; message *m;
int safe;
{ {
int r, timeout, prev; int r, timeout, prev;
if (m->m_type != DEV_IOCTL ) { if (m->m_type != DEV_IOCTL && m->m_type != DEV_IOCTL_S ) {
return EINVAL; return EINVAL;
} }
if (m->REQUEST == DIOCTIMEOUT) { if (m->REQUEST == DIOCTIMEOUT) {
if ((r=sys_datacopy(m->IO_ENDPT, (vir_bytes)m->ADDRESS, if(safe) {
SELF, (vir_bytes)&timeout, sizeof(timeout))) != OK) r= sys_safecopyfrom(m->IO_ENDPT, (vir_bytes) m->IO_GRANT,
return r; 0, (vir_bytes)&timeout, sizeof(timeout), D);
} else {
r= sys_datacopy(m->IO_ENDPT, (vir_bytes)m->ADDRESS,
SELF, (vir_bytes)&timeout, sizeof(timeout));
}
if(r != OK)
return r;
if (timeout == 0) { if (timeout == 0) {
/* Restore defaults. */ /* Restore defaults. */
@ -2311,8 +2366,17 @@ message *m;
timeout_ticks = timeout; timeout_ticks = timeout;
} }
if ((r=sys_datacopy(SELF, (vir_bytes)&prev, if(safe) {
m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(prev))) != OK) r= sys_safecopyto(m->IO_ENDPT,
(vir_bytes) m->IO_GRANT,
0, (vir_bytes)&prev, sizeof(prev), D);
} else {
r=sys_datacopy(SELF, (vir_bytes)&prev,
m->IO_ENDPT, (vir_bytes)m->ADDRESS,
sizeof(prev));
}
if(r != OK)
return r; return r;
} }
@ -2321,9 +2385,17 @@ message *m;
int count; int count;
if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO; if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO;
count = w_wn->open_ct; count = w_wn->open_ct;
if ((r=sys_datacopy(SELF, (vir_bytes)&count, if(safe) {
m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(count))) != OK) r= sys_safecopyto(m->IO_ENDPT, (vir_bytes) m->IO_GRANT,
0, (vir_bytes)&count, sizeof(count), D);
} else {
r=sys_datacopy(SELF, (vir_bytes)&count,
m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(count));
}
if(r != OK)
return r; return r;
return OK; return OK;
} }
return EINVAL; return EINVAL;