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

📄 aha1542.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (flag & MBOA)			printk("MBOF ");		if (flag & HACC)			printk("HACC ");		if (flag & SCRD)			printk("SCRD ");		printk("status %02x\n", inb(STATUS(shost->io_port)));	};#endif	number_serviced = 0;	needs_restart = 0;	while (1 == 1) {		flag = inb(INTRFLAGS(shost->io_port));		/* Check for unusual interrupts.  If any of these happen, we should		   probably do something special, but for now just printing a message		   is sufficient.  A SCSI reset detected is something that we really		   need to deal with in some way. */		if (flag & ~MBIF) {			if (flag & MBOA)				printk("MBOF ");			if (flag & HACC)				printk("HACC ");			if (flag & SCRD) {				needs_restart = 1;				printk("SCRD ");			}		}		aha1542_intr_reset(shost->io_port);		save_flags(flags);		cli();		mbi = HOSTDATA(shost)->aha1542_last_mbi_used + 1;		if (mbi >= 2 * AHA1542_MAILBOXES)			mbi = AHA1542_MAILBOXES;		do {			if (mb[mbi].status != 0)				break;			mbi++;			if (mbi >= 2 * AHA1542_MAILBOXES)				mbi = AHA1542_MAILBOXES;		} while (mbi != HOSTDATA(shost)->aha1542_last_mbi_used);		if (mb[mbi].status == 0) {			restore_flags(flags);			/* Hmm, no mail.  Must have read it the last time around */			if (!number_serviced && !needs_restart)				printk(KERN_WARNING "aha1542.c: interrupt received, but no mail.\n");			/* We detected a reset.  Restart all pending commands for			   devices that use the hard reset option */			if (needs_restart)				aha1542_restart(shost);			return;		};		mbo = (scsi2int(mb[mbi].ccbptr) - (SCSI_PA(&ccb[0]))) / sizeof(struct ccb);		mbistatus = mb[mbi].status;		mb[mbi].status = 0;		HOSTDATA(shost)->aha1542_last_mbi_used = mbi;		restore_flags(flags);#ifdef DEBUG		{			if (ccb[mbo].tarstat | ccb[mbo].hastat)				printk(KERN_DEBUG "aha1542_command: returning %x (status %d)\n",				       ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status);		};#endif		if (mbistatus == 3)			continue;	/* Aborted command not found */#ifdef DEBUG		printk(KERN_DEBUG "...done %d %d\n", mbo, mbi);#endif		SCtmp = HOSTDATA(shost)->SCint[mbo];		if (!SCtmp || !SCtmp->scsi_done) {			printk(KERN_WARNING "aha1542_intr_handle: Unexpected interrupt\n");			printk(KERN_WARNING "tarstat=%x, hastat=%x idlun=%x ccb#=%d \n", ccb[mbo].tarstat,			       ccb[mbo].hastat, ccb[mbo].idlun, mbo);			return;		}		my_done = SCtmp->scsi_done;		if (SCtmp->host_scribble) {			scsi_free(SCtmp->host_scribble, 512);			SCtmp->host_scribble = 0;		}		/* Fetch the sense data, and tuck it away, in the required slot.  The		   Adaptec automatically fetches it, and there is no guarantee that		   we will still have it in the cdb when we come back */		if (ccb[mbo].tarstat == 2)			memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen],			       sizeof(SCtmp->sense_buffer));		/* is there mail :-) */		/* more error checking left out here */		if (mbistatus != 1)			/* This is surely wrong, but I don't know what's right */			errstatus = makecode(ccb[mbo].hastat, ccb[mbo].tarstat);		else			errstatus = 0;#ifdef DEBUG		if (errstatus)			printk(KERN_DEBUG "(aha1542 error:%x %x %x) ", errstatus,			       ccb[mbo].hastat, ccb[mbo].tarstat);#endif		if (ccb[mbo].tarstat == 2) {#ifdef DEBUG			int i;#endif			DEB(printk("aha1542_intr_handle: sense:"));#ifdef DEBUG			for (i = 0; i < 12; i++)				printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen + i]);			printk("\n");#endif			/*			   DEB(printk("aha1542_intr_handle: buf:"));			   for (i = 0; i < bufflen; i++)			   printk("%02x ", ((unchar *)buff)[i]);			   printk("\n");			 */		}		DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus));		SCtmp->result = errstatus;		HOSTDATA(shost)->SCint[mbo] = NULL;	/* This effectively frees up the mailbox slot, as							   far as queuecommand is concerned */		my_done(SCtmp);		number_serviced++;	};}int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)){	unchar ahacmd = CMD_START_SCSI;	unchar direction;	unchar *cmd = (unchar *) SCpnt->cmnd;	unchar target = SCpnt->target;	unchar lun = SCpnt->lun;	unsigned long flags;	void *buff = SCpnt->request_buffer;	int bufflen = SCpnt->request_bufflen;	int mbo;	struct mailbox *mb;	struct ccb *ccb;	DEB(int i);	mb = HOSTDATA(SCpnt->host)->mb;	ccb = HOSTDATA(SCpnt->host)->ccb;	DEB(if (target > 1) {	    SCpnt->result = DID_TIME_OUT << 16;	    done(SCpnt); return 0;	    }	);	if (*cmd == REQUEST_SENSE) {		/* Don't do the command - we have the sense data already */#if 0		/* scsi_request_sense() provides a buffer of size 256,		   so there is no reason to expect equality */		if (bufflen != sizeof(SCpnt->sense_buffer))			printk(KERN_CRIT "aha1542: Wrong buffer length supplied "			       "for request sense (%d)\n", bufflen);#endif		SCpnt->result = 0;		done(SCpnt);		return 0;	}#ifdef DEBUG	if (*cmd == READ_10 || *cmd == WRITE_10)		i = xscsi2int(cmd + 2);	else if (*cmd == READ_6 || *cmd == WRITE_6)		i = scsi2int(cmd + 2);	else		i = -1;	if (done)		printk(KERN_DEBUG "aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);	else		printk(KERN_DEBUG "aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen);	aha1542_stat();	printk(KERN_DEBUG "aha1542_queuecommand: dumping scsi cmd:");	for (i = 0; i < SCpnt->cmd_len; i++)		printk("%02x ", cmd[i]);	printk("\n");	if (*cmd == WRITE_10 || *cmd == WRITE_6)		return 0;	/* we are still testing, so *don't* write */#endif	/* Use the outgoing mailboxes in a round-robin fashion, because this	   is how the host adapter will scan for them */	save_flags(flags);	cli();	mbo = HOSTDATA(SCpnt->host)->aha1542_last_mbo_used + 1;	if (mbo >= AHA1542_MAILBOXES)		mbo = 0;	do {		if (mb[mbo].status == 0 && HOSTDATA(SCpnt->host)->SCint[mbo] == NULL)			break;		mbo++;		if (mbo >= AHA1542_MAILBOXES)			mbo = 0;	} while (mbo != HOSTDATA(SCpnt->host)->aha1542_last_mbo_used);	if (mb[mbo].status || HOSTDATA(SCpnt->host)->SCint[mbo])		panic("Unable to find empty mailbox for aha1542.\n");	HOSTDATA(SCpnt->host)->SCint[mbo] = SCpnt;	/* This will effectively prevent someone else from							   screwing with this cdb. */	HOSTDATA(SCpnt->host)->aha1542_last_mbo_used = mbo;	restore_flags(flags);#ifdef DEBUG	printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done);#endif	any2scsi(mb[mbo].ccbptr, SCSI_PA(&ccb[mbo]));	/* This gets trashed for some reason */	memset(&ccb[mbo], 0, sizeof(struct ccb));	ccb[mbo].cdblen = SCpnt->cmd_len;	direction = 0;	if (*cmd == READ_10 || *cmd == READ_6)		direction = 8;	else if (*cmd == WRITE_10 || *cmd == WRITE_6)		direction = 16;	memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen);	if (SCpnt->use_sg) {		struct scatterlist *sgpnt;		struct chain *cptr;#ifdef DEBUG		unsigned char *ptr;#endif		int i;		ccb[mbo].op = 2;	/* SCSI Initiator Command  w/scatter-gather */		SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);		sgpnt = (struct scatterlist *) SCpnt->request_buffer;		cptr = (struct chain *) SCpnt->host_scribble;		if (cptr == NULL)			panic("aha1542.c: unable to allocate DMA memory\n");		for (i = 0; i < SCpnt->use_sg; i++) {			if (sgpnt[i].length == 0 || SCpnt->use_sg > 16 ||			    (((int) sgpnt[i].address) & 1) || (sgpnt[i].length & 1)) {				unsigned char *ptr;				printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i);				for (i = 0; i < SCpnt->use_sg; i++) {					printk(KERN_CRIT "%d: %x %x %d\n", i, (unsigned int) sgpnt[i].address, (unsigned int) sgpnt[i].alt_address,					       sgpnt[i].length);				};				printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr);				ptr = (unsigned char *) &cptr[i];				for (i = 0; i < 18; i++)					printk("%02x ", ptr[i]);				panic("Foooooooood fight!");			};			any2scsi(cptr[i].dataptr, SCSI_PA(sgpnt[i].address));			if (SCSI_PA(sgpnt[i].address + sgpnt[i].length - 1) > ISA_DMA_THRESHOLD)				BAD_SG_DMA(SCpnt, sgpnt, SCpnt->use_sg, i);			any2scsi(cptr[i].datalen, sgpnt[i].length);		};		any2scsi(ccb[mbo].datalen, SCpnt->use_sg * sizeof(struct chain));		any2scsi(ccb[mbo].dataptr, SCSI_PA(cptr));#ifdef DEBUG		printk("cptr %x: ", cptr);		ptr = (unsigned char *) cptr;		for (i = 0; i < 18; i++)			printk("%02x ", ptr[i]);#endif	} else {		ccb[mbo].op = 0;	/* SCSI Initiator Command */		SCpnt->host_scribble = NULL;		any2scsi(ccb[mbo].datalen, bufflen);		if (buff && SCSI_PA(buff + bufflen - 1) > ISA_DMA_THRESHOLD)			BAD_DMA(buff, bufflen);		any2scsi(ccb[mbo].dataptr, SCSI_PA(buff));	};	ccb[mbo].idlun = (target & 7) << 5 | direction | (lun & 7);	/*SCSI Target Id */	ccb[mbo].rsalen = 16;	ccb[mbo].linkptr[0] = ccb[mbo].linkptr[1] = ccb[mbo].linkptr[2] = 0;	ccb[mbo].commlinkid = 0;#ifdef DEBUG	{		int i;		printk(KERN_DEBUG "aha1542_command: sending.. ");		for (i = 0; i < sizeof(ccb[mbo]) - 10; i++)			printk("%02x ", ((unchar *) & ccb[mbo])[i]);	};#endif	if (done) {		DEB(printk("aha1542_queuecommand: now waiting for interrupt ");		    aha1542_stat());		SCpnt->scsi_done = done;		mb[mbo].status = 1;		aha1542_out(SCpnt->host->io_port, &ahacmd, 1);	/* start scsi command */		DEB(aha1542_stat());	} else		printk("aha1542_queuecommand: done can't be NULL\n");	return 0;}static void internal_done(Scsi_Cmnd * SCpnt){	SCpnt->SCp.Status++;}int aha1542_command(Scsi_Cmnd * SCpnt){	DEB(printk("aha1542_command: ..calling aha1542_queuecommand\n"));	aha1542_queuecommand(SCpnt, internal_done);	SCpnt->SCp.Status = 0;	while (!SCpnt->SCp.Status)		barrier();	return SCpnt->result;}/* Initialize mailboxes */static void setup_mailboxes(int bse, struct Scsi_Host *shpnt){	int i;	struct mailbox *mb;	struct ccb *ccb;	unchar cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0};	mb = HOSTDATA(shpnt)->mb;	ccb = HOSTDATA(shpnt)->ccb;	for (i = 0; i < AHA1542_MAILBOXES; i++) {		mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0;		any2scsi(mb[i].ccbptr, SCSI_PA(&ccb[i]));	};	aha1542_intr_reset(bse);	/* reset interrupts, so they don't block */	any2scsi((cmd + 2), SCSI_PA(mb));	aha1542_out(bse, cmd, 5);	WAIT(INTRFLAGS(bse), INTRMASK, HACC, 0);	while (0) {fail:		printk(KERN_ERR "aha1542_detect: failed setting up mailboxes\n");	}	aha1542_intr_reset(bse);}static int aha1542_getconfig(int base_io, unsigned char *irq_level, unsigned char *dma_chan, unsigned char *scsi_id){	unchar inquiry_cmd[] = {CMD_RETCONF};	unchar inquiry_result[3];	int i;	i = inb(STATUS(base_io));	if (i & DF) {		i = inb(DATA(base_io));	};	aha1542_out(base_io, inquiry_cmd, 1);	aha1542_in(base_io, inquiry_result, 3);	WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0);	while (0) {fail:		printk(KERN_ERR "aha1542_detect: query board settings\n");	}	aha1542_intr_reset(base_io);	switch (inquiry_result[0]) {	case 0x80:		*dma_chan = 7;		break;	case 0x40:		*dma_chan = 6;		break;	case 0x20:		*dma_chan = 5;		break;	case 0x01:		*dma_chan = 0;		break;	case 0:		/* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel.		   Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */		*dma_chan = 0xFF;		break;	default:		printk(KERN_ERR "Unable to determine Adaptec DMA priority.  Disabling board\n");		return -1;	};	switch (inquiry_result[1]) {	case 0x40:		*irq_level = 15;		break;	case 0x20:		*irq_level = 14;		break;	case 0x8:		*irq_level = 12;		break;	case 0x4:		*irq_level = 11;		break;	case 0x2:		*irq_level = 10;		break;	case 0x1:		*irq_level = 9;		break;	default:		printk(KERN_ERR "Unable to determine Adaptec IRQ level.  Disabling board\n");		return -1;	};	*scsi_id = inquiry_result[2] & 7;	return 0;}/* This function should only be called for 1542C boards - we can detect   the special firmware settings and unlock the board */static int aha1542_mbenable(int base){	static unchar mbenable_cmd[3];	static unchar mbenable_result[2];	int retval;	retval = BIOS_TRANSLATION_6432;	mbenable_cmd[0] = CMD_EXTBIOS;	aha1542_out(base, mbenable_cmd, 1);	if (aha1542_in1(base, mbenable_result, 2))		return retval;	WAITd(INTRFLAGS(base), INTRMASK, HACC, 0, 100);	aha1542_intr_reset(base);

⌨️ 快捷键说明

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