コード例 #1
0
ファイル: memory.c プロジェクト: sebhtml/minix
/*===========================================================================*
 *				m_transfer				     *
 *===========================================================================*/
static int m_transfer(
  endpoint_t endpt,		/* endpoint of grant owner */
  int opcode,			/* DEV_GATHER_S or DEV_SCATTER_S */
  u64_t pos64,			/* offset on device to read or write */
  iovec_t *iov,			/* pointer to read or write request vector */
  unsigned int nr_req,		/* length of request vector */
  endpoint_t UNUSED(user_endpt),/* endpoint of user process */
  unsigned int UNUSED(flags)
)
{
/* Read or write one the driver's character devices. */
  unsigned count, left, chunk;
  vir_bytes vir_offset = 0;
  struct device *dv;
  unsigned long dv_size;
  int s, r;
  off_t position;
  cp_grant_id_t grant;
  vir_bytes dev_vaddr;

  /* ZERO_DEV and NULL_DEV are infinite in size. */
  if (m_device != ZERO_DEV && m_device != NULL_DEV && ex64hi(pos64) != 0)
	return OK;	/* Beyond EOF */
  position= cv64ul(pos64);

  /* Get minor device number and check for /dev/null. */
  dv = &m_geom[m_device];
  dv_size = cv64ul(dv->dv_size);
  dev_vaddr = m_vaddrs[m_device];

  while (nr_req > 0) {

	/* How much to transfer and where to / from. */
	count = iov->iov_size;
	grant = (cp_grant_id_t) iov->iov_addr;

	switch (m_device) {

	/* No copying; ignore request. */
	case NULL_DEV:
	    if (opcode == DEV_GATHER_S) return(OK);	/* always at EOF */
	    break;

	/* Virtual copying. For kernel memory. */
	default:
	case KMEM_DEV:
	    if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
		printf("MEM: dev %d not initialized\n", m_device);
		return EIO;
	    }
	    if (position >= dv_size) return(OK);	/* check for EOF */
	    if (position + count > dv_size) count = dv_size - position;
	    if (opcode == DEV_GATHER_S) {	/* copy actual data */
	        r=sys_safecopyto(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	    } else {
	        r=sys_safecopyfrom(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	    }
	    if(r != OK) {
              panic("I/O copy failed: %d", r);
	    }
	    break;

	/* Physical copying. Only used to access entire memory.
	 * Transfer one 'page window' at a time.
	 */
	case MEM_DEV:
	{
	    u32_t pagestart, page_off;
	    static u32_t pagestart_mapped;
	    static int any_mapped = 0;
	    static char *vaddr;
	    int r;
	    u32_t subcount;
	    phys_bytes mem_phys;

	    if (position >= dv_size)
		return(OK);	/* check for EOF */
	    if (position + count > dv_size)
		count = dv_size - position;
	    mem_phys = position;

	    page_off = mem_phys % PAGE_SIZE;
	    pagestart = mem_phys - page_off; 

	    /* All memory to the map call has to be page-aligned.
	     * Don't have to map same page over and over.
	     */
	    if(!any_mapped || pagestart_mapped != pagestart) {
	     if(any_mapped) {
		if(vm_unmap_phys(SELF, vaddr, PAGE_SIZE) != OK)
			panic("vm_unmap_phys failed");
		any_mapped = 0;
	     }
	     vaddr = vm_map_phys(SELF, (void *) pagestart, PAGE_SIZE);
	     if(vaddr == MAP_FAILED) 
		r = ENOMEM;
	     else
		r = OK;
	     if(r != OK) {
		printf("memory: vm_map_phys failed\n");
		return r;
	     }
	     any_mapped = 1;
	     pagestart_mapped = pagestart;
	   }

	    /* how much to be done within this page. */
	    subcount = PAGE_SIZE-page_off;
	    if(subcount > count)
		subcount = count;

	    if (opcode == DEV_GATHER_S) {			/* copy data */
	           s=sys_safecopyto(endpt, grant,
		       vir_offset, (vir_bytes) vaddr+page_off, subcount);
	    } else {
	           s=sys_safecopyfrom(endpt, grant,
		       vir_offset, (vir_bytes) vaddr+page_off, subcount);
	    }
	    if(s != OK)
		return s;
	    count = subcount;
	    break;
	}

	/* Null byte stream generator. */
	case ZERO_DEV:
	    if (opcode == DEV_GATHER_S) {
		size_t suboffset = 0;
	        left = count;
		while (left > 0) {
		    chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
	             s=sys_safecopyto(endpt, grant,
		       vir_offset+suboffset, (vir_bytes) dev_zero, chunk);
		    if(s != OK)
		        return s;
		    left -= chunk;
	            suboffset += chunk;
		}
	    }
	    break;

	}

	/* Book the number of bytes transferred. */
	position += count;
	vir_offset += count;
	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }

  }
  return(OK);
}
コード例 #2
0
ファイル: memory.c プロジェクト: sebhtml/minix
/*===========================================================================*
 *				m_block_transfer			     *
 *===========================================================================*/
