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

📄 aha1740.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    unchar direction;    unchar *cmd = (unchar *) SCpnt->cmnd;    unchar target = SCpnt->target;    struct aha1740_hostdata *host = HOSTDATA(SCpnt->host);    unsigned long flags;    void *buff = SCpnt->request_buffer;    int bufflen = SCpnt->request_bufflen;    int ecbno;    DEB(int i);    if(*cmd == REQUEST_SENSE)    {	if (bufflen != sizeof(SCpnt->sense_buffer))	{	    printk("Wrong buffer length supplied for request sense (%d)\n",		   bufflen);	}	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;    printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",	   target, *cmd, i, bufflen);    printk("scsi cmd:");    for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);    printk("\n");#endif    /* locate an available ecb */    save_flags(flags);    cli();    ecbno = host->last_ecb_used + 1;		/* An optimization */    if (ecbno >= AHA1740_ECBS)	ecbno = 0;    do {	if (!host->ecb[ecbno].cmdw)	    break;	ecbno++;	if (ecbno >= AHA1740_ECBS)	    ecbno = 0;    } while (ecbno != host->last_ecb_used);    if (host->ecb[ecbno].cmdw)	panic("Unable to find empty ecb for aha1740.\n");    host->ecb[ecbno].cmdw = AHA1740CMD_INIT;	/* SCSI Initiator Command						   doubles as reserved flag */    host->last_ecb_used = ecbno;        restore_flags(flags);#ifdef DEBUG    printk("Sending command (%d %x)...", ecbno, done);#endif    host->ecb[ecbno].cdblen = SCpnt->cmd_len;	/* SCSI Command Descriptor Block Length */    direction = 0;    if (*cmd == READ_10 || *cmd == READ_6)	direction = 1;    else if (*cmd == WRITE_10 || *cmd == WRITE_6)	direction = 0;    memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);    if (SCpnt->use_sg)    {	struct scatterlist * sgpnt;	struct aha1740_chain * cptr;	int i;	DEB(unsigned char * ptr);	host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command  w/scatter-gather*/	SCpnt->host_scribble = (unsigned char *) scsi_malloc(512);	sgpnt = (struct scatterlist *) SCpnt->request_buffer;	cptr = (struct aha1740_chain *) SCpnt->host_scribble; 	if (cptr == NULL) panic("aha1740.c: unable to allocate DMA memory\n");	for(i=0; i<SCpnt->use_sg; i++)	{	    cptr[i].datalen = sgpnt[i].length;	    cptr[i].dataptr = virt_to_bus(sgpnt[i].address);	}	host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain);	host->ecb[ecbno].dataptr = virt_to_bus(cptr);#ifdef DEBUG	printk("cptr %x: ",cptr);	ptr = (unsigned char *) cptr;	for(i=0;i<24;i++) printk("%02x ", ptr[i]);#endif    }    else    {	SCpnt->host_scribble = NULL;	host->ecb[ecbno].datalen = bufflen;	host->ecb[ecbno].dataptr = virt_to_bus(buff);    }    host->ecb[ecbno].lun = SCpnt->lun;    host->ecb[ecbno].ses = 1;	/* Suppress underrun errors */    host->ecb[ecbno].dir = direction;    host->ecb[ecbno].ars = 1;  /* Yes, get the sense on an error */    host->ecb[ecbno].senselen = 12;    host->ecb[ecbno].senseptr = virt_to_bus(host->ecb[ecbno].sense);    host->ecb[ecbno].statusptr = virt_to_bus(host->ecb[ecbno].status);    host->ecb[ecbno].done = done;    host->ecb[ecbno].SCpnt = SCpnt;#ifdef DEBUG    {	int i;	printk("aha1740_command: sending.. ");	for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)	    printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);    }    printk("\n");#endif    if (done)    { /*  The Adaptec Spec says the card is so fast that the loops will	  only be executed once in the code below. Even if this was true	  with the fastest processors when the spec was written, it doesn't	  seem to be true with todays fast processors. We print a warning	  if the code is executed more often than LOOPCNT_WARN. If this	  happens, it should be investigated. If the count reaches	  LOOPCNT_MAX, we assume something is broken; since there is no	  way to return an error (the return value is ignored by the	  mid-level scsi layer) we have to panic (and maybe that's the	  best thing we can do then anyhow). */#define LOOPCNT_WARN 10		/* excessive mbxout wait -> syslog-msg */#define LOOPCNT_MAX 1000000	/* mbxout deadlock -> panic() after ~ 2 sec. */	int loopcnt;	unsigned int base = SCpnt->host->io_port;	DEB(printk("aha1740[%d] critical section\n",ecbno));	save_flags(flags);	cli();	for (loopcnt = 0; ; loopcnt++) {	    if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;	    if (loopcnt == LOOPCNT_WARN) {		printk("aha1740[%d]_mbxout wait!\n",ecbno);		cli(); /* printk may have done a sti()! */	    }	    if (loopcnt == LOOPCNT_MAX)		panic("aha1740.c: mbxout busy!\n");	}	outl(virt_to_bus(host->ecb + ecbno), MBOXOUT0(base));	for (loopcnt = 0; ; loopcnt++) {	    if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;	    if (loopcnt == LOOPCNT_WARN) {		printk("aha1740[%d]_attn wait!\n",ecbno);		cli();	    }	    if (loopcnt == LOOPCNT_MAX)		panic("aha1740.c: attn wait failed!\n");	}	outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */	restore_flags(flags);	DEB(printk("aha1740[%d] request queued.\n",ecbno));    }    else	printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");    return 0;}static void internal_done(Scsi_Cmnd * SCpnt){    SCpnt->SCp.Status++;}int aha1740_command(Scsi_Cmnd * SCpnt){    aha1740_queuecommand(SCpnt, internal_done);    SCpnt->SCp.Status = 0;    while (!SCpnt->SCp.Status)	barrier();    return SCpnt->result;}/* Query the board for its irq_level.  Nothing else matters   in enhanced mode on an EISA bus. */void aha1740_getconfig(unsigned int base, unsigned int *irq_level,		       unsigned int *translation){    static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };    *irq_level = intab[inb(INTDEF(base)) & 0x7];    *translation = inb(RESV1(base)) & 0x1;    outb(inb(INTDEF(base)) | 0x10, INTDEF(base));}int aha1740_detect(Scsi_Host_Template * tpnt){    int count = 0, slot;    DEB(printk("aha1740_detect: \n"));    for ( slot=MINEISA; slot <= MAXEISA; slot++ )    {	int slotbase;	unsigned int irq_level, translation;	struct Scsi_Host *shpnt;	struct aha1740_hostdata *host;	slotbase = SLOTBASE(slot);	/*	 * The ioports for eisa boards are generally beyond that used in the	 * check/allocate region code, but this may change at some point,	 * so we go through the motions.	 */	if (check_region(slotbase, SLOTSIZE))  /* See if in use */	    continue;	if (!aha1740_test_port(slotbase))	    continue;	aha1740_getconfig(slotbase,&irq_level,&translation);	if ((inb(G2STAT(slotbase)) &	     (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT)	{	/* If the card isn't ready, hard reset it */	    outb(G2CNTRL_HRST, G2CNTRL(slotbase));	    outb(0, G2CNTRL(slotbase));	}	printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level);	printk("aha174x: Extended translation %sabled.\n",	       translation ? "en" : "dis");	DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level));	if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL)) {	    printk("Unable to allocate IRQ for adaptec controller.\n");	    continue;	}	shpnt = scsi_register(tpnt, sizeof(struct aha1740_hostdata));	if(shpnt == NULL)	{		free_irq(irq_level, NULL);		continue;	}	request_region(slotbase, SLOTSIZE, "aha1740");	shpnt->base = 0;	shpnt->io_port = slotbase;	shpnt->n_io_port = SLOTSIZE;	shpnt->irq = irq_level;	shpnt->dma_channel = 0xff;	host = HOSTDATA(shpnt);	host->slot = slot;	host->translation = translation;	aha_host[irq_level - 9] = shpnt;	count++;    }    return count;}/* Note:  They following two functions do not apply very well to the Adaptec,   which basically manages its own affairs quite well without our interference,   so I haven't put anything into them.  I can faintly imagine someone with a   *very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(),   but it hasn't happened yet, and doing aborts brings the Adaptec to its   knees.  I cannot (at this moment in time) think of any reason to reset the   card once it's running.  So there. */int aha1740_abort(Scsi_Cmnd * SCpnt){    DEB(printk("aha1740_abort called\n"));    return SCSI_ABORT_SNOOZE;}/* We do not implement a reset function here, but the upper level code assumes   that it will get some kind of response for the command in SCpnt.  We must   oblige, or the command will hang the scsi system */int aha1740_reset(Scsi_Cmnd * SCpnt, unsigned int ignored){    DEB(printk("aha1740_reset called\n"));    return SCSI_RESET_PUNT;}int aha1740_biosparam(Disk * disk, kdev_t dev, int* ip){    int size = disk->capacity;    int extended = HOSTDATA(disk->device->host)->translation;    DEB(printk("aha1740_biosparam\n"));    if (extended && (ip[2] > 1024))    {	ip[0] = 255;	ip[1] = 63;	ip[2] = size / (255 * 63);    }    else    {	ip[0] = 64;	ip[1] = 32;	ip[2] = size >> 11;    }    return 0;}/* Eventually this will go into an include file, but this will be later */static Scsi_Host_Template driver_template = AHA1740;#include "scsi_module.c"/* Okay, you made it all the way through.  As of this writing, 3/31/93, I'mbrad@saturn.gaylord.com or brad@bradpc.gaylord.com.  I'll try to help as timepermits if you have any trouble with this driver.  Happy Linuxing! */

⌨️ 快捷键说明

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