Example #1
0
static int get_stream_blocksize(BlockBackend *blk)
{
    uint8_t cmd[6];
    uint8_t buf[12];
    uint8_t sensebuf[8];
    sg_io_hdr_t io_header;
    int ret;

    memset(cmd, 0, sizeof(cmd));
    memset(buf, 0, sizeof(buf));
    cmd[0] = MODE_SENSE;
    cmd[4] = sizeof(buf);

    memset(&io_header, 0, sizeof(io_header));
    io_header.interface_id = 'S';
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
    io_header.dxfer_len = sizeof(buf);
    io_header.dxferp = buf;
    io_header.cmdp = cmd;
    io_header.cmd_len = sizeof(cmd);
    io_header.mx_sb_len = sizeof(sensebuf);
    io_header.sbp = sensebuf;
    io_header.timeout = 6000; /* XXX */

    ret = blk_ioctl(blk, SG_IO, &io_header);
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
        return -1;
    }
    return (buf[9] << 16) | (buf[10] << 8) | buf[11];
}
Example #2
0
void scsi_generic_read_device_identification(SCSIDevice *s)
{
    uint8_t cmd[6];
    uint8_t buf[250];
    uint8_t sensebuf[8];
    sg_io_hdr_t io_header;
    int ret;
    int i, len;

    memset(cmd, 0, sizeof(cmd));
    memset(buf, 0, sizeof(buf));
    cmd[0] = INQUIRY;
    cmd[1] = 1;
    cmd[2] = 0x83;
    cmd[4] = sizeof(buf);

    memset(&io_header, 0, sizeof(io_header));
    io_header.interface_id = 'S';
    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
    io_header.dxfer_len = sizeof(buf);
    io_header.dxferp = buf;
    io_header.cmdp = cmd;
    io_header.cmd_len = sizeof(cmd);
    io_header.mx_sb_len = sizeof(sensebuf);
    io_header.sbp = sensebuf;
    io_header.timeout = 6000; /* XXX */

    ret = blk_ioctl(s->conf.blk, SG_IO, &io_header);
    if (ret < 0 || io_header.driver_status || io_header.host_status) {
        return;
    }

    len = MIN((buf[2] << 8) | buf[3], sizeof(buf) - 4);
    for (i = 0; i + 3 <= len; ) {
        const uint8_t *p = &buf[i + 4];
        uint64_t wwn;

        if (i + (p[3] + 4) > len) {
            break;
        }

        if ((p[1] & 0x10) == 0) {
            /* Associated with the logical unit */
            if (read_naa_id(p, &wwn) == 0) {
                s->wwn = wwn;
            }
        } else if ((p[1] & 0x10) == 0x10) {
            /* Associated with the target port */
            if (read_naa_id(p, &wwn) == 0) {
                s->port_wwn = wwn;
            }
        }

        i += p[3] + 4;
    }
}
Example #3
0
static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
{
	struct NFTLrecord *nftl;

	nftl = NFTLs[MINOR(inode->i_rdev) / 16];

	if (!nftl) return -EINVAL;

	switch (cmd) {
	case HDIO_GETGEO: {
		struct hd_geometry g;

		g.heads = nftl->heads;
		g.sectors = nftl->sectors;
		g.cylinders = nftl->cylinders;
		g.start = part_table[MINOR(inode->i_rdev)].start_sect;
		return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
	}
	case BLKGETSIZE:   /* Return device size */
		if (!arg) return -EINVAL;
		return put_user(part_table[MINOR(inode->i_rdev)].nr_sects,
                                (long *) arg);
		
	case BLKFLSBUF:
		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
		fsync_dev(inode->i_rdev);
		invalidate_buffers(inode->i_rdev);
		if (nftl->mtd->sync)
			nftl->mtd->sync(nftl->mtd);
		return 0;

	case BLKRRPART:
		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
		if (nftl->usecount > 1) return -EBUSY;
#if LINUX_VERSION_CODE < 0x20328
		resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) / 16);
#else
		grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) / 16,
				1<<4, nftl->nr_sects);
#endif
		return 0;

#if (LINUX_VERSION_CODE < 0x20303)		
	RO_IOCTLS(inode->i_rdev, arg);  /* ref. linux/blk.h */
#else
	case BLKROSET:
	case BLKROGET:
	case BLKSSZGET:
		return blk_ioctl(inode->i_rdev, cmd, arg);
