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:
		
							parent
							
								
									e929676268
								
							
						
					
					
						commit
						3bd3c2cee1
					
				@ -347,15 +347,15 @@ FORWARD _PROTOTYPE( char *w_name, (void) 				);
 | 
			
		||||
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) 				);
 | 
			
		||||
@ -371,7 +371,7 @@ FORWARD _PROTOTYPE( int atapi_intr_wait, (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. */
 | 
			
		||||
@ -1045,7 +1045,7 @@ PRIVATE int w_io_test(void)
 | 
			
		||||
 	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)
 | 
			
		||||
@ -1185,12 +1185,13 @@ PRIVATE int do_transfer(struct wini *wn, unsigned int precomp,
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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;
 | 
			
		||||
@ -1199,15 +1200,14 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
@ -1237,7 +1237,7 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
@ -1314,9 +1314,16 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
 | 
			
		||||
			if (do_copyout)
 | 
			
		||||
			{
 | 
			
		||||
				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(),
 | 
			
		||||
@ -1328,9 +1335,9 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
			/* 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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -1367,15 +1374,30 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
 | 
			
		||||
		/* 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)
 | 
			
		||||
			{
 | 
			
		||||
		   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)
 | 
			
		||||
			{
 | 
			
		||||
		   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);
 | 
			
		||||
		   }
 | 
			
		||||
@ -1387,8 +1409,12 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
		/* 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? */
 | 
			
		||||
@ -1518,12 +1544,13 @@ struct command *cmd;		/* Command block */
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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;
 | 
			
		||||
@ -1555,7 +1582,12 @@ int *do_copyoutp;
 | 
			
		||||
			n= size;
 | 
			
		||||
		if (n == 0 || (n & 1))
 | 
			
		||||
			panic("at_wini", "bad size in iov", iov[i].iov_size);
 | 
			
		||||
		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)
 | 
			
		||||
@ -1635,9 +1667,14 @@ int *do_copyoutp;
 | 
			
		||||
				if (n > iov->iov_size)
 | 
			
		||||
					n= iov->iov_size;
 | 
			
		||||
			
 | 
			
		||||
				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(),
 | 
			
		||||
@ -2069,12 +2106,13 @@ void sense_request(void)
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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;
 | 
			
		||||
@ -2084,6 +2122,7 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
@ -2161,17 +2200,25 @@ unsigned nr_req;		/* length of request vector */
 | 
			
		||||
			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)
 | 
			
		||||
			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;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -2273,19 +2320,27 @@ unsigned cnt;
 | 
			
		||||
/*===========================================================================*
 | 
			
		||||
 *				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)
 | 
			
		||||
		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) {
 | 
			
		||||
@ -2311,8 +2366,17 @@ message *m;
 | 
			
		||||
					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;
 | 
			
		||||
		}
 | 
			
		||||
	
 | 
			
		||||
@ -2321,9 +2385,17 @@ message *m;
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user