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

📄 mesh.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
			static int mesh_phasemm_seqerr;			mesh_phasemm_seqerr++;			phase_mismatch(ms);			return;		}		printk(KERN_ERR "mesh: sequence error (err=%x exc=%x)\n",		       err, exc);	} else {		printk(KERN_ERR "mesh: unknown error %x (exc=%x)\n", err, exc);	}	mesh_dump_regs(ms);	dumplog(ms, ms->conn_tgt);	if (ms->phase > selecting && (mr->bus_status1 & BS1_BSY)) {		/* try to do what the target wants */		do_abort(ms);		phase_mismatch(ms);		return;	}	ms->stat = DID_ERROR;	mesh_done(ms, 1);}static void handle_exception(struct mesh_state *ms){	int exc;	volatile struct mesh_regs *mr = ms->mesh;	exc = in_8(&mr->exception);	out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE);	if (exc & EXC_RESELECTED) {		static int mesh_resel_exc;		mesh_resel_exc++;		reselected(ms);	} else if (exc == EXC_ARBLOST) {		printk(KERN_DEBUG "mesh: lost arbitration\n");		ms->stat = DID_BUS_BUSY;		mesh_done(ms, 1);	} else if (exc == EXC_SELTO) {		/* selection timed out */		ms->stat = DID_BAD_TARGET;		mesh_done(ms, 1);	} else if (exc == EXC_PHASEMM) {		/* target wants to do something different:		   find out what it wants and do it. */		phase_mismatch(ms);	} else {		printk(KERN_ERR "mesh: can't cope with exception %x\n", exc);		mesh_dump_regs(ms);		dumplog(ms, ms->conn_tgt);		do_abort(ms);		phase_mismatch(ms);	}}static voidmesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs){	struct mesh_state *ms = (struct mesh_state *) dev_id;	volatile struct mesh_regs *mr = ms->mesh;	int intr;#if 0	if (ALLOW_DEBUG(ms->conn_tgt))		printk(KERN_DEBUG "mesh_intr, bs0=%x int=%x exc=%x err=%x "		       "phase=%d msgphase=%d\n", mr->bus_status0,		       mr->interrupt, mr->exception, mr->error,		       ms->phase, ms->msgphase);#endif	while ((intr = in_8(&mr->interrupt)) != 0) {		dlog(ms, "interrupt intr/err/exc/seq=%.8x", 		     MKWORD(intr, mr->error, mr->exception, mr->sequence));		if (intr & INT_ERROR) {			handle_error(ms);		} else if (intr & INT_EXCEPTION) {			handle_exception(ms);		} else if (intr & INT_CMDDONE) {			out_8(&mr->interrupt, INT_CMDDONE);			cmd_complete(ms);		}	}}static voidhandle_msgin(struct mesh_state *ms){	int i, code;	Scsi_Cmnd *cmd = ms->current_req;	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];	if (ms->n_msgin == 0)		return;	code = ms->msgin[0];	if (ALLOW_DEBUG(ms->conn_tgt)) {		printk(KERN_DEBUG "got %d message bytes:", ms->n_msgin);		for (i = 0; i < ms->n_msgin; ++i)			printk(" %x", ms->msgin[i]);		printk("\n");	}	dlog(ms, "msgin msg=%.8x",	     MKWORD(ms->n_msgin, code, ms->msgin[1], ms->msgin[2]));	ms->expect_reply = 0;	ms->n_msgout = 0;	if (ms->n_msgin < msgin_length(ms))		goto reject;	if (cmd)		cmd->SCp.Message = code;	switch (code) {	case COMMAND_COMPLETE:		break;	case EXTENDED_MESSAGE:		switch (ms->msgin[2]) {		case EXTENDED_MODIFY_DATA_POINTER:			ms->data_ptr += (ms->msgin[3] << 24) + ms->msgin[6]				+ (ms->msgin[4] << 16) + (ms->msgin[5] << 8);			break;		case EXTENDED_SDTR:			if (tp->sdtr_state != sdtr_sent) {				/* reply with an SDTR */				add_sdtr_msg(ms);				/* limit period to at least his value,				   offset to no more than his */				if (ms->msgout[3] < ms->msgin[3])					ms->msgout[3] = ms->msgin[3];				if (ms->msgout[4] > ms->msgin[4])					ms->msgout[4] = ms->msgin[4];				set_sdtr(ms, ms->msgout[3], ms->msgout[4]);				ms->msgphase = msg_out;			} else {				set_sdtr(ms, ms->msgin[3], ms->msgin[4]);			}			break;		default:			goto reject;		}		break;	case SAVE_POINTERS:		tp->saved_ptr = ms->data_ptr;		break;	case RESTORE_POINTERS:		ms->data_ptr = tp->saved_ptr;		break;	case DISCONNECT:		ms->phase = disconnecting;		break;	case ABORT:		break;	case MESSAGE_REJECT:		if (tp->sdtr_state == sdtr_sent)			set_sdtr(ms, 0, 0);		break;	case NOP:		break;	default:		if (IDENTIFY_BASE <= code && code <= IDENTIFY_BASE + 7) {			if (cmd == NULL) {				do_abort(ms);				ms->msgphase = msg_out;			} else if (code != cmd->lun + IDENTIFY_BASE) {				printk(KERN_WARNING "mesh: lun mismatch "				       "(%d != %d) on reselection from "				       "target %d\n", i, cmd->lun,				       ms->conn_tgt);			}			break;		}		goto reject;	}	return; reject:	printk(KERN_WARNING "mesh: rejecting message from target %d:",	       ms->conn_tgt);	for (i = 0; i < ms->n_msgin; ++i)		printk(" %x", ms->msgin[i]);	printk("\n");	ms->msgout[0] = MESSAGE_REJECT;	ms->n_msgout = 1;	ms->msgphase = msg_out;}static voidmesh_done(struct mesh_state *ms, int start_next){	Scsi_Cmnd *cmd;	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];	cmd = ms->current_req;	ms->current_req = 0;	tp->current_req = 0;	if (cmd) {		cmd->result = (ms->stat << 16) + cmd->SCp.Status;		if (ms->stat == DID_OK)			cmd->result += (cmd->SCp.Message << 8);		if (DEBUG_TARGET(cmd)) {			printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n",			       cmd->result, ms->data_ptr, cmd->request_bufflen);			if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3)			    && cmd->request_buffer != 0) {				unsigned char *b = cmd->request_buffer;				printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n",				       b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);			}		}		cmd->SCp.this_residual -= ms->data_ptr;		mesh_completed(ms, cmd);	}	if (start_next) {		out_8(&ms->mesh->sequence, SEQ_ENBRESEL);		udelay(1);		ms->phase = idle;		mesh_start(ms);	}}static voidmesh_completed(struct mesh_state *ms, Scsi_Cmnd *cmd){#ifdef MESH_NEW_STYLE_EH	(*cmd->scsi_done)(cmd);#else	if (ms->completed_q == NULL)		ms->completed_q = cmd;	else		ms->completed_qtail->host_scribble = (void *) cmd;	ms->completed_qtail = cmd;	cmd->host_scribble = NULL;	queue_task(&ms->tqueue, &tq_immediate);	mark_bh(IMMEDIATE_BH);#endif /* MESH_NEW_STYLE_EH */}/* * Set up DMA commands for transferring data. */static voidset_dma_cmds(struct mesh_state *ms, Scsi_Cmnd *cmd){	int i, dma_cmd, total, off, dtot;	struct scatterlist *scl;	struct dbdma_cmd *dcmds;	dma_cmd = ms->tgts[ms->conn_tgt].data_goes_out?		OUTPUT_MORE: INPUT_MORE;	dcmds = ms->dma_cmds;	dtot = 0;	if (cmd) {		cmd->SCp.this_residual = cmd->request_bufflen;		if (cmd->use_sg > 0) {			total = 0;			scl = (struct scatterlist *) cmd->buffer;			off = ms->data_ptr;			for (i = 0; i < cmd->use_sg; ++i, ++scl) {				total += scl->length;				if (off >= scl->length) {					off -= scl->length;					continue;				}				if (scl->length > 0xffff)					panic("mesh: scatterlist element >= 64k");				st_le16(&dcmds->req_count, scl->length - off);				st_le16(&dcmds->command, dma_cmd);				st_le32(&dcmds->phy_addr,					virt_to_phys(scl->address) + off);				dcmds->xfer_status = 0;				++dcmds;				dtot += scl->length - off;				off = 0;			}		} else if (ms->data_ptr < cmd->request_bufflen) {			dtot = cmd->request_bufflen - ms->data_ptr;			if (dtot > 0xffff)				panic("mesh: transfer size >= 64k");			st_le16(&dcmds->req_count, dtot);			st_le32(&dcmds->phy_addr,				virt_to_phys(cmd->request_buffer) + ms->data_ptr);			dcmds->xfer_status = 0;			++dcmds;		}	}	if (dtot == 0) {		/* Either the target has overrun our buffer,		   or the caller didn't provide a buffer. */		static char mesh_extra_buf[64];		dtot = sizeof(mesh_extra_buf);		st_le16(&dcmds->req_count, dtot);		st_le32(&dcmds->phy_addr, virt_to_phys(mesh_extra_buf));		dcmds->xfer_status = 0;		++dcmds;	}	dma_cmd += OUTPUT_LAST - OUTPUT_MORE;	st_le16(&dcmds[-1].command, dma_cmd);	memset(dcmds, 0, sizeof(*dcmds));	st_le16(&dcmds->command, DBDMA_STOP);	ms->dma_count = dtot;}static voidhalt_dma(struct mesh_state *ms){	volatile struct dbdma_regs *md = ms->dma;	volatile struct mesh_regs *mr = ms->mesh;	Scsi_Cmnd *cmd = ms->current_req;	int t, nb;	if (!ms->tgts[ms->conn_tgt].data_goes_out) {		/* wait a little while until the fifo drains */		t = 50;		while (t > 0 && mr->fifo_count != 0		       && (in_le32(&md->status) & ACTIVE) != 0) {			--t;			udelay(1);		}	}	out_le32(&md->control, RUN << 16);	/* turn off RUN bit */	nb = (mr->count_hi << 8) + mr->count_lo;	dlog(ms, "halt_dma fc/count=%.6x",	     MKWORD(0, mr->fifo_count, 0, nb));	if (ms->tgts[ms->conn_tgt].data_goes_out)		nb += mr->fifo_count;	/* nb is the number of bytes not yet transferred	   to/from the target. */	ms->data_ptr -= nb;	dlog(ms, "data_ptr %x", ms->data_ptr);	if (ms->data_ptr < 0) {		printk(KERN_ERR "mesh: halt_dma: data_ptr=%d (nb=%d, ms=%p)\n",		       ms->data_ptr, nb, ms);		ms->data_ptr = 0;#ifdef MESH_DBG		dumplog(ms, ms->conn_tgt);		dumpslog(ms);#endif /* MESH_DBG */	} else if (cmd && cmd->request_bufflen != 0 &&		   ms->data_ptr > cmd->request_bufflen) {		printk(KERN_DEBUG "mesh: target %d overrun, "		       "data_ptr=%x total=%x goes_out=%d\n",		       ms->conn_tgt, ms->data_ptr, cmd->request_bufflen,		       ms->tgts[ms->conn_tgt].data_goes_out);	}	ms->dma_started = 0;}/* * Work out whether we expect data to go out from the host adaptor or into it. * (If this information is available from somewhere else in the scsi * code, somebody please let me know :-) */static intdata_goes_out(Scsi_Cmnd *cmd){	switch (cmd->cmnd[0]) {	case CHANGE_DEFINITION: 	case COMPARE:	  	case COPY:	case COPY_VERIFY:	    	case FORMAT_UNIT:	 	case LOG_SELECT:	case MEDIUM_SCAN:	  	case MODE_SELECT:	case MODE_SELECT_10:	case REASSIGN_BLOCKS: 	case RESERVE:	case SEARCH_EQUAL:	  	case SEARCH_EQUAL_12: 	case SEARCH_HIGH:	 	case SEARCH_HIGH_12:  	case SEARCH_LOW:	case SEARCH_LOW_12:	case SEND_DIAGNOSTIC: 	case SEND_VOLUME_TAG:	     	case SET_WINDOW: 	case UPDATE_BLOCK:		case WRITE_BUFFER: 	case WRITE_6:		case WRITE_10:		case WRITE_12:	  	case WRITE_LONG:		case WRITE_LONG_2:      /* alternate code for WRITE_LONG */	case WRITE_SAME:		case WRITE_VERIFY:	case WRITE_VERIFY_12:		return 1;	default:		return 0;	}}#ifdef MESH_DBGstatic inline u32 readtb(void){	u32 tb;#ifdef DBG_USE_TB	/* Beware: if you enable this, it will crash on 601s. */	asm ("mftb %0" : "=r" (tb) : );#else	tb = 0;#endif	return tb;}static void dlog(struct mesh_state *ms, char *fmt, int a){	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];	struct dbglog *tlp, *slp;	tlp = &tp->log[tp->log_ix];	slp = &ms->log[ms->log_ix];	tlp->fmt = fmt;	tlp->tb = readtb();	tlp->phase = (ms->msgphase << 4) + ms->phase;	tlp->bs0 = ms->mesh->bus_status0;	tlp->bs1 = ms->mesh->bus_status1;	tlp->tgt = ms->conn_tgt;	tlp->d = a;	*slp = *tlp;	if (++tp->log_ix >= N_DBG_LOG)		tp->log_ix = 0;	if (tp->n_log < N_DBG_LOG)		++tp->n_log;	if (++ms->log_ix >= N_DBG_SLOG)		ms->log_ix = 0;	if (ms->n_log < N_DBG_SLOG)		++ms->n_log;}static void dumplog(struct mesh_state *ms, int t){	struct mesh_target *tp = &ms->tgts[t];	struct dbglog *lp;	int i;	if (tp->n_log == 0)		return;	i = tp->log_ix - tp->n_log;	if (i < 0)		i += N_DBG_LOG;	tp->n_log = 0;	do {		lp = &tp->log[i];		printk(KERN_DEBUG "mesh log %d: bs=%.2x%.2x ph=%.2x ",		       t, lp->bs1, lp->bs0, lp->phase);#ifdef DBG_USE_TB		printk("tb=%10u ", lp->tb);#endif		printk(lp->fmt, lp->d);		printk("\n");		if (++i >= N_DBG_LOG)			i = 0;	} while (i != tp->log_ix);}static void dumpslog(struct mesh_state *ms){	struct dbglog *lp;	int i;	if (ms->n_log == 0)		return;	i = ms->log_ix - ms->n_log;	if (i < 0)		i += N_DBG_SLOG;	ms->n_log = 0;	do {		lp = &ms->log[i];		printk(KERN_DEBUG "mesh log: bs=%.2x%.2x ph=%.2x t%d ",		       lp->bs1, lp->bs0, lp->phase, lp->tgt);#ifdef DBG_USE_TB		printk("tb=%10u ", lp->tb);#endif		printk(lp->fmt, lp->d);		printk("\n");		if (++i >= N_DBG_SLOG)			i = 0;	} while (i != ms->log_ix);}#endif /* MESH_DBG */static Scsi_Host_Template driver_template = SCSI_MESH;#include "scsi_module.c"

⌨️ 快捷键说明

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