#endif

	default:
		return -EINVAL;
	}
}
Example #4
0
File: pd.c Project: TitaniumBoy/lin
static int pd_ioctl(struct inode *inode,struct file *file,
                    unsigned int cmd, unsigned long arg)

{       struct hd_geometry *geo = (struct hd_geometry *) arg;
        int dev, err, unit;

        if ((!inode) || (!inode->i_rdev)) return -EINVAL;
        dev = MINOR(inode->i_rdev);
	unit = DEVICE_NR(inode->i_rdev);
        if (dev >= PD_DEVS) return -EINVAL;
	if (!PD.present) return -ENODEV;

        switch (cmd) {
	    case CDROMEJECT:
		if (PD.access == 1) pd_eject(unit);
		return 0;
            case HDIO_GETGEO:
                if (!geo) return -EINVAL;
                err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
                if (err) return err;

		if (PD.alt_geom) {
                    put_user(PD.capacity/(PD_LOG_HEADS*PD_LOG_SECTS), 
		    		(short *) &geo->cylinders);
                    put_user(PD_LOG_HEADS, (char *) &geo->heads);
                    put_user(PD_LOG_SECTS, (char *) &geo->sectors);
		} else {
                    put_user(PD.cylinders, (short *) &geo->cylinders);
                    put_user(PD.heads, (char *) &geo->heads);
                    put_user(PD.sectors, (char *) &geo->sectors);
		}
                put_user(pd_hd[dev].start_sect,(long *)&geo->start);
                return 0;
            case BLKRRPART:
		if (!capable(CAP_SYS_ADMIN))
			return -EACCES;
                return pd_revalidate(inode->i_rdev);
	    case BLKGETSIZE:
	    case BLKGETSIZE64:
	    case BLKROSET:
	    case BLKROGET:
	    case BLKRASET:
	    case BLKRAGET:
	    case BLKFLSBUF:
	    case BLKPG:
		return blk_ioctl(inode->i_rdev, cmd, arg);
            default:
                return -EINVAL;
        }
}
Example #5
0
int sbull_ioctl (struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg)
{
    int err;
    long size;
    struct hd_geometry geo;

    PDEBUG("ioctl 0x%x 0x%lx\n", cmd, arg);
    switch(cmd) {

      case BLKGETSIZE:
        /* Return the device size, expressed in sectors */
        if (!arg) return -EINVAL; /* NULL pointer: not valid */
        err = ! access_ok (VERIFY_WRITE, arg, sizeof(long));
        if (err) return -EFAULT;
        size = blksize*sbull_sizes[MINOR(inode->i_rdev)]
		/ sbull_hardsects[MINOR(inode->i_rdev)];
	__copy_to_user((long *) arg, &size, sizeof (long));
        return 0;

      case BLKRRPART: /* re-read partition table: can't do it */
        return -ENOTTY;

      case HDIO_GETGEO:
        /*
	 * Get geometry: since we are a virtual device, we have to make
	 * up something plausible.  So we claim 16 sectors, four heads,
	 * and calculate the corresponding number of cylinders.  We set the
	 * start of data at sector four.
         */
        err = ! access_ok(VERIFY_WRITE, arg, sizeof(geo));
        if (err) return -EFAULT;
        size = sbull_size * blksize / sbull_hardsect;
        geo.cylinders = (size & ~0x3f) >> 6;
	geo.heads = 4;
	geo.sectors = 16;
	geo.start = 4;
	__copy_to_user((void *) arg, &geo, sizeof(geo));
        return 0;

      default:
        /*
         * For ioctls we don't understand, let the block layer handle them.
         */
        return blk_ioctl(inode->i_rdev, cmd, arg);
    }

    return -ENOTTY; /* unknown command */
}
Example #6
0
File: rd.c Project: nhanh0/hah
static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	int error = -EINVAL;
	unsigned int minor;

	if (!inode || !inode->i_rdev) 	
		goto out;

	minor = MINOR(inode->i_rdev);

	switch (cmd) {
		case BLKFLSBUF:
			if (!capable(CAP_SYS_ADMIN))
				return -EACCES;
			/* special: we want to release the ramdisk memory,
			   it's not like with the other blockdevices where
			   this ioctl only flushes away the buffer cache. */
			error = -EBUSY;
			down(&inode->i_bdev->bd_sem);
			if (inode->i_bdev->bd_openers <= 2) {
				truncate_inode_pages(inode->i_mapping, 0);
				error = 0;
			}
			up(&inode->i_bdev->bd_sem);
			break;
         	case BLKGETSIZE:   /* Return device size */
			if (!arg)
				break;
			error = put_user(rd_kbsize[minor] << 1, (unsigned long *) arg);
			break;
         	case BLKGETSIZE64:
			error = put_user((u64)rd_kbsize[minor]<<10, (u64*)arg);
			break;
		case BLKROSET:
		case BLKROGET:
		case BLKSSZGET:
			error = blk_ioctl(inode->i_rdev, cmd, arg);
	};