static int m_block_transfer(
  dev_t minor,			/* minor device number */
  int do_write,			/* read or write? */
  u64_t pos64,			/* offset on device to read or write */
  endpoint_t endpt,		/* process doing the request */
  iovec_t *iov,			/* pointer to read or write request vector */
  unsigned int nr_req,		/* length of request vector */
  int UNUSED(flags)		/* transfer flags */
)
{
/* Read or write one the driver's block devices. */
  unsigned count;
  vir_bytes vir_offset = 0;
  struct device *dv;
  unsigned long dv_size;
  int r;
  off_t position;
  vir_bytes dev_vaddr;
  cp_grant_id_t grant;
  ssize_t total = 0;

  /* Get minor device information. */
  if ((dv = m_block_part(minor)) == NULL) return(ENXIO);
  dv_size = cv64ul(dv->dv_size);
  dev_vaddr = m_vaddrs[minor];

  if (ex64hi(pos64) != 0)
	return OK;	/* Beyond EOF */
  position= cv64ul(pos64);

  while (nr_req > 0) {

	/* How much to transfer and where to / from. */
	count = iov->iov_size;
	grant = (cp_grant_id_t) iov->iov_addr;

	/* Virtual copying. For RAM disks and internal FS. */
	if(!dev_vaddr || dev_vaddr == (vir_bytes) MAP_FAILED) {
		printf("MEM: dev %d not initialized\n", minor);
		return EIO;
	}
	if (position >= dv_size) return(total);	/* check for EOF */
	if (position + count > dv_size) count = dv_size - position;
	if (!do_write) {	/* copy actual data */
	        r=sys_safecopyto(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	} else {
	        r=sys_safecopyfrom(endpt, grant, vir_offset,
		  dev_vaddr + position, count);
	}
	if(r != OK) {
		panic("I/O copy failed: %d", r);
	}

	/* Book the number of bytes transferred. */
	position += count;
	vir_offset += count;
	total += count;
	if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }

  }
  return(total);
}
コード例 #3
0
ファイル: mkswap.c プロジェクト: aunali1/Minix2.0.4-RPi
int main(int argc, char **argv)
{
    int first;
    int i;
    char *file;
    unsigned long offset, size, devsize;
    int fd;
    struct stat st;
    ssize_t r;
    struct super_block super;
    swap_hdr_t swap_hdr;
    u8_t block[BLOCK_SIZE];

    first= 0;
    i= 1;
    while (i < argc && argv[i][0] == '-') {
	char *opt= argv[i++]+1;

	if (opt[0] == '-' && opt[1] == 0) break;	/* -- */

	while (*opt != 0) switch (*opt++) {
	case 'f':	first= 1;	break;
	default:	usage();
	}
    }
    if (i == argc) usage();
    file= argv[i++];

    size= 0;
    if (i < argc) {
	char *end;
	unsigned long m;

	size= strtoul(argv[i], &end, 10);
	if (end == argv[i]) usage();
	m= 1024;
	if (*end != 0) {
	    switch (*end) {
	    case 'm':	case 'M':	m *= 1024;	/*FALL THROUGH*/
	    case 'k':	case 'K':	end++;		break;
	    }
	}
	if (*end != 0 || size == -1
	    || (size * m) / m != size || (size *= m) <= SWAP_OFFSET
	) {
	    fprintf(stderr, "mkswap: %s: Bad size\n", argv[i]);
	    exit(1);
	}
	i++;
    }
    if (i != argc) usage();

    /* Open the device or file. */
    if ((fd= open(file, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) {
	fprintf(stderr, "mkswap: Can't open %s: %s\n", file, strerror(errno));
	exit(1);
    }

    /* File or device? */
    (void) fstat(fd, &st);
    if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
	struct partition part;

	/* How big is the partition? */
	if (ioctl(fd, DIOCGETP, &part) < 0) {
	    fprintf(stderr, "mkswap: Can't determine the size of %s: %s\n",
		file, strerror(errno));
	    exit(1);
	}
	devsize= cv64ul(part.size);
	offset= 0;

	if (!first) {
	    /* Is there a file system? */
	    r= -1;
	    if (lseek(fd, SUPER_BLOCK * BLOCK_SIZE, SEEK_SET) == -1
		|| (r= read(fd, block, BLOCK_SIZE)) < BLOCK_SIZE
	    ) {
		fprintf(stderr, "mkswap: %s: %s\n",
		    file, r >= 0 ? "End of file" : strerror(errno));
		exit(1);
	    }
	    memcpy(&super, block, sizeof(super));
	    if (super.s_magic == SUPER_MAGIC) {
		offset= (unsigned long) super.s_nzones * BLOCK_SIZE;
	    } else
	    if (super.s_magic == SUPER_V2) {
		offset= (unsigned long) super.s_zones * BLOCK_SIZE;
	    } else {
		first= 1;
	    }
	}
	if (size == 0) size= devsize - offset;
	if (size == 0 || offset + size > devsize) {
	    fprintf(stderr, "mkswap: There is no room on %s for ", file);
	    if (size > 0) fprintf(stderr, "%lu kilobytes of ", size/1024);
	    fprintf(stderr, "swapspace\n");
	    if (offset > 0) {
		fprintf(stderr, "(Use the -f flag to wipe the file system)\n");
	    }
	    exit(1);
	}
    } else
    if (S_ISREG(st.st_mode)) {
	/* Write to the swap file to guarantee space for MM. */
	unsigned long n;

	if (size == 0) {
	    fprintf(stderr, "mkswap: No size specified for %s\n", file);
	    usage();
	}

	memset(block, 0, sizeof(block));
	for (n= 0; n < size; n += r) {
	    r= size > sizeof(block) ? sizeof(block) : size;
	    if ((r= write(fd, block, r)) <= 0) {
		fprintf(stderr, "mkswap: %s: %s\n",
		    file, r == 0 ? "End of file" : strerror(errno));
		exit(1);
	    }
	}
	first= 1;
    } else {
	fprintf(stderr, "mkswap: %s is not a device or a file\n", file);
	exit(1);
    }

    if (offset < SWAP_OFFSET) {
	offset += SWAP_OFFSET;
	if (size < SWAP_OFFSET) size= 0; else size -= SWAP_OFFSET;
    }
    swap_hdr.sh_magic[0]= SWAP_MAGIC0;
    swap_hdr.sh_magic[1]= SWAP_MAGIC1;
    swap_hdr.sh_magic[2]= SWAP_MAGIC2;
    swap_hdr.sh_magic[3]= SWAP_MAGIC3;
    swap_hdr.sh_version= SH_VERSION;
    swap_hdr.sh_priority= 0;
    swap_hdr.sh_offset= offset;
    swap_hdr.sh_swapsize= size;

    r= -1;
    if (lseek(fd, SWAP_BOOTOFF, SEEK_SET) == -1
	|| (r= read(fd, block, sizeof(block))) < BLOCK_SIZE
    ) {
	fprintf(stderr, "mkswap: %s: %s\n", file,
	    file, r >= 0 ? "End of file" : strerror(errno));
	exit(1);
    }

    r= (first ? SWAP_BOOTOFF : OPTSWAP_BOOTOFF) - SWAP_BOOTOFF;
    memcpy(block + r, &swap_hdr, sizeof(swap_hdr));

    r= -1;
    if (lseek(fd, SWAP_BOOTOFF, SEEK_SET) == -1
	|| (r= write(fd, block, sizeof(block))) < BLOCK_SIZE
    ) {
	fprintf(stderr, "mkswap: %s: %s\n", file,
	    file, r >= 0 ? "End of file" : strerror(errno));
	exit(1);
    }
    printf("%s: swapspace at offset %lu, size %lu kilobytes\n",
	file, offset / 1024, size / 1024);
    return 0;
}