FORWARD _PROTOTYPE( int w_specify, (void) );
FORWARD _PROTOTYPE( int w_io_test, (void) );
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_ext, (struct command *cmd) );
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 ack_irqs, (unsigned int) );
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 com_simple, (struct command *cmd) );
FORWARD _PROTOTYPE( void w_timeout, (void) );
FORWARD _PROTOTYPE( int atapi_open, (void) );
FORWARD _PROTOTYPE( void atapi_close, (void) );
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
/* Entry points to this driver. */
if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV)
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. */
if (w_prepare(save_dev) == NIL_DEV)
/*===========================================================================*
* 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 opcode; /* DEV_GATHER or DEV_SCATTER */
off_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
+int safe; /* iov contains addresses (0) or grants? */
{
struct wini *wn = w_wn;
iovec_t *iop, *iov_end = iov + nr_req;
unsigned long dv_size = cv64ul(w_dv->dv_size);
unsigned cylinder, head, sector, nbytes;
unsigned dma_buf_offset;
+ size_t addr_offset = 0;
#if ENABLE_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
-
-
/* Check disk address. */
if ((position & SECTOR_MASK) != 0) return(EINVAL);
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
printf("nbytes = %d\n", nbytes);
#endif
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,
- proc_nr, D, iov->iov_addr, n);
+ proc_nr, D,
+ iov->iov_addr + addr_offset, n);
+ }
if (s != OK)
{
panic(w_name(),
/* Book the bytes successfully transferred. */
nbytes -= n;
position += n;
- iov->iov_addr += n;
- if ((iov->iov_size -= n) == 0)
- { iov++; nr_req--; }
+ if ((iov->iov_size -= n) == 0) {
+ iov++; nr_req--; addr_offset = 0;
+ }
dma_buf_offset += n;
}
}
/* Copy bytes to or from the device's buffer. */
if (opcode == DEV_GATHER) {
- if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr,
- (void *) iov->iov_addr, SECTOR_SIZE)) != OK)
- {
- panic(w_name(),"Call to sys_insw() failed", s);
- }
+ if(safe) {
+ s=sys_safe_insw(wn->base_cmd + REG_DATA, proc_nr,
+ (void *) (iov->iov_addr), addr_offset,
+ 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 {
- if ((s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr,
- (void *) iov->iov_addr, SECTOR_SIZE)) != OK)
- {
- panic(w_name(),"Call to sys_outsw() failed",
- s);
- }
+ if(safe) {
+ s=sys_safe_outsw(wn->base_cmd + REG_DATA, proc_nr,
+ (void *) (iov->iov_addr), addr_offset,
+ SECTOR_SIZE);
+ } 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. */
if ((r = at_intr_wait()) != OK) break;
/* Book the bytes successfully transferred. */
nbytes -= SECTOR_SIZE;
position += SECTOR_SIZE;
- iov->iov_addr += SECTOR_SIZE;
- if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; }
+ addr_offset += SECTOR_SIZE;
+ if ((iov->iov_size -= SECTOR_SIZE) == 0) {
+ iov++;
+ nr_req--;
+ addr_offset = 0;
+ }
}
/* Any errors? */
/*===========================================================================*
* 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;
int proc_nr;
iovec_t *iov;
int do_write;
int *do_copyoutp;
+int safe;
{
phys_bytes phys, user_phys;
unsigned n, offset, size;
n= size;
if (n == 0 || (n & 1))
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)
panic("at_wini", "can't map user buffer", r);
if (user_phys & 1)
if (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,
n);
+ }
if (r != OK)
{
panic(w_name(),
/*===========================================================================*
* 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 opcode; /* DEV_GATHER or DEV_SCATTER */
off_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
+int safe; /* use safecopies? */
{
struct wini *wn = w_wn;
iovec_t *iop, *iov_end = iov + nr_req;
unsigned long dv_size = cv64ul(w_dv->dv_size);
unsigned nbytes, nblocks, count, before, chunk;
static u8_t packet[ATAPI_PACKETSIZE];
+ size_t addr_offset = 0;
errors = fresh = 0;
chunk = nbytes;
if (chunk > count) chunk = count;
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)
- panic(w_name(),"Call to sys_insw() failed", s);
+ if(safe) {
+ 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;
nbytes -= chunk;
count -= chunk;
- iov->iov_addr += chunk;
+ addr_offset += chunk;
fresh = 0;
if ((iov->iov_size -= chunk) == 0) {
iov++;
nr_req--;
fresh = 1; /* new element is optional */
+ addr_offset = 0;
}
}
/*===========================================================================*
* w_other *
*===========================================================================*/
-PRIVATE int w_other(dr, m)
+PRIVATE int w_other(dr, m, safe)
struct driver *dr;
message *m;
+int safe;
{
int r, timeout, prev;
- if (m->m_type != DEV_IOCTL ) {
+ if (m->m_type != DEV_IOCTL && m->m_type != DEV_IOCTL_S ) {
return EINVAL;
}
if (m->REQUEST == DIOCTIMEOUT) {
- if ((r=sys_datacopy(m->IO_ENDPT, (vir_bytes)m->ADDRESS,
- SELF, (vir_bytes)&timeout, sizeof(timeout))) != OK)
- return r;
+ if(safe) {
+ r= sys_safecopyfrom(m->IO_ENDPT, (vir_bytes) m->IO_GRANT,
+ 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) {
/* Restore defaults. */
timeout_ticks = timeout;
}
- if ((r=sys_datacopy(SELF, (vir_bytes)&prev,
- m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(prev))) != OK)
+ if(safe) {
+ 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;
}
int count;
if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO;
count = w_wn->open_ct;
- if ((r=sys_datacopy(SELF, (vir_bytes)&count,
- m->IO_ENDPT, (vir_bytes)m->ADDRESS, sizeof(count))) != OK)
+ if(safe) {
+ 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 OK;
}
return EINVAL;