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

📄 aic79xx_osm.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		 * the free directly, but check our		 * list for extra sanity.		 */		ahd = ahd_find_softc(*(struct ahd_softc **)host->hostdata);		if (ahd != NULL) {			u_long s;			ahd_lock(ahd, &s);			ahd_intr_enable(ahd, FALSE);			ahd_unlock(ahd, &s);			ahd_free(ahd);		}	}	ahd_list_unlock(&l);	return (0);}#endif/* * Return a string describing the driver. */static const char *ahd_linux_info(struct Scsi_Host *host){	static char buffer[512];	char	ahd_info[256];	char   *bp;	struct ahd_softc *ahd;	bp = &buffer[0];	ahd = *(struct ahd_softc **)host->hostdata;	memset(bp, 0, sizeof(buffer));	strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev ");	strcat(bp, AIC79XX_DRIVER_VERSION);	strcat(bp, "\n");	strcat(bp, "        <");	strcat(bp, ahd->description);	strcat(bp, ">\n");	strcat(bp, "        ");	ahd_controller_info(ahd, ahd_info);	strcat(bp, ahd_info);	strcat(bp, "\n");	return (bp);}/* * Queue an SCB to the controller. */static intahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)){	struct	 ahd_softc *ahd;	struct	 ahd_linux_device *dev;	u_long	 flags;	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;	/*	 * Save the callback on completion function.	 */	cmd->scsi_done = scsi_done;	ahd_midlayer_entrypoint_lock(ahd, &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 (ahd->platform_data->qfrozen != 0	 && AHD_DV_CMD(cmd) == 0) {		ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);		ahd_linux_queue_cmd_complete(ahd, cmd);		ahd_schedule_completeq(ahd);		ahd_midlayer_entrypoint_unlock(ahd, &flags);		return (0);	}	dev = ahd_linux_get_device(ahd, cmd->device->channel,				   cmd->device->id, cmd->device->lun,				   /*alloc*/TRUE);	if (dev == NULL) {		ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);		ahd_linux_queue_cmd_complete(ahd, cmd);		ahd_schedule_completeq(ahd);		ahd_midlayer_entrypoint_unlock(ahd, &flags);		printf("%s: aic79xx_linux_queue - Unable to allocate device!\n",		       ahd_name(ahd));		return (0);	}	if (cmd->cmd_len > MAX_CDB_LEN)		return (-EINVAL);	cmd->result = CAM_REQ_INPROG << 16;	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe);	if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {		TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);		dev->flags |= AHD_DEV_ON_RUN_LIST;		ahd_linux_run_device_queues(ahd);	}	ahd_midlayer_entrypoint_unlock(ahd, &flags);	return (0);}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static intahd_linux_slave_alloc(Scsi_Device *device){	struct	ahd_softc *ahd;	ahd = *((struct ahd_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Alloc %d\n", ahd_name(ahd), device->id);	return (0);}static intahd_linux_slave_configure(Scsi_Device *device){	struct	ahd_softc *ahd;	struct	ahd_linux_device *dev;	u_long	flags;	ahd = *((struct ahd_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Configure %d\n", ahd_name(ahd), device->id);	ahd_midlayer_entrypoint_lock(ahd, &flags);	/*	 * Since Linux has attached to the device, configure	 * it so we don't free and allocate the device	 * structure on every command.	 */	dev = ahd_linux_get_device(ahd, device->channel,				   device->id, device->lun,				   /*alloc*/TRUE);	if (dev != NULL) {		dev->flags &= ~AHD_DEV_UNCONFIGURED;		dev->flags |= AHD_DEV_SLAVE_CONFIGURED;		dev->scsi_device = device;		ahd_linux_device_queue_depth(ahd, dev);	}	ahd_midlayer_entrypoint_unlock(ahd, &flags);	return (0);}static voidahd_linux_slave_destroy(Scsi_Device *device){	struct	ahd_softc *ahd;	struct	ahd_linux_device *dev;	u_long	flags;	ahd = *((struct ahd_softc **)device->host->hostdata);	if (bootverbose)		printf("%s: Slave Destroy %d\n", ahd_name(ahd), device->id);	ahd_midlayer_entrypoint_lock(ahd, &flags);	dev = ahd_linux_get_device(ahd, 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 & AHD_DEV_SLAVE_CONFIGURED) != 0) {		dev->flags |= AHD_DEV_UNCONFIGURED;		if (TAILQ_EMPTY(&dev->busyq)		 && dev->active == 0		 && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0)			ahd_linux_free_device(ahd, dev);	}	ahd_midlayer_entrypoint_unlock(ahd, &flags);}#else/* * Sets the queue depth for each SCSI device hanging * off the input host adapter. */static voidahd_linux_select_queue_depth(struct Scsi_Host * host,			     Scsi_Device * scsi_devs){	Scsi_Device *device;	Scsi_Device *ldev;	struct	ahd_softc *ahd;	u_long	flags;	ahd = *((struct ahd_softc **)host->hostdata);	ahd_lock(ahd, &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	 ahd_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 = ahd_linux_get_device(ahd, device->channel,						   device->id, device->lun,						   /*alloc*/TRUE);			if (dev != NULL) {				dev->flags &= ~AHD_DEV_UNCONFIGURED;				dev->scsi_device = device;				ahd_linux_device_queue_depth(ahd, dev);				device->queue_depth = dev->openings						    + dev->active;				if ((dev->flags & (AHD_DEV_Q_BASIC						| AHD_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;				}			}		}	}	ahd_unlock(ahd, &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)ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,		    sector_t capacity, int geom[]){	uint8_t *bh;#elseahd_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	 ahd_softc *ahd;	ahd = *((struct ahd_softc **)sdev->host->hostdata);#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 (aic79xx_extended != 0)		extended = 1;	else		extended = (ahd->flags & AHD_EXTENDED_TRANS_A) != 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 intahd_linux_abort(Scsi_Cmnd *cmd){	struct ahd_softc *ahd;	struct ahd_cmd *acmd;	struct ahd_cmd *list_acmd;	struct ahd_linux_device *dev;	struct scb *pending_scb;	u_long s;	u_int  saved_scbptr;	u_int  active_scbptr;	u_int  last_phase;	u_int  cdb_byte;	int    retval;	int    was_paused;	int    paused;	int    wait;	int    disconnected;	ahd_mode_state saved_modes;	pending_scb = NULL;	paused = FALSE;	wait = FALSE;	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;	acmd = (struct ahd_cmd *)cmd;	printf("%s:%d:%d:%d: Attempting to abort cmd %p:",	       ahd_name(ahd), cmd->device->channel, cmd->device->id,	       cmd->device->lun, cmd);	for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)		printf(" 0x%x", cmd->cmnd[cdb_byte]);	printf("\n");	/*	 * In all versions of Linux, we have to work around	 * a major flaw in how the mid-layer is locked down	 * if we are to sleep successfully in our error handler	 * while allowing our interrupt handler to run.  Since	 * the midlayer acquires either the io_request_lock or	 * our lock prior to calling us, we must use the	 * spin_unlock_irq() method for unlocking our lock.	 * This will force interrupts to be enabled on the	 * current CPU.  Since the EH thread should not have	 * been running with CPU interrupts disabled other than	 * by acquiring either the io_request_lock or our own	 * lock, this *should* be safe.	 */	ahd_midlayer_entrypoint_lock(ahd, &s);	/*	 * First determine if we currently own this command.	 * Start by searching the device queue.  If not found	 * there, check the pending_scb list.  If not found	 * at all, and the system wanted us to just abort the	 * command, return success.	 */	dev = ahd_linux_get_device(ahd, cmd->device->channel,				   cmd->device->id, cmd->device->lun,				   /*alloc*/FALSE);	if (dev == NULL) {		/*		 * No target device for this command exists,		 * so we must not still own the command.		 */		printf("%s:%d:%d:%d: Is not an active device\n",		       ahd_name(ahd), cmd->device->channel, cmd->device->id,		       cmd->device->lun);		retval = SUCCESS;		goto no_cmd;	}	TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {		if (list_acmd == acmd)			break;	}	if (list_acmd != NULL) {		printf("%s:%d:%d:%d: Command found on device queue\n",		       ahd_name(ahd), cmd->device->channel, cmd->device->id,		       cmd->device->lun);		TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);		cmd->result = DID_ABORT << 16;		ahd_linux_queue_cmd_complete(ahd, cmd);		retval = SUCCESS;		goto done;	}	/*	 * See if we can find a matching cmd in the pending list.	 */	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {		if (pending_scb->io_ctx == cmd)			break;	}	if (pending_scb == NULL) {		printf("%s:%d:%d:%d: Command not found\n",		       ahd_name(ahd), cmd->device->channel, cmd->device->id,		       cmd->device->lun);		goto no_cmd;	}	if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {		/*		 * We can't queue two recovery actions using the same SCB		 */		retval = FAILED;		goto  done;	}	/*	 * Ensure that the card doesn't do anything	 * behind our back.  Also make sure that we	 * didn't "just" miss an interrupt that would	 * affect this cmd.	 */	was_paused = ahd_is_paused(ahd);	ahd_pause_and_flushwork(ahd);	paused = TRUE;	if ((pending_scb->flags & SCB_ACTIVE) == 0) {		printf("%s:%d:%d:%d: Command already completed\n",		       ahd_name(ahd), cmd->device->channel, cmd->device->id,		       cmd->device->lun);

⌨️ 快捷键说明

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