out:
	return error;
}
Example #7
0
static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
{
	struct NFTLrecord *nftl;
	int p;

	nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS];

	if (!nftl) return -EINVAL;

	switch (cmd) {
	case HDIO_GETGEO: {
		struct hd_geometry g;

		g.heads = nftl->heads;
		g.sectors = nftl->sectors;
		g.cylinders = nftl->cylinders;
		g.start = part_table[MINOR(inode->i_rdev)].start_sect;
		return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
	}
	case BLKGETSIZE:   /* Return device size */
		return put_user(part_table[MINOR(inode->i_rdev)].nr_sects,
                                (unsigned long *) arg);

#ifdef BLKGETSIZE64
	case BLKGETSIZE64:
		return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9,
                                (u64 *)arg);
#endif

	case BLKFLSBUF:
		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
		fsync_dev(inode->i_rdev);
		invalidate_buffers(inode->i_rdev);
		if (nftl->mtd->sync)
			nftl->mtd->sync(nftl->mtd);
		return 0;

	case BLKRRPART:
		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
		if (nftl->usecount > 1) return -EBUSY;
		/* 
		 * We have to flush all buffers and invalidate caches,
		 * or we won't be able to re-use the partitions,
		 * if there was a change and we don't want to reboot
		 */
		p = (1<<NFTL_PARTN_BITS) - 1;
		while (p-- > 0) {
			kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p);
			if (part_table[p].nr_sects > 0)
				invalidate_device (devp, 1);

			part_table[MINOR(inode->i_dev)+p].start_sect = 0;
			part_table[MINOR(inode->i_dev)+p].nr_sects = 0;
		}
		
#if LINUX_VERSION_CODE < 0x20328
		resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS);
#else
		grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS,
				1<<NFTL_PARTN_BITS, nftl->nr_sects);
#endif
		return 0;

#if (LINUX_VERSION_CODE < 0x20303)		
	RO_IOCTLS(inode->i_rdev, arg);  /* ref. linux/blk.h */
#else
	case BLKROSET:
	case BLKROGET:
	case BLKSSZGET:
		return blk_ioctl(inode->i_rdev, cmd, arg);
