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

📄 aha152x.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}#endif	printk("detected %d controller(s)\n", setup_count);	for (i = 0; i < setup_count; i++) {		struct Scsi_Host *shpnt;		unsigned long int the_time;		shpnt = aha152x_host[setup[i].irq - IRQ_MIN] =		    scsi_register(tpnt, sizeof(struct aha152x_hostdata));		registered_count++;		shpnt->io_port = setup[i].io_port;		shpnt->n_io_port = IO_RANGE;		shpnt->irq = setup[i].irq;		ISSUE_SC = (Scsi_Cmnd *) NULL;		CURRENT_SC = (Scsi_Cmnd *) NULL;		DISCONNECTED_SC = (Scsi_Cmnd *) NULL;		HOSTDATA(shpnt)->reconnect = setup[i].reconnect;		HOSTDATA(shpnt)->parity = setup[i].parity;		HOSTDATA(shpnt)->synchronous = setup[i].synchronous;		HOSTDATA(shpnt)->delay = setup[i].delay;		HOSTDATA(shpnt)->ext_trans = setup[i].ext_trans;#ifdef DEBUG_AHA152X		HOSTDATA(shpnt)->debug = setup[i].debug;#endif		HOSTDATA(shpnt)->aborting = 0;		HOSTDATA(shpnt)->abortion_complete = 0;		HOSTDATA(shpnt)->abort_result = 0;		HOSTDATA(shpnt)->commands = 0;		HOSTDATA(shpnt)->message_len = 0;		for (j = 0; j < 8; j++)			HOSTDATA(shpnt)->syncrate[j] = 0;		SETPORT(SCSIID, setup[i].scsiid << 4);		shpnt->this_id = setup[i].scsiid;		if (setup[i].reconnect)			shpnt->can_queue = AHA152X_MAXQUEUE;		/* RESET OUT */		SETBITS(SCSISEQ, SCSIRSTO);		do_pause(30);		CLRBITS(SCSISEQ, SCSIRSTO);		do_pause(setup[i].delay);		aha152x_reset_ports(shpnt);		printk("aha152x%d: vital data: PORTBASE=0x%03lx, IRQ=%d, SCSI ID=%d,"		       " reconnect=%s, parity=%s, synchronous=%s, delay=%d, extended translation=%s\n",		       i,		       shpnt->io_port,		       shpnt->irq,		       shpnt->this_id,		     HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled",		       HOSTDATA(shpnt)->parity ? "enabled" : "disabled",		   HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled",		       HOSTDATA(shpnt)->delay,		    HOSTDATA(shpnt)->ext_trans ? "enabled" : "disabled");		request_region(shpnt->io_port, IO_RANGE, "aha152x");	/* Register */		/* not expecting any interrupts */		SETPORT(SIMODE0, 0);		SETPORT(SIMODE1, 0);		SETBITS(DMACNTRL0, INTEN);		ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", shpnt);		if (ok < 0) {			if (ok == -EINVAL)				printk("aha152x%d: bad IRQ %d.\n", i, shpnt->irq);			else if (ok == -EBUSY)				printk("aha152x%d: IRQ %d already in use.\n", i, shpnt->irq);			else				printk("\naha152x%d: Unexpected error code %d on requesting IRQ %d.\n", i, ok, shpnt->irq);			printk("aha152x: driver needs an IRQ.\n");			scsi_unregister(shpnt);			registered_count--;			release_region(shpnt->io_port, IO_RANGE);			shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0;			continue;		}		HOSTDATA(shpnt)->swint = 0;		printk("aha152x: trying software interrupt, ");		SETBITS(DMACNTRL0, SWINT);		the_time = jiffies + 100;		while (!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time))			barrier();		free_irq(shpnt->irq, shpnt);		if (!HOSTDATA(shpnt)->swint) {			if (TESTHI(DMASTAT, INTSTAT)) {				printk("lost.\n");			} else {				printk("failed.\n");			}			printk("aha152x: IRQ %d possibly wrong.  Please verify.\n", shpnt->irq);			scsi_unregister(shpnt);			registered_count--;			release_region(shpnt->io_port, IO_RANGE);			shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0;			continue;		}		printk("ok.\n");		CLRBITS(DMACNTRL0, SWINT);		/* clear interrupts */		SETPORT(SSTAT0, 0x7f);		SETPORT(SSTAT1, 0xef);		if (request_irq(shpnt->irq, aha152x_intr, SA_INTERRUPT, "aha152x", shpnt) < 0) {			printk("aha152x: failed to reassign interrupt.\n");		}	}	return (registered_count > 0);}int aha152x_release(struct Scsi_Host *shpnt){	if (shpnt->irq)		free_irq(shpnt->irq, shpnt);	if (shpnt->io_port)		release_region(shpnt->io_port, IO_RANGE);	return 0;}/*  *  Queue a command and setup interrupts for a free bus. */int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)){	struct Scsi_Host *shpnt = SCpnt->host;	unsigned long flags;#if defined(DEBUG_RACE)	enter_driver("queue");#else#if defined(DEBUG_QUEUE)	if (HOSTDATA(shpnt)->debug & debug_queue)		printk("aha152x: queue(), ");#endif#endif#if defined(DEBUG_QUEUE)	if (HOSTDATA(shpnt)->debug & debug_queue) {		printk("SCpnt (target = %d lun = %d cmnd = ",		       SCpnt->target, SCpnt->lun);		print_command(SCpnt->cmnd);		printk(", cmd_len=%d, pieces = %d size = %u), ",		  SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);		disp_ports(shpnt);	}#endif	SCpnt->scsi_done = done;	/* setup scratch area	   SCp.ptr              : buffer pointer	   SCp.this_residual    : buffer length	   SCp.buffer           : next buffer	   SCp.buffers_residual : left buffers in list	   SCp.phase            : current state of the command */	SCpnt->SCp.phase = not_issued;	if (SCpnt->use_sg) {		SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;		SCpnt->SCp.ptr = SCpnt->SCp.buffer->address;		SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;		SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;	} else {		SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;		SCpnt->SCp.this_residual = SCpnt->request_bufflen;		SCpnt->SCp.buffer = NULL;		SCpnt->SCp.buffers_residual = 0;	}	SCpnt->SCp.Status = CHECK_CONDITION;	SCpnt->SCp.Message = 0;	SCpnt->SCp.have_data_in = 0;	SCpnt->SCp.sent_command = 0;	/* Turn led on, when this is the first command. */	save_flags(flags);	cli();	HOSTDATA(shpnt)->commands++;	if (HOSTDATA(shpnt)->commands == 1)		SETPORT(PORTA, 1);#if defined(DEBUG_QUEUES)	if (HOSTDATA(shpnt)->debug & debug_queues)		printk("i+ (%d), ", HOSTDATA(shpnt)->commands);#endif	append_SC(&ISSUE_SC, SCpnt);	/* Enable bus free interrupt, when we aren't currently on the bus */	if (!CURRENT_SC) {		SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);		SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);	}	restore_flags(flags);#if defined(DEBUG_RACE)	leave_driver("queue");#endif	return 0;}/* *  We only support commands in interrupt-driven fashion */int aha152x_command(Scsi_Cmnd * SCpnt){	printk("aha152x: interrupt driven driver; use aha152x_queue()\n");	return -1;}/* *  Abort a queued command *  (commands that are on the bus can't be aborted easily) */int aha152x_abort(Scsi_Cmnd * SCpnt){	struct Scsi_Host *shpnt = SCpnt->host;	unsigned long flags;	Scsi_Cmnd *ptr, *prev;	save_flags(flags);	cli();#if defined(DEBUG_ABORT)	if (HOSTDATA(shpnt)->debug & debug_abort) {		printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt);		show_queues(shpnt);	}#endif	/* look for command in issue queue */	for (ptr = ISSUE_SC, prev = NULL;	     ptr && ptr != SCpnt;	     prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble);	if (ptr) {		/* dequeue */		if (prev)			prev->host_scribble = ptr->host_scribble;		else			ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble;		HOSTDATA(shpnt)->commands--;		restore_flags(flags);		ptr->host_scribble = NULL;		ptr->result = DID_ABORT << 16;		spin_lock_irqsave(&io_request_lock, flags);		ptr->scsi_done(ptr);		spin_unlock_irqrestore(&io_request_lock, flags);		return SCSI_ABORT_SUCCESS;	}	/* if the bus is busy or a command is currently processed,	   we can't do anything more */	if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC != SCpnt)) {		/* fail abortion, if bus is busy */		if (!CURRENT_SC)			printk("bus busy w/o current command, ");		restore_flags(flags);		return SCSI_ABORT_BUSY;	}	/* bus is free */	if (CURRENT_SC) {		HOSTDATA(shpnt)->commands--;		/* target entered bus free before COMMAND COMPLETE, nothing to abort */		restore_flags(flags);		spin_lock_irqsave(&io_request_lock, flags);		CURRENT_SC->result = DID_ERROR << 16;		CURRENT_SC->scsi_done(CURRENT_SC);		CURRENT_SC = (Scsi_Cmnd *) NULL;		spin_unlock_irqrestore(&io_request_lock, flags);		return SCSI_ABORT_SUCCESS;	}	/* look for command in disconnected queue */	for (ptr = DISCONNECTED_SC, prev = NULL;	     ptr && ptr != SCpnt;	     prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble);	if (!ptr) {		/* command wasn't found */		printk("command not found\n");		restore_flags(flags);		return SCSI_ABORT_NOT_RUNNING;	}	if (!HOSTDATA(shpnt)->aborting) {		/* dequeue */		if (prev)			prev->host_scribble = ptr->host_scribble;		else			DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;		HOSTDATA(shpnt)->commands--;		/* set command current and initiate selection,		   let the interrupt routine take care of the abortion */		CURRENT_SC = ptr;		ptr->SCp.phase = in_selection | aborted;		SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);		ADDMSG(ABORT);		/* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */		SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));		SETPORT(SIMODE1, ENSELTIMO);		/* Enable SELECTION OUT sequence */		SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);		SETBITS(DMACNTRL0, INTEN);		HOSTDATA(shpnt)->abort_result = SCSI_ABORT_SUCCESS;		HOSTDATA(shpnt)->aborting++;		HOSTDATA(shpnt)->abortion_complete = 0;		restore_flags(flags);		/* sleep until the abortion is complete */		while (!HOSTDATA(shpnt)->abortion_complete)			barrier();		HOSTDATA(shpnt)->aborting = 0;		return HOSTDATA(shpnt)->abort_result;	} else {		/* we're already aborting a command */		restore_flags(flags);		return SCSI_ABORT_BUSY;	}}/* *  Restore default values to the AIC-6260 registers and reset the fifos */static void aha152x_reset_ports(struct Scsi_Host *shpnt){	/* disable interrupts */	SETPORT(DMACNTRL0, RSTFIFO);	SETPORT(SCSISEQ, 0);	SETPORT(SXFRCTL1, 0);	SETPORT(SCSISIG, 0);	SETPORT(SCSIRATE, 0);	/* clear all interrupt conditions */	SETPORT(SSTAT0, 0x7f);	SETPORT(SSTAT1, 0xef);	SETPORT(SSTAT4, SYNCERR | FWERR | FRERR);	SETPORT(DMACNTRL0, 0);	SETPORT(DMACNTRL1, 0);	SETPORT(BRSTCNTRL, 0xf1);	/* clear SCSI fifo and transfer count */	SETPORT(SXFRCTL0, CH1 | CLRCH1 | CLRSTCNT);	SETPORT(SXFRCTL0, CH1);	/* enable interrupts */	SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);	SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);}/* *  Reset registers, reset a hanging bus and *  kill active and disconnected commands for target w/o soft reset */int aha152x_reset(Scsi_Cmnd * SCpnt, unsigned int unused){	struct Scsi_Host *shpnt = SCpnt->host;	unsigned long flags;	Scsi_Cmnd *ptr, *prev, *next;	aha152x_reset_ports(shpnt);	/* Reset, if bus hangs */	if (TESTLO(SSTAT1, BUSFREE)) {		CLRBITS(DMACNTRL0, INTEN);#if defined(DEBUG_RESET)		if (HOSTDATA(shpnt)->debug & debug_reset) {			printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");			show_queues(shpnt);		}#endif		ptr = CURRENT_SC;		if (ptr && !ptr->device->soft_reset) {			ptr->host_scribble = NULL;			ptr->result = DID_RESET << 16;			ptr->scsi_done(CURRENT_SC);			CURRENT_SC = NULL;		}		save_flags(flags);		cli();		prev = NULL;		ptr = DISCONNECTED_SC;		while (ptr) {			if (!ptr->device->soft_reset) {				if (prev)					prev->host_scribble = ptr->host_scribble;				else					DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;				next = (Scsi_Cmnd *) ptr->host_scribble;				ptr->host_scribble = NULL;				ptr->result = DID_RESET << 16;				ptr->scsi_done(ptr);				ptr = next;			} else {				prev = ptr;				ptr = (Scsi_Cmnd *) ptr->host_scribble;			}		}		restore_flags(flags);#if defined(DEBUG_RESET)		if (HOSTDATA(shpnt)->debug & debug_reset) {			printk("commands on targets w/ soft-resets:\n");			show_queues(shpnt);		}#endif		/* RESET OUT */		SETPORT(SCSISEQ, SCSIRSTO);		do_pause(30);		SETPORT(SCSISEQ, 0);		do_pause(DELAY);		SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);		SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);		SETPORT(DMACNTRL0, INTEN);	}	return SCSI_RESET_SUCCESS;}/* * Return the "logical geometry" */int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array){	struct Scsi_Host *shpnt = disk->device->host;#if defined(DEBUG_BIOSPARAM)	if (HOSTDATA(shpnt)->debug & debug_biosparam)		printk("aha152x_biosparam: dev=%s, size=%d, ",		       kdevname(dev), disk->capacity);#endif	/* try default translation */	info_array[0] = 64;	info_array[1] = 32;

⌨️ 快捷键说明

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