⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ub.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
	cmd->state = UB_CMDST_INIT;	cmd->done = ub_probe_done;	cmd->back = &compl;	spin_lock_irqsave(&sc->lock, flags);	cmd->tag = sc->tagcnt++;	rc = ub_submit_scsi(sc, cmd);	spin_unlock_irqrestore(&sc->lock, flags);	if (rc != 0) {		printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */		goto err_submit;	}	wait_for_completion(&compl);	rc = cmd->error;err_submit:	kfree(cmd);err_alloc:	return rc;}/* * Read the SCSI capacity synchronously (for probing). */static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret){	struct ub_scsi_cmd *cmd;	char *p;	enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 };	unsigned long flags;	unsigned int bsize, shift;	unsigned long nsec;	struct completion compl;	int rc;	init_completion(&compl);	rc = -ENOMEM;	if ((cmd = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)		goto err_alloc;	memset(cmd, 0, ALLOC_SIZE);	p = (char *)cmd + sizeof(struct ub_scsi_cmd);	cmd->cdb[0] = 0x25;	cmd->cdb_len = 10;	cmd->dir = UB_DIR_READ;	cmd->state = UB_CMDST_INIT;	cmd->data = p;	cmd->len = 8;	cmd->done = ub_probe_done;	cmd->back = &compl;	spin_lock_irqsave(&sc->lock, flags);	cmd->tag = sc->tagcnt++;	rc = ub_submit_scsi(sc, cmd);	spin_unlock_irqrestore(&sc->lock, flags);	if (rc != 0) {		printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */		goto err_submit;	}	wait_for_completion(&compl);	if (cmd->error != 0) {		printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */		rc = -EIO;		goto err_read;	}	if (cmd->act_len != 8) {		printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */		rc = -EIO;		goto err_read;	}	/* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */	nsec = be32_to_cpu(*(u32 *)p) + 1;	bsize = be32_to_cpu(*(u32 *)(p + 4));	switch (bsize) {	case 512:	shift = 0;	break;	case 1024:	shift = 1;	break;	case 2048:	shift = 2;	break;	case 4096:	shift = 3;	break;	default:		printk("ub: Bad sector size %u\n", bsize); /* P3 */		rc = -EDOM;		goto err_inv_bsize;	}	ret->bsize = bsize;	ret->bshift = shift;	ret->nsec = nsec << shift;	rc = 0;err_inv_bsize:err_read:err_submit:	kfree(cmd);err_alloc:	return rc;}/* */static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt){	struct completion *cop = urb->context;	complete(cop);}static void ub_probe_timeout(unsigned long arg){	struct completion *cop = (struct completion *) arg;	complete(cop);}/* * Clear initial stalls. */static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe){	int endp;	struct usb_ctrlrequest *cr;	struct completion compl;	struct timer_list timer;	int rc;	init_completion(&compl);	endp = usb_pipeendpoint(stalled_pipe);	if (usb_pipein (stalled_pipe))		endp |= USB_DIR_IN;	cr = &sc->work_cr;	cr->bRequestType = USB_RECIP_ENDPOINT;	cr->bRequest = USB_REQ_CLEAR_FEATURE;	cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT);	cr->wIndex = cpu_to_le16(endp);	cr->wLength = cpu_to_le16(0);	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);	sc->work_urb.transfer_flags = 0;	sc->work_urb.actual_length = 0;	sc->work_urb.error_count = 0;	sc->work_urb.status = 0;	init_timer(&timer);	timer.function = ub_probe_timeout;	timer.data = (unsigned long) &compl;	timer.expires = jiffies + UB_CTRL_TIMEOUT;	add_timer(&timer);	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {		printk(KERN_WARNING		     "%s: Unable to submit a probe clear (%d)\n", sc->name, rc);		del_timer_sync(&timer);		return rc;	}	wait_for_completion(&compl);	del_timer_sync(&timer);	/*	 * Most of the time, URB was done and dev set to NULL, and so	 * the unlink bounces out with ENODEV. We do not call usb_kill_urb	 * because we still think about a backport to 2.4.	 */	usb_unlink_urb(&sc->work_urb);	/* reset the endpoint toggle */	usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);	return 0;}/* * Get the pipe settings. */static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,    struct usb_interface *intf){	struct usb_host_interface *altsetting = intf->cur_altsetting;	struct usb_endpoint_descriptor *ep_in = NULL;	struct usb_endpoint_descriptor *ep_out = NULL;	struct usb_endpoint_descriptor *ep;	int i;	/*	 * Find the endpoints we need.	 * We are expecting a minimum of 2 endpoints - in and out (bulk).	 * We will ignore any others.	 */	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {		ep = &altsetting->endpoint[i].desc;		/* Is it a BULK endpoint? */		if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)				== USB_ENDPOINT_XFER_BULK) {			/* BULK in or out? */			if (ep->bEndpointAddress & USB_DIR_IN)				ep_in = ep;			else				ep_out = ep;		}	}	if (ep_in == NULL || ep_out == NULL) {		printk(KERN_NOTICE "%s: device %u failed endpoint check\n",		    sc->name, sc->dev->devnum);		return -EIO;	}	/* Calculate and store the pipe values */	sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0);	sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0);	sc->send_bulk_pipe = usb_sndbulkpipe(dev,		ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);	sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, 		ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);	return 0;}/* * Probing is done in the process context, which allows us to cheat * and not to build a state machine for the discovery. */static int ub_probe(struct usb_interface *intf,    const struct usb_device_id *dev_id){	struct ub_dev *sc;	request_queue_t *q;	struct gendisk *disk;	int rc;	rc = -ENOMEM;	if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)		goto err_core;	memset(sc, 0, sizeof(struct ub_dev));	spin_lock_init(&sc->lock);	usb_init_urb(&sc->work_urb);	tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);	atomic_set(&sc->poison, 0);	init_timer(&sc->work_timer);	sc->work_timer.data = (unsigned long) sc;	sc->work_timer.function = ub_urb_timeout;	ub_init_completion(&sc->work_done);	sc->work_done.done = 1;		/* A little yuk, but oh well... */	rc = -ENOSR;	if ((sc->id = ub_id_get()) == -1)		goto err_id;	snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a');	sc->dev = interface_to_usbdev(intf);	sc->intf = intf;	// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;	usb_set_intfdata(intf, sc);	usb_get_dev(sc->dev);	// usb_get_intf(sc->intf);	/* Do we need this? */	/* XXX Verify that we can handle the device (from descriptors) */	ub_get_pipes(sc, sc->dev, intf);	if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)		goto err_diag;	/*	 * At this point, all USB initialization is done, do upper layer.	 * We really hate halfway initialized structures, so from the	 * invariants perspective, this ub_dev is fully constructed at	 * this point.	 */	/*	 * This is needed to clear toggles. It is a problem only if we do	 * `rmmod ub && modprobe ub` without disconnects, but we like that.	 */	ub_probe_clear_stall(sc, sc->recv_bulk_pipe);	ub_probe_clear_stall(sc, sc->send_bulk_pipe);	/*	 * The way this is used by the startup code is a little specific.	 * A SCSI check causes a USB stall. Our common case code sees it	 * and clears the check, after which the device is ready for use.	 * But if a check was not present, any command other than	 * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE).	 *	 * If we neglect to clear the SCSI check, the first real command fails	 * (which is the capacity readout). We clear that and retry, but why	 * causing spurious retries for no reason.	 *	 * Revalidation may start with its own TEST_UNIT_READY, but that one	 * has to succeed, so we clear checks with an additional one here.	 * In any case it's not our business how revaliadation is implemented.	 */	ub_sync_tur(sc);	sc->removable = 1;		/* XXX Query this from the device */	ub_revalidate(sc);	/* This is pretty much a long term P3 */	printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",	    sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);	/*	 * Just one disk per sc currently, but maybe more.	 */	rc = -ENOMEM;	if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)		goto err_diskalloc;	sc->disk = disk;	sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a');	sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a');	disk->major = UB_MAJOR;	disk->first_minor = sc->id * UB_MINORS_PER_MAJOR;	disk->fops = &ub_bd_fops;	disk->private_data = sc;	disk->driverfs_dev = &intf->dev;	rc = -ENOMEM;	if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)		goto err_blkqinit;	disk->queue = q;        // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);	blk_queue_max_hw_segments(q, UB_MAX_REQ_SG);	blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);	// blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);	blk_queue_max_sectors(q, UB_MAX_SECTORS);	// blk_queue_hardsect_size(q, xxxxx);	/*	 * This is a serious infraction, caused by a deficiency in the	 * USB sg interface (usb_sg_wait()). We plan to remove this once	 * we get mileage on the driver and can justify a change to USB API.	 * See blk_queue_bounce_limit() to understand this part.	 *	 * XXX And I still need to be aware of the DMA mask in the HC.	 */	q->bounce_pfn = blk_max_low_pfn;	q->bounce_gfp = GFP_NOIO;	q->queuedata = sc;	set_capacity(disk, sc->capacity.nsec);	if (sc->removable)		disk->flags |= GENHD_FL_REMOVABLE;	add_disk(disk);	return 0;err_blkqinit:	put_disk(disk);err_diskalloc:	device_remove_file(&sc->intf->dev, &dev_attr_diag);err_diag:	usb_set_intfdata(intf, NULL);	// usb_put_intf(sc->intf);	usb_put_dev(sc->dev);	spin_lock_irq(&ub_lock);	ub_id_put(sc->id);	spin_unlock_irq(&ub_lock);err_id:	kfree(sc);err_core:	return rc;}static void ub_disconnect(struct usb_interface *intf){	struct ub_dev *sc = usb_get_intfdata(intf);	struct gendisk *disk = sc->disk;	request_queue_t *q = disk->queue;	unsigned long flags;	/*	 * Fence stall clearnings, operations triggered by unlinkings and so on.	 * We do not attempt to unlink any URBs, because we do not trust the	 * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.	 */	atomic_set(&sc->poison, 1);	/*	 * Blow away queued commands.	 *	 * Actually, this never works, because before we get here	 * the HCD terminates outstanding URB(s). It causes our	 * SCSI command queue to advance, commands fail to submit,	 * and the whole queue drains. So, we just use this code to	 * print warnings.	 */	spin_lock_irqsave(&sc->lock, flags);	{		struct ub_scsi_cmd *cmd;		int cnt = 0;		while ((cmd = ub_cmdq_pop(sc)) != NULL) {			cmd->error = -ENOTCONN;			cmd->state = UB_CMDST_DONE;			ub_cmdtr_state(sc, cmd);			ub_cmdq_pop(sc);			(*cmd->done)(sc, cmd);			cnt++;		}		if (cnt != 0) {			printk(KERN_WARNING "%s: "			    "%d was queued after shutdown\n", sc->name, cnt);		}	}	spin_unlock_irqrestore(&sc->lock, flags);	/*	 * Unregister the upper layer, this waits for all commands to end.	 */	if (disk->flags & GENHD_FL_UP)		del_gendisk(disk);	if (q)		blk_cleanup_queue(q);	/*	 * If we zero disk->private_data BEFORE put_disk, we have to check	 * for NULL all over the place in open, release, check_media and	 * revalidate, because the block level semaphore is well inside the	 * put_disk. But we cannot zero after the call, because *disk is gone.	 * The sd.c is blatantly racy in this area.	 */	/* disk->private_data = NULL; */	put_disk(disk);	sc->disk = NULL;	/*	 * We really expect blk_cleanup_queue() to wait, so no amount	 * of paranoya is too much.	 *	 * Taking a lock on a structure which is about to be freed	 * is very nonsensual. Here it is largely a way to do a debug freeze,	 * and a bracket which shows where the nonsensual code segment ends.	 *	 * Testing for -EINPROGRESS is always a bug, so we are bending	 * the rules a little.	 */	spin_lock_irqsave(&sc->lock, flags);	if (sc->work_urb.status == -EINPROGRESS) {	/* janitors: ignore */		printk(KERN_WARNING "%s: "		    "URB is active after disconnect\n", sc->name);	}	spin_unlock_irqrestore(&sc->lock, flags);	/*	 * At this point there must be no commands coming from anyone	 * and no URBs left in transit.	 */	device_remove_file(&sc->intf->dev, &dev_attr_diag);	usb_set_intfdata(intf, NULL);	// usb_put_intf(sc->intf);	sc->intf = NULL;	usb_put_dev(sc->dev);	sc->dev = NULL;	spin_lock_irqsave(&ub_lock, flags);	if (sc->openc == 0)		ub_cleanup(sc);	spin_unlock_irqrestore(&ub_lock, flags);}struct usb_driver ub_driver = {	.owner =	THIS_MODULE,	.name =		"ub",	.probe =	ub_probe,	.disconnect =	ub_disconnect,	.id_table =	ub_usb_ids,};static int __init ub_init(void){	int rc;	/* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n",			sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev));	if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)		goto err_regblkdev;	devfs_mk_dir(DEVFS_NAME);	if ((rc = usb_register(&ub_driver)) != 0)		goto err_register;	return 0;err_register:	devfs_remove(DEVFS_NAME);	unregister_blkdev(UB_MAJOR, DRV_NAME);err_regblkdev:	return rc;}static void __exit ub_exit(void){	usb_deregister(&ub_driver);	devfs_remove(DEVFS_NAME);	unregister_blkdev(UB_MAJOR, DRV_NAME);}module_init(ub_init);module_exit(ub_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -