Exemplo n.º 1
0
static int ds_ioctl(struct inode * inode, struct file * file,
		    u_int cmd, u_long arg)
{
    socket_t i = MINOR(inode->i_rdev);
    socket_info_t *s;
    u_int size;
    int ret, err;
    ds_ioctl_arg_t buf;

    DEBUG(2, "ds_ioctl(socket %d, %#x, %#lx)\n", i, cmd, arg);
    
    if ((i >= sockets) || (sockets == 0))
	return -ENODEV;
    s = &socket_table[i];
    
    size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
    if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;

    /* Permission check */
    if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
	return -EPERM;
	
    if (cmd & IOC_IN) {
	err = verify_area(VERIFY_READ, (char *)arg, size);
	if (err) {
	    DEBUG(3, "ds_ioctl(): verify_read = %d\n", err);
	    return err;
	}
    }
    if (cmd & IOC_OUT) {
	err = verify_area(VERIFY_WRITE, (char *)arg, size);
	if (err) {
	    DEBUG(3, "ds_ioctl(): verify_write = %d\n", err);
	    return err;
	}
    }
    
    err = ret = 0;
    
    if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);
    
    switch (cmd) {
    case DS_ADJUST_RESOURCE_INFO:
	ret = CardServices(AdjustResourceInfo, s->handle, &buf.adjust);
	break;
    case DS_GET_CARD_SERVICES_INFO:
	ret = CardServices(GetCardServicesInfo, &buf.servinfo);
	break;
    case DS_GET_CONFIGURATION_INFO:
	ret = CardServices(GetConfigurationInfo, s->handle, &buf.config);
	break;
    case DS_GET_FIRST_TUPLE:
	ret = CardServices(GetFirstTuple, s->handle, &buf.tuple);
	break;
    case DS_GET_NEXT_TUPLE:
	ret = CardServices(GetNextTuple, s->handle, &buf.tuple);
	break;
    case DS_GET_TUPLE_DATA:
	buf.tuple.TupleData = buf.tuple_parse.data;
	buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
	ret = CardServices(GetTupleData, s->handle, &buf.tuple);
	break;
    case DS_PARSE_TUPLE:
	buf.tuple.TupleData = buf.tuple_parse.data;
	ret = CardServices(ParseTuple, s->handle, &buf.tuple,
			   &buf.tuple_parse.parse);
	break;
    case DS_RESET_CARD:
	ret = CardServices(ResetCard, s->handle, NULL);
	break;
    case DS_GET_STATUS:
	ret = CardServices(GetStatus, s->handle, &buf.status);
	break;
    case DS_VALIDATE_CIS:
	ret = CardServices(ValidateCIS, s->handle, &buf.cisinfo);
	break;
    case DS_SUSPEND_CARD:
	ret = CardServices(SuspendCard, s->handle, NULL);
	break;
    case DS_RESUME_CARD:
	ret = CardServices(ResumeCard, s->handle, NULL);
	break;
    case DS_EJECT_CARD:
	ret = CardServices(EjectCard, s->handle, NULL);
	break;
    case DS_INSERT_CARD:
	ret = CardServices(InsertCard, s->handle, NULL);
	break;
    case DS_ACCESS_CONFIGURATION_REGISTER:
	if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
	    return -EPERM;
	ret = CardServices(AccessConfigurationRegister, s->handle,
			   &buf.conf_reg);
	break;
    case DS_GET_FIRST_REGION:
        ret = CardServices(GetFirstRegion, s->handle, &buf.region);
	break;
    case DS_GET_NEXT_REGION:
	ret = CardServices(GetNextRegion, s->handle, &buf.region);
	break;
    case DS_GET_FIRST_WINDOW:
	buf.win_info.handle = (window_handle_t)s->handle;
	ret = CardServices(GetFirstWindow, &buf.win_info.handle,
			   &buf.win_info.window);
	break;
    case DS_GET_NEXT_WINDOW:
	ret = CardServices(GetNextWindow, &buf.win_info.handle,
			   &buf.win_info.window);
	break;
    case DS_GET_MEM_PAGE:
	ret = CardServices(GetMemPage, buf.win_info.handle,
			   &buf.win_info.map);
	break;
    case DS_REPLACE_CIS:
	ret = CardServices(ReplaceCIS, s->handle, &buf.cisdump);
	break;
    case DS_BIND_REQUEST:
	if (!capable(CAP_SYS_ADMIN)) return -EPERM;
	err = bind_request(i, &buf.bind_info);
	break;
    case DS_GET_DEVICE_INFO:
	err = get_device_info(i, &buf.bind_info, 1);
	break;
    case DS_GET_NEXT_DEVICE:
	err = get_device_info(i, &buf.bind_info, 0);
	break;
    case DS_UNBIND_REQUEST:
	err = unbind_request(i, &buf.bind_info);
	break;
    case DS_BIND_MTD:
	if (!capable(CAP_SYS_ADMIN)) return -EPERM;
	err = bind_mtd(i, &buf.mtd_info);
	break;
    default:
	err = -EINVAL;
    }
    
    if ((err == 0) && (ret != CS_SUCCESS)) {
	DEBUG(2, "ds_ioctl: ret = %d\n", ret);
	switch (ret) {
	case CS_BAD_SOCKET: case CS_NO_CARD:
	    err = -ENODEV; break;
	case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
	case CS_BAD_TUPLE:
	    err = -EINVAL; break;
	case CS_IN_USE:
	    err = -EBUSY; break;
	case CS_OUT_OF_RESOURCE:
	    err = -ENOSPC; break;
	case CS_NO_MORE_ITEMS:
	    err = -ENODATA; break;
	case CS_UNSUPPORTED_FUNCTION:
	    err = -ENOSYS; break;
	default:
	    err = -EIO; break;
	}
    }
    
    if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size);
     
    return err;
} /* ds_ioctl */
Exemplo n.º 2
0
static int ds_ioctl(struct inode * inode, struct file * file,
                    u_int cmd, u_long arg)
{
    struct pcmcia_bus_socket *s;
    void __user *uarg = (char __user *)arg;
    u_int size;
    int ret, err;
    ds_ioctl_arg_t buf;
    user_info_t *user;

    ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);

    user = file->private_data;
    if (CHECK_USER(user))
        return -EIO;

    s = user->socket;
    if (s->state & DS_SOCKET_DEAD)
        return -EIO;

    size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
    if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;

    /* Permission check */
    if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
        return -EPERM;

    if (cmd & IOC_IN) {
        err = verify_area(VERIFY_READ, uarg, size);
        if (err) {
            ds_dbg(3, "ds_ioctl(): verify_read = %d\n", err);
            return err;
        }
    }
    if (cmd & IOC_OUT) {
        err = verify_area(VERIFY_WRITE, uarg, size);
        if (err) {
            ds_dbg(3, "ds_ioctl(): verify_write = %d\n", err);
            return err;
        }
    }

    err = ret = 0;

    if (cmd & IOC_IN) __copy_from_user((char *)&buf, uarg, size);

    switch (cmd) {
    case DS_ADJUST_RESOURCE_INFO:
        ret = pcmcia_adjust_resource_info(s->handle, &buf.adjust);
        break;
    case DS_GET_CARD_SERVICES_INFO:
        ret = pcmcia_get_card_services_info(&buf.servinfo);
        break;
    case DS_GET_CONFIGURATION_INFO:
        ret = pcmcia_get_configuration_info(s->handle, &buf.config);
        break;
    case DS_GET_FIRST_TUPLE:
        ret = pcmcia_get_first_tuple(s->handle, &buf.tuple);
        break;
    case DS_GET_NEXT_TUPLE:
        ret = pcmcia_get_next_tuple(s->handle, &buf.tuple);
        break;
    case DS_GET_TUPLE_DATA:
        buf.tuple.TupleData = buf.tuple_parse.data;
        buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
        ret = pcmcia_get_tuple_data(s->handle, &buf.tuple);
        break;
    case DS_PARSE_TUPLE:
        buf.tuple.TupleData = buf.tuple_parse.data;
        ret = pcmcia_parse_tuple(s->handle, &buf.tuple, &buf.tuple_parse.parse);
        break;
    case DS_RESET_CARD:
        ret = pcmcia_reset_card(s->handle, NULL);
        break;
    case DS_GET_STATUS:
        ret = pcmcia_get_status(s->handle, &buf.status);
        break;
    case DS_VALIDATE_CIS:
        ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);
        break;
    case DS_SUSPEND_CARD:
        ret = pcmcia_suspend_card(s->parent);
        break;
    case DS_RESUME_CARD:
        ret = pcmcia_resume_card(s->parent);
        break;
    case DS_EJECT_CARD:
        ret = pcmcia_eject_card(s->parent);
        break;
    case DS_INSERT_CARD:
        ret = pcmcia_insert_card(s->parent);
        break;
    case DS_ACCESS_CONFIGURATION_REGISTER:
        if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
            return -EPERM;
        ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);
        break;
    case DS_GET_FIRST_REGION:
        ret = pcmcia_get_first_region(s->handle, &buf.region);
        break;
    case DS_GET_NEXT_REGION:
        ret = pcmcia_get_next_region(s->handle, &buf.region);
        break;
    case DS_GET_FIRST_WINDOW:
        buf.win_info.handle = (window_handle_t)s->handle;
        ret = pcmcia_get_first_window(&buf.win_info.handle, &buf.win_info.window);
        break;
    case DS_GET_NEXT_WINDOW:
        ret = pcmcia_get_next_window(&buf.win_info.handle, &buf.win_info.window);
        break;
    case DS_GET_MEM_PAGE:
        ret = pcmcia_get_mem_page(buf.win_info.handle,
                                  &buf.win_info.map);
        break;
    case DS_REPLACE_CIS:
        ret = pcmcia_replace_cis(s->handle, &buf.cisdump);
        break;
    case DS_BIND_REQUEST:
        if (!capable(CAP_SYS_ADMIN)) return -EPERM;
        err = bind_request(s, &buf.bind_info);
        break;
    case DS_GET_DEVICE_INFO:
        err = get_device_info(s, &buf.bind_info, 1);
        break;
    case DS_GET_NEXT_DEVICE:
        err = get_device_info(s, &buf.bind_info, 0);
        break;
    case DS_UNBIND_REQUEST:
        err = unbind_request(s, &buf.bind_info);
        break;
    case DS_BIND_MTD:
        if (!capable(CAP_SYS_ADMIN)) return -EPERM;
        err = bind_mtd(s, &buf.mtd_info);
        break;
    default:
        err = -EINVAL;
    }

    if ((err == 0) && (ret != CS_SUCCESS)) {
        ds_dbg(2, "ds_ioctl: ret = %d\n", ret);
        switch (ret) {
        case CS_BAD_SOCKET:
        case CS_NO_CARD:
            err = -ENODEV;
            break;
        case CS_BAD_ARGS:
        case CS_BAD_ATTRIBUTE:
        case CS_BAD_IRQ:
        case CS_BAD_TUPLE:
            err = -EINVAL;
            break;
        case CS_IN_USE:
            err = -EBUSY;
            break;
        case CS_OUT_OF_RESOURCE:
            err = -ENOSPC;
            break;
        case CS_NO_MORE_ITEMS:
            err = -ENODATA;
            break;
        case CS_UNSUPPORTED_FUNCTION:
            err = -ENOSYS;
            break;
        default:
            err = -EIO;
            break;
        }
    }

    if (cmd & IOC_OUT) __copy_to_user(uarg, (char *)&buf, size);

    return err;
} /* ds_ioctl */