#endif

	default:
		return -EINVAL;
	}
}
Example #8
0
static void scsi_generic_realize(SCSIDevice *s, Error **errp)
{
    int rc;
    int sg_version;
    struct sg_scsi_id scsiid;

    if (!s->conf.blk) {
        error_setg(errp, "drive property not set");
        return;
    }

    if (blk_get_on_error(s->conf.blk, 0) != BLOCKDEV_ON_ERROR_ENOSPC) {
        error_setg(errp, "Device doesn't support drive option werror");
        return;
    }
    if (blk_get_on_error(s->conf.blk, 1) != BLOCKDEV_ON_ERROR_REPORT) {
        error_setg(errp, "Device doesn't support drive option rerror");
        return;
    }

    /* check we are using a driver managing SG_IO (version 3 and after */
    rc = blk_ioctl(s->conf.blk, SG_GET_VERSION_NUM, &sg_version);
    if (rc < 0) {
        error_setg(errp, "cannot get SG_IO version number: %s.  "
                         "Is this a SCSI device?",
                         strerror(-rc));
        return;
    }
    if (sg_version < 30000) {
        error_setg(errp, "scsi generic interface too old");
        return;
    }

    /* get LUN of the /dev/sg? */
    if (blk_ioctl(s->conf.blk, SG_GET_SCSI_ID, &scsiid)) {
        error_setg(errp, "SG_GET_SCSI_ID ioctl failed");
        return;
    }

    /* define device state */
    s->type = scsiid.scsi_type;
    DPRINTF("device type %d\n", s->type);

    switch (s->type) {
    case TYPE_TAPE:
        s->blocksize = get_stream_blocksize(s->conf.blk);
        if (s->blocksize == -1) {
            s->blocksize = 0;
        }
        break;

        /* Make a guess for block devices, we'll fix it when the guest sends.
         * READ CAPACITY.  If they don't, they likely would assume these sizes
         * anyway. (TODO: they could also send MODE SENSE).
         */
    case TYPE_ROM:
    case TYPE_WORM:
        s->blocksize = 2048;
        break;
    default:
        s->blocksize = 512;
        break;
    }

    DPRINTF("block size %d\n", s->blocksize);
}
Example #9
0
/*!
  j'ai récupérée quasi intégralement le code de sbull.c,
  j'ai juste adapté certains noms de fonction
  Ca permet d'avoir une fonction bien testée et débuggée
*/
int smd_ioctl (struct inode *inode, 
	       struct file *filp,
	       unsigned int cmd, 
	       unsigned long arg) {
  int err, size;
  struct hd_geometry *geo = (struct hd_geometry *)arg;
  servernode_t *sn;
  ndevice_t *nd;

  nd = minor2ndev[MINOR(inode->i_rdev)];
  sn = nd->sn;
    
  PDEBUG("cmd=0x%x arg=0x%lx ndev='%s:%s'\n", 
	 cmd, 
	 arg,
	 sn->name,
	 nd->name);

  switch(cmd) {

  case BLKGETSIZE: /* Return the device size, expressed in sectors */
    if (!arg) return -EINVAL; /* NULL pointer: not valid */
    err=verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
    if (err) return err;
    put_user(nd->size * (1024 / SMD_HARDSECT), (long *) arg);

    PDEBUG("BLKGETSIZE %lld (device size %lld, sect size %d)\n",
	   nd->size  * (1024 / SMD_HARDSECT),
	   nd->size,
	   SMD_HARDSECT );
    
    return 0;
    
  case BLKFLSBUF: /* flush */
    if (!suser()) return -EACCES; /* only root */
    fsync_dev(inode->i_rdev);
    invalidate_buffers(inode->i_rdev);
    PDEBUG("BLKFLSBUF \n");
    return 0;

  case BLKRAGET: /* return the readahead value */
    if (!arg)  return -EINVAL;
    err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
    if (err) return err;
    put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
    PDEBUG("BLKRAGET \n");
    return 0;

  case BLKRASET: /* set the readahead value */
    if (!suser()) return -EACCES;
    if (arg > 0xff) return -EINVAL; /* limit it */
    read_ahead[MAJOR(inode->i_rdev)] = arg;
    PDEBUG("BLKRASET \n");
    return 0;

  case BLKRRPART: /* re-read partition table: can't do it */
    PDEBUG("BLKRRPART \n");
    return -EINVAL;

    //RO_IOCTLS(inode->i_rdev, arg); /* the default RO operations */

  case HDIO_GETGEO:
    /*
     * get geometry: we have to fake one...  trim the size to a
     * multiple of 64 (32k): tell we have 16 sectors, 4 heads,
     * whatever cylinders. Tell also that data starts at sector. 4.
     */
    size = nd->size * (1024 / SMD_HARDSECT);
    size &= ~0x3f; /* multiple of 64 */
    if (geo==NULL) return -EINVAL;
    err = verify_area(VERIFY_WRITE, geo, sizeof(*geo));
    if (err) return err;
    put_user(size >> 6, &geo->cylinders);
    put_user(        4, &geo->heads);
    put_user(       16, &geo->sectors);
    put_user(        4, &geo->start);
    PDEBUG("HDIO_GETGEO \n");
    return 0;

  default:
    PDEBUG("PAR DEFAUT \n");
    return blk_ioctl(inode->i_rdev, cmd, arg);
  }

  PDEBUG("COMMANDE INCONNUE \n");
  return -EINVAL; /* unknown command */
}
Example #10
0
static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
	int dev;

	if ((!inode) || !(inode->i_rdev))
		return -EINVAL;
 	dev = DEVICE_NR(inode->i_rdev);

	if (dev >= xd_drives) return -EINVAL;
	switch (cmd) {
		case HDIO_GETGEO:
		{
			struct hd_geometry g;
			struct hd_geometry *geometry = (struct hd_geometry *) arg;
			g.heads = xd_info[dev].heads;
			g.sectors = xd_info[dev].sectors;
			g.cylinders = xd_info[dev].cylinders;
			g.start = xd_struct[MINOR(inode->i_rdev)].start_sect;
			return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
		}
		case HDIO_SET_DMA:
			if (!capable(CAP_SYS_ADMIN))
				return -EACCES;
			if (xdc_busy)
				return -EBUSY;
				
			nodma = !arg;
			
			if (nodma && xd_dma_buffer) {
				xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
				xd_dma_buffer = 0;
			} else if (!nodma && !xd_dma_buffer) {
				xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);
				if (!xd_dma_buffer)
				{
					nodma = XD_DONT_USE_DMA;
					return -ENOMEM;
				}
			}
			return 0;
		case HDIO_GET_DMA:
			return put_user(!nodma, (long *) arg);
		case HDIO_GET_MULTCOUNT:
			return put_user(xd_maxsectors, (long *) arg);
		case BLKRRPART:
			if (!capable(CAP_SYS_ADMIN)) 
				return -EACCES;
			return xd_reread_partitions(inode->i_rdev);
		case BLKGETSIZE:
		case BLKGETSIZE64:
		case BLKFLSBUF:
		case BLKROSET:
		case BLKROGET:
		case BLKRASET:
		case BLKRAGET:
		case BLKPG:
			return blk_ioctl(inode->i_rdev, cmd, arg);
		default:
			return -EINVAL;
	}
}
Example #11
0
static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
{
	kdev_t dev = inode->i_rdev;
	struct Scsi_Host * host;
	Scsi_Device * SDev;
	int diskinfo[4];
    
	SDev = rscsi_disks[DEVICE_NR(dev)].device;
	if (!SDev)
		return -ENODEV;

	/*
	 * If we are in the middle of error recovery, don't let anyone
	 * else try and use this device.  Also, if error recovery fails, it
	 * may try and take the device offline, in which case all further
	 * access to the device is prohibited.
	 */

	if( !scsi_block_when_processing_errors(SDev) )
	{
		return -ENODEV;
	}

	switch (cmd) 
	{
		case HDIO_GETGEO:   /* Return BIOS disk parameters */
		{
			struct hd_geometry *loc = (struct hd_geometry *) arg;
			if(!loc)
				return -EINVAL;

			host = rscsi_disks[DEVICE_NR(dev)].device->host;
	
			/* default to most commonly used values */
	
		        diskinfo[0] = 0x40;
	        	diskinfo[1] = 0x20;
	        	diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;
	
			/* override with calculated, extended default, or driver values */
	
			if(host->hostt->bios_param != NULL)
				host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
					    dev,
					    &diskinfo[0]);
			else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
					dev, &diskinfo[0]);

			if (put_user(diskinfo[0], &loc->heads) ||
				put_user(diskinfo[1], &loc->sectors) ||
				put_user(diskinfo[2], &loc->cylinders) ||
				put_user(sd_gendisks[SD_MAJOR_IDX(
				    inode->i_rdev)].part[MINOR(
				    inode->i_rdev)].start_sect, &loc->start))
				return -EFAULT;
			return 0;
		}
		case HDIO_GETGEO_BIG:
		{
			struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;

			if(!loc)
				return -EINVAL;

			host = rscsi_disks[DEVICE_NR(dev)].device->host;

			/* default to most commonly used values */

			diskinfo[0] = 0x40;
			diskinfo[1] = 0x20;
			diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;

			/* override with calculated, extended default, or driver values */

			if(host->hostt->bios_param != NULL)
				host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
					    dev,
					    &diskinfo[0]);
			else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
					dev, &diskinfo[0]);

			if (put_user(diskinfo[0], &loc->heads) ||
				put_user(diskinfo[1], &loc->sectors) ||
				put_user(diskinfo[2], (unsigned int *) &loc->cylinders) ||
				put_user(sd_gendisks[SD_MAJOR_IDX(
				    inode->i_rdev)].part[MINOR(
				    inode->i_rdev)].start_sect, &loc->start))
				return -EFAULT;
			return 0;
		}
		case BLKGETSIZE:
		case BLKGETSIZE64:
		case BLKROSET:
		case BLKROGET:
		case BLKRASET:
		case BLKRAGET:
		case BLKFLSBUF:
		case BLKSSZGET:
		case BLKPG:
		case BLKELVGET:
		case BLKELVSET:
		case BLKBSZGET:
		case BLKBSZSET:
			return blk_ioctl(inode->i_rdev, cmd, arg);

		case BLKRRPART: /* Re-read partition tables */
		        if (!capable(CAP_SYS_ADMIN))
		                return -EACCES;
			return revalidate_scsidisk(dev, 1);

		default:
			return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
	}
}