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

📄 imm.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* If not, drop back down to the scheduler and wait a timer tick */	if (!(r & 0x80))	    return 0;    }    return 1;			/* FINISH_RETURN */}/* deprecated synchronous interface */int imm_command(Scsi_Cmnd * cmd){    static int first_pass = 1;    int host_no = cmd->host->unique_id;    if (first_pass) {	printk("imm: using non-queuing interface\n");	first_pass = 0;    }    if (imm_hosts[host_no].cur_cmd) {	printk("IMM: bug in imm_command\n");	return 0;    }    imm_hosts[host_no].failed = 0;    imm_hosts[host_no].jstart = jiffies;    imm_hosts[host_no].cur_cmd = cmd;    cmd->result = DID_ERROR << 16;	/* default return code */    cmd->SCp.phase = 0;    imm_pb_claim(host_no);    while (imm_engine(&imm_hosts[host_no], cmd))	schedule();    if (cmd->SCp.phase)		/* Only disconnect if we have connected */	imm_disconnect(cmd->host->unique_id);    imm_pb_release(host_no);    imm_hosts[host_no].cur_cmd = 0;    return cmd->result;}/* * Since the IMM itself doesn't generate interrupts, we use * the scheduler's task queue to generate a stream of call-backs and * complete the request when the drive is ready. */static void imm_interrupt(void *data){    imm_struct *tmp = (imm_struct *) data;    Scsi_Cmnd *cmd = tmp->cur_cmd;    unsigned long flags;    if (!cmd) {	printk("IMM: bug in imm_interrupt\n");	return;    }    if (imm_engine(tmp, cmd)) {	tmp->imm_tq.data = (void *) tmp;	tmp->imm_tq.sync = 0;	queue_task(&tmp->imm_tq, &tq_timer);	return;    }    /* Command must of completed hence it is safe to let go... */#if IMM_DEBUG > 0    switch ((cmd->result >> 16) & 0xff) {    case DID_OK:	break;    case DID_NO_CONNECT:	printk("imm: no device at SCSI ID %i\n", cmd->target);	break;    case DID_BUS_BUSY:	printk("imm: BUS BUSY - EPP timeout detected\n");	break;    case DID_TIME_OUT:	printk("imm: unknown timeout\n");	break;    case DID_ABORT:	printk("imm: told to abort\n");	break;    case DID_PARITY:	printk("imm: parity error (???)\n");	break;    case DID_ERROR:	printk("imm: internal driver error\n");	break;    case DID_RESET:	printk("imm: told to reset device\n");	break;    case DID_BAD_INTR:	printk("imm: bad interrupt (???)\n");	break;    default:	printk("imm: bad return code (%02x)\n", (cmd->result >> 16) & 0xff);    }#endif    if (cmd->SCp.phase > 1)	imm_disconnect(cmd->host->unique_id);    if (cmd->SCp.phase > 0)	imm_pb_release(cmd->host->unique_id);    spin_lock_irqsave(&io_request_lock, flags);    tmp->cur_cmd = 0;    cmd->scsi_done(cmd);    spin_unlock_irqrestore(&io_request_lock, flags);    return;}static int imm_engine(imm_struct * tmp, Scsi_Cmnd * cmd){    int host_no = cmd->host->unique_id;    unsigned short ppb = IMM_BASE(host_no);    unsigned char l = 0, h = 0;    int retv, x;    /* First check for any errors that may of occurred     * Here we check for internal errors     */    if (tmp->failed)	return 0;    switch (cmd->SCp.phase) {    case 0:			/* Phase 0 - Waiting for parport */	if ((jiffies - tmp->jstart) > HZ) {	    /*	     * We waited more than a second	     * for parport to call us	     */	    imm_fail(host_no, DID_BUS_BUSY);	    return 0;	}	return 1;		/* wait until imm_wakeup claims parport */	/* Phase 1 - Connected */    case 1:	imm_connect(host_no, CONNECT_EPP_MAYBE);	cmd->SCp.phase++;	/* Phase 2 - We are now talking to the scsi bus */    case 2:	if (!imm_select(host_no, cmd->target)) {	    imm_fail(host_no, DID_NO_CONNECT);	    return 0;	}	cmd->SCp.phase++;	/* Phase 3 - Ready to accept a command */    case 3:	w_ctr(ppb, 0x0c);	if (!(r_str(ppb) & 0x80))	    return 1;	if (!imm_send_command(cmd))	    return 0;	cmd->SCp.phase++;	/* Phase 4 - Setup scatter/gather buffers */    case 4:	if (cmd->use_sg) {	    /* if many buffers are available, start filling the first */	    cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;	    cmd->SCp.this_residual = cmd->SCp.buffer->length;	    cmd->SCp.ptr = cmd->SCp.buffer->address;	} else {	    /* else fill the only available buffer */	    cmd->SCp.buffer = NULL;	    cmd->SCp.this_residual = cmd->request_bufflen;	    cmd->SCp.ptr = cmd->request_buffer;	}	cmd->SCp.buffers_residual = cmd->use_sg;	cmd->SCp.phase++;	if (cmd->SCp.this_residual & 0x01)	    cmd->SCp.this_residual++;	/* Phase 5 - Pre-Data transfer stage */    case 5:	/* Spin lock for BUSY */	w_ctr(ppb, 0x0c);	if (!(r_str(ppb) & 0x80))	    return 1;	/* Require negotiation for read requests */	x = (r_str(ppb) & 0xb8);	tmp->rd = (x & 0x10) ? 1 : 0;	tmp->dp = (x & 0x20) ? 0 : 1;	if ((tmp->dp) && (tmp->rd))	    if (imm_negotiate(tmp))		return 0;	cmd->SCp.phase++;	/* Phase 6 - Data transfer stage */    case 6:	/* Spin lock for BUSY */	w_ctr(ppb, 0x0c);	if (!(r_str(ppb) & 0x80))	    return 1;	if (tmp->dp) {	    retv = imm_completion(cmd);	    if (retv == -1)		return 0;	    if (retv == 0)		return 1;	}	cmd->SCp.phase++;	/* Phase 7 - Post data transfer stage */    case 7:	if ((tmp->dp) && (tmp->rd)) {	    if ((tmp->mode == IMM_NIBBLE) || (tmp->mode == IMM_PS2)) {		w_ctr(ppb, 0x4);		w_ctr(ppb, 0xc);		w_ctr(ppb, 0xe);		w_ctr(ppb, 0x4);	    }	}	cmd->SCp.phase++;	/* Phase 8 - Read status/message */    case 8:	/* Check for data overrun */	if (imm_wait(host_no) != (unsigned char) 0xb8) {	    imm_fail(host_no, DID_ERROR);	    return 0;	}	if (imm_negotiate(tmp))	    return 0;	if (imm_in(host_no, &l, 1)) {	/* read status byte */	    /* Check for optional message byte */	    if (imm_wait(host_no) == (unsigned char) 0xb8)		imm_in(host_no, &h, 1);	    cmd->result = (DID_OK << 16) + (l & STATUS_MASK);	}	if ((tmp->mode == IMM_NIBBLE) || (tmp->mode == IMM_PS2)) {	    w_ctr(ppb, 0x4);	    w_ctr(ppb, 0xc);	    w_ctr(ppb, 0xe);	    w_ctr(ppb, 0x4);	}	return 0;		/* Finished */	break;    default:	printk("imm: Invalid scsi phase\n");    }    return 0;}int imm_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)){    int host_no = cmd->host->unique_id;    if (imm_hosts[host_no].cur_cmd) {	printk("IMM: bug in imm_queuecommand\n");	return 0;    }    imm_hosts[host_no].failed = 0;    imm_hosts[host_no].jstart = jiffies;    imm_hosts[host_no].cur_cmd = cmd;    cmd->scsi_done = done;    cmd->result = DID_ERROR << 16;	/* default return code */    cmd->SCp.phase = 0;		/* bus free */    imm_pb_claim(host_no);    imm_hosts[host_no].imm_tq.data = imm_hosts + host_no;    imm_hosts[host_no].imm_tq.sync = 0;    queue_task(&imm_hosts[host_no].imm_tq, &tq_immediate);    mark_bh(IMMEDIATE_BH);    return 0;}/* * Apparently the the disk->capacity attribute is off by 1 sector  * for all disk drives.  We add the one here, but it should really * be done in sd.c.  Even if it gets fixed there, this will still * work. */int imm_biosparam(Disk * disk, kdev_t dev, int ip[]){    ip[0] = 0x40;    ip[1] = 0x20;    ip[2] = (disk->capacity + 1) / (ip[0] * ip[1]);    if (ip[2] > 1024) {	ip[0] = 0xff;	ip[1] = 0x3f;	ip[2] = (disk->capacity + 1) / (ip[0] * ip[1]);    }    return 0;}int imm_abort(Scsi_Cmnd * cmd){    int host_no = cmd->host->unique_id;    /*     * There is no method for aborting commands since Iomega     * have tied the SCSI_MESSAGE line high in the interface     */    switch (cmd->SCp.phase) {    case 0:			/* Do not have access to parport */    case 1:			/* Have not connected to interface */	imm_hosts[host_no].cur_cmd = NULL;	/* Forget the problem */	return SUCCESS;	break;    default:			/* SCSI command sent, can not abort */	return FAILED;	break;    }}void imm_reset_pulse(unsigned int base){    w_ctr(base, 0x04);    w_dtr(base, 0x40);    udelay(1);    w_ctr(base, 0x0c);    w_ctr(base, 0x0d);    udelay(50);    w_ctr(base, 0x0c);    w_ctr(base, 0x04);}int imm_reset(Scsi_Cmnd * cmd){    int host_no = cmd->host->unique_id;    if (cmd->SCp.phase)	imm_disconnect(host_no);    imm_hosts[host_no].cur_cmd = NULL;	/* Forget the problem */    imm_connect(host_no, CONNECT_NORMAL);    imm_reset_pulse(IMM_BASE(host_no));    udelay(1000);		/* device settle delay */    imm_disconnect(host_no);    udelay(1000);		/* device settle delay */    return SUCCESS;}static int device_check(int host_no){    /* This routine looks for a device and then attempts to use EPP       to send a command. If all goes as planned then EPP is available. */    static char cmd[6] =    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};    int loop, old_mode, status, k, ppb = IMM_BASE(host_no);    unsigned char l;    old_mode = imm_hosts[host_no].mode;    for (loop = 0; loop < 8; loop++) {	/* Attempt to use EPP for Test Unit Ready */	if ((ppb & 0x0007) == 0x0000)	    imm_hosts[host_no].mode = IMM_EPP_32;      second_pass:	imm_connect(host_no, CONNECT_EPP_MAYBE);	/* Select SCSI device */	if (!imm_select(host_no, loop)) {	    imm_disconnect(host_no);	    continue;	}	printk("imm: Found device at ID %i, Attempting to use %s\n", loop,	       IMM_MODE_STRING[imm_hosts[host_no].mode]);	/* Send SCSI command */	status = 1;	w_ctr(ppb, 0x0c);	for (l = 0; (l < 3) && (status); l++)	    status = imm_out(host_no, &cmd[l << 1], 2);	if (!status) {            imm_disconnect(host_no);            imm_connect(host_no, CONNECT_EPP_MAYBE);            imm_reset_pulse(IMM_BASE(host_no));            udelay(1000);            imm_disconnect(host_no);            udelay(1000);            if (imm_hosts[host_no].mode == IMM_EPP_32) {                imm_hosts[host_no].mode = old_mode;                goto second_pass;            }	    printk("imm: Unable to establish communication, aborting driver load.\n");	    return 1;	}	w_ctr(ppb, 0x0c);	k = 1000000;		/* 1 Second */	do {	    l = r_str(ppb);	    k--;	    udelay(1);	} while (!(l & 0x80) && (k));	l &= 0xb8;	if (l != 0xb8) {	    imm_disconnect(host_no);	    imm_connect(host_no, CONNECT_EPP_MAYBE);	    imm_reset_pulse(IMM_BASE(host_no));	    udelay(1000);	    imm_disconnect(host_no);	    udelay(1000);	    if (imm_hosts[host_no].mode == IMM_EPP_32) {		imm_hosts[host_no].mode = old_mode;		goto second_pass;	    }	    printk("imm: Unable to establish communication, aborting driver load.\n");	    return 1;	}	imm_disconnect(host_no);	printk("imm: Communication established at 0x%x with ID %i using %s\n", ppb, loop,	       IMM_MODE_STRING[imm_hosts[host_no].mode]);	imm_connect(host_no, CONNECT_EPP_MAYBE);	imm_reset_pulse(IMM_BASE(host_no));	udelay(1000);	imm_disconnect(host_no);	udelay(1000);	return 0;    }    printk("imm: No devices found, aborting driver load.\n");    return 1;}

⌨️ 快捷键说明

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