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

📄 aic7xxx_osm.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * Initialize our softc list lock prior to	 * probing for any adapters.	 */	ahc_list_lockinit();	found = ahc_linux_pci_init();	if (!ahc_linux_eisa_init())		found++;		/*	 * Register with the SCSI layer all	 * controllers we've found.	 */	TAILQ_FOREACH(ahc, &ahc_tailq, links) {		if (ahc_linux_register_host(ahc, template) == 0)			found++;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	spin_lock_irq(&io_request_lock);#endif	aic7xxx_detect_complete++;	return (found);}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)/* * Free the passed in Scsi_Host memory structures prior to unloading the * module. */intahc_linux_release(struct Scsi_Host * host){	struct ahc_softc *ahc;	u_long l;	ahc_list_lock(&l);	if (host != NULL) {		/*		 * We should be able to just perform		 * the free directly, but check our		 * list for extra sanity.		 */		ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata);		if (ahc != NULL) {			u_long s;			ahc_lock(ahc, &s);			ahc_intr_enable(ahc, FALSE);			ahc_unlock(ahc, &s);			ahc_free(ahc);		}	}	ahc_list_unlock(&l);	return (0);}#endif/* * Return a string describing the driver. */static const char *ahc_linux_info(struct Scsi_Host *host){	static char buffer[512];	char	ahc_info[256];	char   *bp;	struct ahc_softc *ahc;	bp = &buffer[0];	ahc = *(struct ahc_softc **)host->hostdata;	memset(bp, 0, sizeof(buffer));	strcpy(bp, "Adaptec AIC7XXX EISA/VLB/PCI SCSI HBA DRIVER, Rev ");	strcat(bp, AIC7XXX_DRIVER_VERSION);	strcat(bp, "\n");	strcat(bp, "        <");	strcat(bp, ahc->description);	strcat(bp, ">\n");	strcat(bp, "        ");	ahc_controller_info(ahc, ahc_info);	strcat(bp, ahc_info);	strcat(bp, "\n");	return (bp);}/* * Queue an SCB to the controller. */static intahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)){	struct	 ahc_softc *ahc;	struct	 ahc_linux_device *dev;	u_long	 flags;	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;	/*	 * Save the callback on completion function.	 */	cmd->scsi_done = scsi_done;	ahc_midlayer_entrypoint_lock(ahc, &flags);	/*	 * Close the race of a command that was in the process of	 * being queued to us just as our simq was frozen.  Let	 * DV commands through so long as we are only frozen to	 * perform DV.	 */	if (ahc->platform_data->qfrozen != 0	 && AHC_DV_CMD(cmd) == 0) {		ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);		ahc_linux_queue_cmd_complete(ahc, cmd);		ahc_schedule_completeq(ahc);		ahc_midlayer_entrypoint_unlock(ahc, &flags);		return (0);	}	dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,				   cmd->device->lun, /*alloc*/TRUE);	if (dev == NULL) {		ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);		ahc_linux_queue_cmd_complete(ahc, cmd);		ahc_schedule_completeq(ahc);		ahc_midlayer_entrypoint_unlock(ahc, &flags);		printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",		       ahc_name(ahc));		return (0);	}	cmd->result = CAM_REQ_INPROG << 16;	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe);	if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {		TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);		dev->flags |= AHC_DEV_ON_RUN_LIST;		ahc_linux_run_device_queues(ahc);	}	ahc_midlayer_entrypoint_unlock(ahc, &flags);	return (0);}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static intahc_linux_slave_alloc(Scsi_Device *device){	struct	ahc_softc *ahc;	ahc = *((struct ahc_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id);	return (0);}static intahc_linux_slave_configure(Scsi_Device *device){	struct	ahc_softc *ahc;	struct	ahc_linux_device *dev;	u_long	flags;	ahc = *((struct ahc_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id);	ahc_midlayer_entrypoint_lock(ahc, &flags);	/*	 * Since Linux has attached to the device, configure	 * it so we don't free and allocate the device	 * structure on every command.	 */	dev = ahc_linux_get_device(ahc, device->channel,				   device->id, device->lun,				   /*alloc*/TRUE);	if (dev != NULL) {		dev->flags &= ~AHC_DEV_UNCONFIGURED;		dev->scsi_device = device;		ahc_linux_device_queue_depth(ahc, dev);	}	ahc_midlayer_entrypoint_unlock(ahc, &flags);	return (0);}static voidahc_linux_slave_destroy(Scsi_Device *device){	struct	ahc_softc *ahc;	struct	ahc_linux_device *dev;	u_long	flags;	ahc = *((struct ahc_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id);	ahc_midlayer_entrypoint_lock(ahc, &flags);	dev = ahc_linux_get_device(ahc, device->channel,				   device->id, device->lun,					   /*alloc*/FALSE);	/*	 * Filter out "silly" deletions of real devices by only	 * deleting devices that have had slave_configure()	 * called on them.  All other devices that have not	 * been configured will automatically be deleted by	 * the refcounting process.	 */	if (dev != NULL	 && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {		dev->flags |= AHC_DEV_UNCONFIGURED;		if (TAILQ_EMPTY(&dev->busyq)		 && dev->active == 0	 	 && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)			ahc_linux_free_device(ahc, dev);	}	ahc_midlayer_entrypoint_unlock(ahc, &flags);}#else/* * Sets the queue depth for each SCSI device hanging * off the input host adapter. */static voidahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs){	Scsi_Device *device;	Scsi_Device *ldev;	struct	ahc_softc *ahc;	u_long	flags;	ahc = *((struct ahc_softc **)host->hostdata);	ahc_lock(ahc, &flags);	for (device = scsi_devs; device != NULL; device = device->next) {		/*		 * Watch out for duplicate devices.  This works around		 * some quirks in how the SCSI scanning code does its		 * device management.		 */		for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {			if (ldev->host == device->host			 && ldev->channel == device->channel			 && ldev->id == device->id			 && ldev->lun == device->lun)				break;		}		/* Skip duplicate. */		if (ldev != device)			continue;		if (device->host == host) {			struct	 ahc_linux_device *dev;			/*			 * Since Linux has attached to the device, configure			 * it so we don't free and allocate the device			 * structure on every command.			 */			dev = ahc_linux_get_device(ahc, device->channel,						   device->id, device->lun,						   /*alloc*/TRUE);			if (dev != NULL) {				dev->flags &= ~AHC_DEV_UNCONFIGURED;				dev->scsi_device = device;				ahc_linux_device_queue_depth(ahc, dev);				device->queue_depth = dev->openings						    + dev->active;				if ((dev->flags & (AHC_DEV_Q_BASIC						| AHC_DEV_Q_TAGGED)) == 0) {					/*					 * We allow the OS to queue 2 untagged					 * transactions to us at any time even					 * though we can only execute them					 * serially on the controller/device.					 * This should remove some latency.					 */					device->queue_depth = 2;				}			}		}	}	ahc_unlock(ahc, &flags);}#endif#if defined(__i386__)/* * Return the disk geometry for the given SCSI device. */static int#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,		    sector_t capacity, int geom[]){	uint8_t *bh;#elseahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[]){	struct	scsi_device *sdev = disk->device;	u_long	capacity = disk->capacity;	struct	buffer_head *bh;#endif	int	 heads;	int	 sectors;	int	 cylinders;	int	 ret;	int	 extended;	struct	 ahc_softc *ahc;	u_int	 channel;	ahc = *((struct ahc_softc **)sdev->host->hostdata);	channel = sdev->channel;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)	bh = scsi_bios_ptable(bdev);#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)	bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));#else	bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);#endif	if (bh) {		ret = scsi_partsize(bh, capacity,				    &geom[2], &geom[0], &geom[1]);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)		kfree(bh);#else		brelse(bh);#endif		if (ret != -1)			return (ret);	}	heads = 64;	sectors = 32;	cylinders = aic_sector_div(capacity, heads, sectors);	if (aic7xxx_extended != 0)		extended = 1;	else if (channel == 0)		extended = (ahc->flags & AHC_EXTENDED_TRANS_A) != 0;	else		extended = (ahc->flags & AHC_EXTENDED_TRANS_B) != 0;	if (extended && cylinders >= 1024) {		heads = 255;		sectors = 63;		cylinders = aic_sector_div(capacity, heads, sectors);	}	geom[0] = heads;	geom[1] = sectors;	geom[2] = cylinders;	return (0);}#endif/* * Abort the current SCSI command(s). */static intahc_linux_abort(Scsi_Cmnd *cmd){	int error;	error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);	if (error != 0)		printf("aic7xxx_abort returns 0x%x\n", error);	return (error);}/* * Attempt to send a target reset message to the device that timed out. */static intahc_linux_dev_reset(Scsi_Cmnd *cmd){	int error;	error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);	if (error != 0)		printf("aic7xxx_dev_reset returns 0x%x\n", error);	return (error);}/* * Reset the SCSI bus. */static intahc_linux_bus_reset(Scsi_Cmnd *cmd){	struct ahc_softc *ahc;	u_long s;	int    found;	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;	ahc_midlayer_entrypoint_lock(ahc, &s);	found = ahc_reset_channel(ahc, cmd->device->channel + 'A',				  /*initiate reset*/TRUE);	ahc_linux_run_complete_queue(ahc);	ahc_midlayer_entrypoint_unlock(ahc, &s);	if (bootverbose)		printf("%s: SCSI bus reset delivered. "		       "%d SCBs aborted.\n", ahc_name(ahc), found);	return SUCCESS;}Scsi_Host_Template aic7xxx_driver_template = {	.module			= THIS_MODULE,	.name			= "aic7xxx",	.proc_info		= ahc_linux_proc_info,	.info			= ahc_linux_info,	.queuecommand		= ahc_linux_queue,	.eh_abort_handler	= ahc_linux_abort,	.eh_device_reset_handler = ahc_linux_dev_reset,	.eh_bus_reset_handler	= ahc_linux_bus_reset,#if defined(__i386__)	.bios_param		= ahc_linux_biosparam,#endif	.can_queue		= AHC_MAX_QUEUE,	.this_id		= -1,	.cmd_per_lun		= 2,	.use_clustering		= ENABLE_CLUSTERING,	.slave_alloc		= ahc_linux_slave_alloc,	.slave_configure	= ahc_linux_slave_configure,	.slave_destroy		= ahc_linux_slave_destroy,};/**************************** Tasklet Handler *********************************//* * In 2.4.X and above, this routine is called from a tasklet, * so we must re-acquire our lock prior to executing this code. * In all prior kernels, ahc_schedule_runq() calls this routine * directly and ahc_schedule_runq() is called with our lock held. */static voidahc_runq_tasklet(unsigned long data){	struct ahc_softc* ahc;	struct ahc_linux_device *dev;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	u_long flags;

⌨️ 快捷键说明

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