Linux Audio

Check our new training course

Loading...
v3.1
  1/*  $Id$
  2 *  1993/03/31
  3 *  linux/kernel/aha1740.c
  4 *
  5 *  Based loosely on aha1542.c which is
  6 *  Copyright (C) 1992  Tommy Thorn and
  7 *  Modified by Eric Youngdale
  8 *
  9 *  This file is aha1740.c, written and
 10 *  Copyright (C) 1992,1993  Brad McLean
 11 *  brad@saturn.gaylord.com or brad@bradpc.gaylord.com.
 12 *  
 13 *  Modifications to makecode and queuecommand
 14 *  for proper handling of multiple devices courteously
 15 *  provided by Michael Weller, March, 1993
 16 *
 17 *  Multiple adapter support, extended translation detection,
 18 *  update to current scsi subsystem changes, proc fs support,
 19 *  working (!) module support based on patches from Andreas Arens,
 20 *  by Andreas Degert <ad@papyrus.hamburg.com>, 2/1997
 21 *
 22 * aha1740_makecode may still need even more work
 23 * if it doesn't work for your devices, take a look.
 24 *
 25 * Reworked for new_eh and new locking by Alan Cox <alan@lxorguk.ukuu.org.uk>
 26 *
 27 * Converted to EISA and generic DMA APIs by Marc Zyngier
 28 * <maz@wild-wind.fr.eu.org>, 4/2003.
 29 *
 30 * Shared interrupt support added by Rask Ingemann Lambertsen
 31 * <rask@sygehus.dk>, 10/2003
 32 *
 33 * For the avoidance of doubt the "preferred form" of this code is one which
 34 * is in an open non patent encumbered format. Where cryptographic key signing
 35 * forms part of the process of creating an executable the information
 36 * including keys needed to generate an equivalently functional executable
 37 * are deemed to be part of the source code.
 38 */
 39
 40#include <linux/blkdev.h>
 41#include <linux/interrupt.h>
 42#include <linux/module.h>
 43#include <linux/kernel.h>
 44#include <linux/types.h>
 45#include <linux/string.h>
 46#include <linux/ioport.h>
 47#include <linux/proc_fs.h>
 48#include <linux/stat.h>
 49#include <linux/init.h>
 50#include <linux/device.h>
 51#include <linux/eisa.h>
 52#include <linux/dma-mapping.h>
 53#include <linux/gfp.h>
 54
 55#include <asm/dma.h>
 56#include <asm/system.h>
 57#include <asm/io.h>
 58
 59#include "scsi.h"
 
 
 
 60#include <scsi/scsi_host.h>
 
 61#include "aha1740.h"
 62
 63/* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
 64   IT WORK, THEN:
 65#define DEBUG
 66*/
 67#ifdef DEBUG
 68#define DEB(x) x
 69#else
 70#define DEB(x)
 71#endif
 72
 73struct aha1740_hostdata {
 74	struct eisa_device *edev;
 75	unsigned int translation;
 76	unsigned int last_ecb_used;
 77	dma_addr_t ecb_dma_addr;
 78	struct ecb ecb[AHA1740_ECBS];
 79};
 80
 81struct aha1740_sg {
 82	struct aha1740_chain sg_chain[AHA1740_SCATTER];
 83	dma_addr_t sg_dma_addr;
 84	dma_addr_t buf_dma_addr;
 85};
 86
 87#define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
 88
 89static inline struct ecb *ecb_dma_to_cpu (struct Scsi_Host *host,
 90					  dma_addr_t dma)
 91{
 92	struct aha1740_hostdata *hdata = HOSTDATA (host);
 93	dma_addr_t offset;
 94
 95	offset = dma - hdata->ecb_dma_addr;
 96
 97	return (struct ecb *)(((char *) hdata->ecb) + (unsigned int) offset);
 98}
 99
100static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu)
101{
102	struct aha1740_hostdata *hdata = HOSTDATA (host);
103	dma_addr_t offset;
104    
105	offset = (char *) cpu - (char *) hdata->ecb;
106
107	return hdata->ecb_dma_addr + offset;
108}
109
110static int aha1740_proc_info(struct Scsi_Host *shpnt, char *buffer,
111			     char **start, off_t offset,
112			     int length, int inout)
113{
114	int len;
115	struct aha1740_hostdata *host;
116
117	if (inout)
118		return-ENOSYS;
119
120	host = HOSTDATA(shpnt);
121
122	len = sprintf(buffer, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
123		      "Extended translation %sabled.\n",
124		      shpnt->io_port, shpnt->irq, host->edev->slot,
125		      host->translation ? "en" : "dis");
126
127	if (offset > len) {
128		*start = buffer;
129		return 0;
130	}
131
132	*start = buffer + offset;
133	len -= offset;
134	if (len > length)
135		len = length;
136	return len;
137}
138
139static int aha1740_makecode(unchar *sense, unchar *status)
140{
141	struct statusword
142	{
143		ushort	don:1,	/* Command Done - No Error */
144			du:1,	/* Data underrun */
145		    :1,	qf:1,	/* Queue full */
146		        sc:1,	/* Specification Check */
147		        dor:1,	/* Data overrun */
148		        ch:1,	/* Chaining Halted */
149		        intr:1,	/* Interrupt issued */
150		        asa:1,	/* Additional Status Available */
151		        sns:1,	/* Sense information Stored */
152		    :1,	ini:1,	/* Initialization Required */
153			me:1,	/* Major error or exception */
154		    :1,	eca:1,  /* Extended Contingent alliance */
155		    :1;
156	} status_word;
157	int retval = DID_OK;
158
159	status_word = * (struct statusword *) status;
160#ifdef DEBUG
161	printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",
162	       status[0], status[1], status[2], status[3],
163	       sense[0], sense[1], sense[2], sense[3]);
164#endif
165	if (!status_word.don) { /* Anything abnormal was detected */
166		if ( (status[1]&0x18) || status_word.sc ) {
167			/*Additional info available*/
168			/* Use the supplied info for further diagnostics */
169			switch ( status[2] ) {
170			case 0x12:
171				if ( status_word.dor )
172					retval=DID_ERROR; /* It's an Overrun */
173				/* If not overrun, assume underrun and
174				 * ignore it! */
 
175			case 0x00: /* No info, assume no error, should
176				    * not occur */
177				break;
178			case 0x11:
179			case 0x21:
180				retval=DID_TIME_OUT;
181				break;
182			case 0x0a:
183				retval=DID_BAD_TARGET;
184				break;
185			case 0x04:
186			case 0x05:
187				retval=DID_ABORT;
188				/* Either by this driver or the
189				 * AHA1740 itself */
190				break;
191			default:
192				retval=DID_ERROR; /* No further
193						   * diagnostics
194						   * possible */
195			}
196		} else {
197			/* Michael suggests, and Brad concurs: */
198			if ( status_word.qf ) {
199				retval = DID_TIME_OUT; /* forces a redo */
200				/* I think this specific one should
201				 * not happen -Brad */
202				printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
203			} else
204				if ( status[0]&0x60 ) {
205					 /* Didn't find a better error */
206					retval = DID_ERROR;
207				}
208			/* In any other case return DID_OK so for example
209			   CONDITION_CHECKS make it through to the appropriate
210			   device driver */
211		}
212	}
213	/* Under all circumstances supply the target status -Michael */
214	return status[3] | retval << 16;
215}
216
217static int aha1740_test_port(unsigned int base)
218{
219	if ( inb(PORTADR(base)) & PORTADDR_ENH )
220		return 1;   /* Okay, we're all set */
221	
222	printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
223	return 0;
224}
225
226/* A "high" level interrupt handler */
227static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
228{
229	struct Scsi_Host *host = (struct Scsi_Host *) dev_id;
230        void (*my_done)(Scsi_Cmnd *);
231	int errstatus, adapstat;
232	int number_serviced;
233	struct ecb *ecbptr;
234	Scsi_Cmnd *SCtmp;
235	unsigned int base;
236	unsigned long flags;
237	int handled = 0;
238	struct aha1740_sg *sgptr;
239	struct eisa_device *edev;
240	
241	if (!host)
242		panic("aha1740.c: Irq from unknown host!\n");
243	spin_lock_irqsave(host->host_lock, flags);
244	base = host->io_port;
245	number_serviced = 0;
246	edev = HOSTDATA(host)->edev;
247
248	while(inb(G2STAT(base)) & G2STAT_INTPEND) {
249		handled = 1;
250		DEB(printk("aha1740_intr top of loop.\n"));
251		adapstat = inb(G2INTST(base));
252		ecbptr = ecb_dma_to_cpu (host, inl(MBOXIN0(base)));
253		outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */
254      
255		switch ( adapstat & G2INTST_MASK ) {
256		case	G2INTST_CCBRETRY:
257		case	G2INTST_CCBERROR:
258		case	G2INTST_CCBGOOD:
259			/* Host Ready -> Mailbox in complete */
260			outb(G2CNTRL_HRDY,G2CNTRL(base));
261			if (!ecbptr) {
262				printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
263				       inb(G2STAT(base)),adapstat,
264				       inb(G2INTST(base)), number_serviced++);
265				continue;
266			}
267			SCtmp = ecbptr->SCpnt;
268			if (!SCtmp) {
269				printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
270				       inb(G2STAT(base)),adapstat,
271				       inb(G2INTST(base)), number_serviced++);
272				continue;
273			}
274			sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
275			scsi_dma_unmap(SCtmp);
276
277			/* Free the sg block */
278			dma_free_coherent (&edev->dev,
279					   sizeof (struct aha1740_sg),
280					   SCtmp->host_scribble,
281					   sgptr->sg_dma_addr);
282	    
283			/* Fetch the sense data, and tuck it away, in
284			   the required slot.  The Adaptec
285			   automatically fetches it, and there is no
286			   guarantee that we will still have it in the
287			   cdb when we come back */
288			if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) {
289				memcpy(SCtmp->sense_buffer, ecbptr->sense, 
290				       SCSI_SENSE_BUFFERSIZE);
 
 
 
291				errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
292			} else
293				errstatus = 0;
294			DEB(if (errstatus)
295			    printk("aha1740_intr_handle: returning %6x\n",
296				   errstatus));
297			SCtmp->result = errstatus;
298			my_done = ecbptr->done;
299			memset(ecbptr,0,sizeof(struct ecb)); 
300			if ( my_done )
301				my_done(SCtmp);
302			break;
303			
304		case	G2INTST_HARDFAIL:
305			printk(KERN_ALERT "aha1740 hardware failure!\n");
306			panic("aha1740.c");	/* Goodbye */
307			
308		case	G2INTST_ASNEVENT:
309			printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
310			       adapstat,
311			       inb(MBOXIN0(base)),
312			       inb(MBOXIN1(base)),
313			       inb(MBOXIN2(base)),
314			       inb(MBOXIN3(base))); /* Say What? */
315			/* Host Ready -> Mailbox in complete */
316			outb(G2CNTRL_HRDY,G2CNTRL(base));
317			break;
318			
319		case	G2INTST_CMDGOOD:
320			/* set immediate command success flag here: */
321			break;
322			
323		case	G2INTST_CMDERROR:
324			/* Set immediate command failure flag here: */
325			break;
326		}
327		number_serviced++;
328	}
329
330	spin_unlock_irqrestore(host->host_lock, flags);
331	return IRQ_RETVAL(handled);
332}
333
334static int aha1740_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
335{
 
336	unchar direction;
337	unchar *cmd = (unchar *) SCpnt->cmnd;
338	unchar target = scmd_id(SCpnt);
339	struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
340	unsigned long flags;
341	dma_addr_t sg_dma;
342	struct aha1740_sg *sgptr;
343	int ecbno, nseg;
344	DEB(int i);
345
346	if(*cmd == REQUEST_SENSE) {
347		SCpnt->result = 0;
348		done(SCpnt); 
349		return 0;
350	}
351
352#ifdef DEBUG
353	if (*cmd == READ_10 || *cmd == WRITE_10)
354		i = xscsi2int(cmd+2);
355	else if (*cmd == READ_6 || *cmd == WRITE_6)
356		i = scsi2int(cmd+2);
357	else
358		i = -1;
359	printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
360	       target, *cmd, i, bufflen);
361	printk("scsi cmd:");
362	for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
363	printk("\n");
364#endif
365
366	/* locate an available ecb */
367	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
368	ecbno = host->last_ecb_used + 1; /* An optimization */
369	if (ecbno >= AHA1740_ECBS)
370		ecbno = 0;
371	do {
372		if (!host->ecb[ecbno].cmdw)
373			break;
374		ecbno++;
375		if (ecbno >= AHA1740_ECBS)
376			ecbno = 0;
377	} while (ecbno != host->last_ecb_used);
378
379	if (host->ecb[ecbno].cmdw)
380		panic("Unable to find empty ecb for aha1740.\n");
381
382	host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command
383						    doubles as reserved flag */
384
385	host->last_ecb_used = ecbno;    
386	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
387
388#ifdef DEBUG
389	printk("Sending command (%d %x)...", ecbno, done);
390#endif
391
392	host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command
393						   * Descriptor Block
394						   * Length */
395
396	direction = 0;
397	if (*cmd == READ_10 || *cmd == READ_6)
398		direction = 1;
399	else if (*cmd == WRITE_10 || *cmd == WRITE_6)
400		direction = 0;
401
402	memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
403
404	SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
405						   sizeof (struct aha1740_sg),
406						   &sg_dma, GFP_ATOMIC);
407	if(SCpnt->host_scribble == NULL) {
408		printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
409		return 1;
410	}
411	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
412	sgptr->sg_dma_addr = sg_dma;
413
414	nseg = scsi_dma_map(SCpnt);
415	BUG_ON(nseg < 0);
416	if (nseg) {
417		struct scatterlist *sg;
418		struct aha1740_chain * cptr;
419		int i;
420		DEB(unsigned char * ptr);
421
422		host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
423					   * w/scatter-gather*/
424		cptr = sgptr->sg_chain;
425		scsi_for_each_sg(SCpnt, sg, nseg, i) {
426			cptr[i].datalen = sg_dma_len (sg);
427			cptr[i].dataptr = sg_dma_address (sg);
428		}
429		host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
430		host->ecb[ecbno].dataptr = sg_dma;
431#ifdef DEBUG
432		printk("cptr %x: ",cptr);
433		ptr = (unsigned char *) cptr;
434		for(i=0;i<24;i++) printk("%02x ", ptr[i]);
435#endif
436	} else {
437		host->ecb[ecbno].datalen = 0;
438		host->ecb[ecbno].dataptr = 0;
439	}
440	host->ecb[ecbno].lun = SCpnt->device->lun;
441	host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
442	host->ecb[ecbno].dir = direction;
443	host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */
444	host->ecb[ecbno].senselen = 12;
445	host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
446						    host->ecb[ecbno].sense);
447	host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
448						     host->ecb[ecbno].status);
449	host->ecb[ecbno].done = done;
450	host->ecb[ecbno].SCpnt = SCpnt;
451#ifdef DEBUG
452	{
453		int i;
454		printk("aha1740_command: sending.. ");
455		for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
456			printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
457	}
458	printk("\n");
459#endif
460	if (done) {
461	/* The Adaptec Spec says the card is so fast that the loops
462           will only be executed once in the code below. Even if this
463           was true with the fastest processors when the spec was
464           written, it doesn't seem to be true with today's fast
465           processors. We print a warning if the code is executed more
466           often than LOOPCNT_WARN. If this happens, it should be
467           investigated. If the count reaches LOOPCNT_MAX, we assume
468           something is broken; since there is no way to return an
469           error (the return value is ignored by the mid-level scsi
470           layer) we have to panic (and maybe that's the best thing we
471           can do then anyhow). */
472
473#define LOOPCNT_WARN 10		/* excessive mbxout wait -> syslog-msg */
474#define LOOPCNT_MAX 1000000	/* mbxout deadlock -> panic() after ~ 2 sec. */
475		int loopcnt;
476		unsigned int base = SCpnt->device->host->io_port;
477		DEB(printk("aha1740[%d] critical section\n",ecbno));
478
479		spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
480		for (loopcnt = 0; ; loopcnt++) {
481			if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
482			if (loopcnt == LOOPCNT_WARN) {
483				printk("aha1740[%d]_mbxout wait!\n",ecbno);
484			}
485			if (loopcnt == LOOPCNT_MAX)
486				panic("aha1740.c: mbxout busy!\n");
487		}
488		outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
489		      MBOXOUT0(base));
490		for (loopcnt = 0; ; loopcnt++) {
491			if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
492			if (loopcnt == LOOPCNT_WARN) {
493				printk("aha1740[%d]_attn wait!\n",ecbno);
494			}
495			if (loopcnt == LOOPCNT_MAX)
496				panic("aha1740.c: attn wait failed!\n");
497		}
498		outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
499		spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
500		DEB(printk("aha1740[%d] request queued.\n",ecbno));
501	} else
502		printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
503	return 0;
504}
505
506static DEF_SCSI_QCMD(aha1740_queuecommand)
507
508/* Query the board for its irq_level and irq_type.  Nothing else matters
509   in enhanced mode on an EISA bus. */
510
511static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
512			      unsigned int *irq_type,
513			      unsigned int *translation)
514{
515	static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
516
517	*irq_level = intab[inb(INTDEF(base)) & 0x7];
518	*irq_type  = (inb(INTDEF(base)) & 0x8) >> 3;
519	*translation = inb(RESV1(base)) & 0x1;
520	outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
521}
522
523static int aha1740_biosparam(struct scsi_device *sdev,
524			     struct block_device *dev,
525			     sector_t capacity, int* ip)
526{
527	int size = capacity;
528	int extended = HOSTDATA(sdev->host)->translation;
529
530	DEB(printk("aha1740_biosparam\n"));
531	if (extended && (ip[2] > 1024))	{
532		ip[0] = 255;
533		ip[1] = 63;
534		ip[2] = size / (255 * 63);
535	} else {
536		ip[0] = 64;
537		ip[1] = 32;
538		ip[2] = size >> 11;
539	}
540	return 0;
541}
542
543static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy)
544{
545/*
546 * From Alan Cox :
547 * The AHA1740 has firmware handled abort/reset handling. The "head in
548 * sand" kernel code is correct for once 8)
549 *
550 * So we define a dummy handler just to keep the kernel SCSI code as
551 * quiet as possible...
552 */
553
554	return 0;
555}
556
557static struct scsi_host_template aha1740_template = {
558	.module           = THIS_MODULE,
559	.proc_name        = "aha1740",
560	.proc_info        = aha1740_proc_info,
561	.name             = "Adaptec 174x (EISA)",
562	.queuecommand     = aha1740_queuecommand,
563	.bios_param       = aha1740_biosparam,
564	.can_queue        = AHA1740_ECBS,
565	.this_id          = 7,
566	.sg_tablesize     = AHA1740_SCATTER,
567	.cmd_per_lun      = AHA1740_CMDLUN,
568	.use_clustering   = ENABLE_CLUSTERING,
569	.eh_abort_handler = aha1740_eh_abort_handler,
570};
571
572static int aha1740_probe (struct device *dev)
573{
574	int slotbase, rc;
575	unsigned int irq_level, irq_type, translation;
576	struct Scsi_Host *shpnt;
577	struct aha1740_hostdata *host;
578	struct eisa_device *edev = to_eisa_device (dev);
579
580	DEB(printk("aha1740_probe: \n"));
581	
582	slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
583	if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
584		return -EBUSY;
585	if (!aha1740_test_port(slotbase))
586		goto err_release_region;
587	aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
588	if ((inb(G2STAT(slotbase)) &
589	     (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
590		/* If the card isn't ready, hard reset it */
591		outb(G2CNTRL_HRST, G2CNTRL(slotbase));
592		outb(0, G2CNTRL(slotbase));
593	}
594	printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
595	       edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
596	printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
597	       translation ? "en" : "dis");
598	shpnt = scsi_host_alloc(&aha1740_template,
599			      sizeof(struct aha1740_hostdata));
600	if(shpnt == NULL)
601		goto err_release_region;
602
603	shpnt->base = 0;
604	shpnt->io_port = slotbase;
605	shpnt->n_io_port = SLOTSIZE;
606	shpnt->irq = irq_level;
607	shpnt->dma_channel = 0xff;
608	host = HOSTDATA(shpnt);
609	host->edev = edev;
610	host->translation = translation;
611	host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
612					     sizeof (host->ecb),
613					     DMA_BIDIRECTIONAL);
614	if (!host->ecb_dma_addr) {
615		printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
616		scsi_unregister (shpnt);
617		goto err_host_put;
618	}
619	
620	DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
621	if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
622			"aha1740",shpnt)) {
623		printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
624		       irq_level);
625		goto err_unmap;
626	}
627
628	eisa_set_drvdata (edev, shpnt);
629
630	rc = scsi_add_host (shpnt, dev);
631	if (rc)
632		goto err_irq;
633
634	scsi_scan_host (shpnt);
635	return 0;
636
637 err_irq:
638 	free_irq(irq_level, shpnt);
639 err_unmap:
640	dma_unmap_single (&edev->dev, host->ecb_dma_addr,
641			  sizeof (host->ecb), DMA_BIDIRECTIONAL);
642 err_host_put:
643	scsi_host_put (shpnt);
644 err_release_region:
645	release_region(slotbase, SLOTSIZE);
646
647	return -ENODEV;
648}
649
650static __devexit int aha1740_remove (struct device *dev)
651{
652	struct Scsi_Host *shpnt = dev_get_drvdata(dev);
653	struct aha1740_hostdata *host = HOSTDATA (shpnt);
654
655	scsi_remove_host(shpnt);
656	
657	free_irq (shpnt->irq, shpnt);
658	dma_unmap_single (dev, host->ecb_dma_addr,
659			  sizeof (host->ecb), DMA_BIDIRECTIONAL);
660	release_region (shpnt->io_port, SLOTSIZE);
661
662	scsi_host_put (shpnt);
663	
664	return 0;
665}
666
667static struct eisa_device_id aha1740_ids[] = {
668	{ "ADP0000" },		/* 1740  */
669	{ "ADP0001" },		/* 1740A */
670	{ "ADP0002" },		/* 1742A */
671	{ "ADP0400" },		/* 1744  */
672	{ "" }
673};
674MODULE_DEVICE_TABLE(eisa, aha1740_ids);
675
676static struct eisa_driver aha1740_driver = {
677	.id_table = aha1740_ids,
678	.driver   = {
679		.name    = "aha1740",
680		.probe   = aha1740_probe,
681		.remove  = __devexit_p (aha1740_remove),
682	},
683};
684
685static __init int aha1740_init (void)
686{
687	return eisa_driver_register (&aha1740_driver);
688}
689
690static __exit void aha1740_exit (void)
691{
692	eisa_driver_unregister (&aha1740_driver);
693}
694
695module_init (aha1740_init);
696module_exit (aha1740_exit);
697
 
698MODULE_LICENSE("GPL");
v6.13.7
  1/*  $Id$
  2 *  1993/03/31
  3 *  linux/kernel/aha1740.c
  4 *
  5 *  Based loosely on aha1542.c which is
  6 *  Copyright (C) 1992  Tommy Thorn and
  7 *  Modified by Eric Youngdale
  8 *
  9 *  This file is aha1740.c, written and
 10 *  Copyright (C) 1992,1993  Brad McLean
 11 *  brad@saturn.gaylord.com or brad@bradpc.gaylord.com.
 12 *  
 13 *  Modifications to makecode and queuecommand
 14 *  for proper handling of multiple devices courteously
 15 *  provided by Michael Weller, March, 1993
 16 *
 17 *  Multiple adapter support, extended translation detection,
 18 *  update to current scsi subsystem changes, proc fs support,
 19 *  working (!) module support based on patches from Andreas Arens,
 20 *  by Andreas Degert <ad@papyrus.hamburg.com>, 2/1997
 21 *
 22 * aha1740_makecode may still need even more work
 23 * if it doesn't work for your devices, take a look.
 24 *
 25 * Reworked for new_eh and new locking by Alan Cox <alan@lxorguk.ukuu.org.uk>
 26 *
 27 * Converted to EISA and generic DMA APIs by Marc Zyngier
 28 * <maz@wild-wind.fr.eu.org>, 4/2003.
 29 *
 30 * Shared interrupt support added by Rask Ingemann Lambertsen
 31 * <rask@sygehus.dk>, 10/2003
 32 *
 33 * For the avoidance of doubt the "preferred form" of this code is one which
 34 * is in an open non patent encumbered format. Where cryptographic key signing
 35 * forms part of the process of creating an executable the information
 36 * including keys needed to generate an equivalently functional executable
 37 * are deemed to be part of the source code.
 38 */
 39
 40#include <linux/blkdev.h>
 41#include <linux/interrupt.h>
 42#include <linux/module.h>
 43#include <linux/kernel.h>
 44#include <linux/types.h>
 45#include <linux/string.h>
 46#include <linux/ioport.h>
 47#include <linux/proc_fs.h>
 48#include <linux/stat.h>
 49#include <linux/init.h>
 50#include <linux/device.h>
 51#include <linux/eisa.h>
 52#include <linux/dma-mapping.h>
 53#include <linux/gfp.h>
 54
 55#include <asm/dma.h>
 
 56#include <asm/io.h>
 57
 58#include <scsi/scsi.h>
 59#include <scsi/scsi_cmnd.h>
 60#include <scsi/scsi_device.h>
 61#include <scsi/scsi_eh.h>
 62#include <scsi/scsi_host.h>
 63#include <scsi/scsi_tcq.h>
 64#include "aha1740.h"
 65
 66/* IF YOU ARE HAVING PROBLEMS WITH THIS DRIVER, AND WANT TO WATCH
 67   IT WORK, THEN:
 68#define DEBUG
 69*/
 70#ifdef DEBUG
 71#define DEB(x) x
 72#else
 73#define DEB(x)
 74#endif
 75
 76struct aha1740_hostdata {
 77	struct eisa_device *edev;
 78	unsigned int translation;
 79	unsigned int last_ecb_used;
 80	dma_addr_t ecb_dma_addr;
 81	struct ecb ecb[AHA1740_ECBS];
 82};
 83
 84struct aha1740_sg {
 85	struct aha1740_chain sg_chain[AHA1740_SCATTER];
 86	dma_addr_t sg_dma_addr;
 87	dma_addr_t buf_dma_addr;
 88};
 89
 90#define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata)
 91
 92static inline struct ecb *ecb_dma_to_cpu (struct Scsi_Host *host,
 93					  dma_addr_t dma)
 94{
 95	struct aha1740_hostdata *hdata = HOSTDATA (host);
 96	dma_addr_t offset;
 97
 98	offset = dma - hdata->ecb_dma_addr;
 99
100	return (struct ecb *)(((char *) hdata->ecb) + (unsigned int) offset);
101}
102
103static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu)
104{
105	struct aha1740_hostdata *hdata = HOSTDATA (host);
106	dma_addr_t offset;
107    
108	offset = (char *) cpu - (char *) hdata->ecb;
109
110	return hdata->ecb_dma_addr + offset;
111}
112
113static int aha1740_show_info(struct seq_file *m, struct Scsi_Host *shpnt)
 
 
114{
115	struct aha1740_hostdata *host = HOSTDATA(shpnt);
116	seq_printf(m, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n"
 
 
 
 
 
 
 
117		      "Extended translation %sabled.\n",
118		      shpnt->io_port, shpnt->irq, host->edev->slot,
119		      host->translation ? "en" : "dis");
120	return 0;
 
 
 
 
 
 
 
 
 
 
121}
122
123static int aha1740_makecode(unchar *sense, unchar *status)
124{
125	struct statusword
126	{
127		ushort	don:1,	/* Command Done - No Error */
128			du:1,	/* Data underrun */
129		    :1,	qf:1,	/* Queue full */
130		        sc:1,	/* Specification Check */
131		        dor:1,	/* Data overrun */
132		        ch:1,	/* Chaining Halted */
133		        intr:1,	/* Interrupt issued */
134		        asa:1,	/* Additional Status Available */
135		        sns:1,	/* Sense information Stored */
136		    :1,	ini:1,	/* Initialization Required */
137			me:1,	/* Major error or exception */
138		    :1,	eca:1,  /* Extended Contingent alliance */
139		    :1;
140	} status_word;
141	int retval = DID_OK;
142
143	status_word = * (struct statusword *) status;
144#ifdef DEBUG
145	printk("makecode from %x,%x,%x,%x %x,%x,%x,%x",
146	       status[0], status[1], status[2], status[3],
147	       sense[0], sense[1], sense[2], sense[3]);
148#endif
149	if (!status_word.don) { /* Anything abnormal was detected */
150		if ( (status[1]&0x18) || status_word.sc ) {
151			/*Additional info available*/
152			/* Use the supplied info for further diagnostics */
153			switch ( status[2] ) {
154			case 0x12:
155				if ( status_word.dor )
156					retval=DID_ERROR; /* It's an Overrun */
157				/* If not overrun, assume underrun and
158				 * ignore it! */
159				break;
160			case 0x00: /* No info, assume no error, should
161				    * not occur */
162				break;
163			case 0x11:
164			case 0x21:
165				retval=DID_TIME_OUT;
166				break;
167			case 0x0a:
168				retval=DID_BAD_TARGET;
169				break;
170			case 0x04:
171			case 0x05:
172				retval=DID_ABORT;
173				/* Either by this driver or the
174				 * AHA1740 itself */
175				break;
176			default:
177				retval=DID_ERROR; /* No further
178						   * diagnostics
179						   * possible */
180			}
181		} else {
182			/* Michael suggests, and Brad concurs: */
183			if ( status_word.qf ) {
184				retval = DID_TIME_OUT; /* forces a redo */
185				/* I think this specific one should
186				 * not happen -Brad */
187				printk("aha1740.c: WARNING: AHA1740 queue overflow!\n");
188			} else
189				if ( status[0]&0x60 ) {
190					 /* Didn't find a better error */
191					retval = DID_ERROR;
192				}
193			/* In any other case return DID_OK so for example
194			   CONDITION_CHECKS make it through to the appropriate
195			   device driver */
196		}
197	}
198	/* Under all circumstances supply the target status -Michael */
199	return status[3] | retval << 16;
200}
201
202static int aha1740_test_port(unsigned int base)
203{
204	if ( inb(PORTADR(base)) & PORTADDR_ENH )
205		return 1;   /* Okay, we're all set */
206	
207	printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n");
208	return 0;
209}
210
211/* A "high" level interrupt handler */
212static irqreturn_t aha1740_intr_handle(int irq, void *dev_id)
213{
214	struct Scsi_Host *host = (struct Scsi_Host *) dev_id;
215        void (*my_done)(struct scsi_cmnd *);
216	int errstatus, adapstat;
217	int number_serviced;
218	struct ecb *ecbptr;
219	struct scsi_cmnd *SCtmp;
220	unsigned int base;
221	unsigned long flags;
222	int handled = 0;
223	struct aha1740_sg *sgptr;
224	struct eisa_device *edev;
225	
226	if (!host)
227		panic("aha1740.c: Irq from unknown host!\n");
228	spin_lock_irqsave(host->host_lock, flags);
229	base = host->io_port;
230	number_serviced = 0;
231	edev = HOSTDATA(host)->edev;
232
233	while(inb(G2STAT(base)) & G2STAT_INTPEND) {
234		handled = 1;
235		DEB(printk("aha1740_intr top of loop.\n"));
236		adapstat = inb(G2INTST(base));
237		ecbptr = ecb_dma_to_cpu (host, inl(MBOXIN0(base)));
238		outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */
239      
240		switch ( adapstat & G2INTST_MASK ) {
241		case	G2INTST_CCBRETRY:
242		case	G2INTST_CCBERROR:
243		case	G2INTST_CCBGOOD:
244			/* Host Ready -> Mailbox in complete */
245			outb(G2CNTRL_HRDY,G2CNTRL(base));
246			if (!ecbptr) {
247				printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n",
248				       inb(G2STAT(base)),adapstat,
249				       inb(G2INTST(base)), number_serviced++);
250				continue;
251			}
252			SCtmp = ecbptr->SCpnt;
253			if (!SCtmp) {
254				printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n",
255				       inb(G2STAT(base)),adapstat,
256				       inb(G2INTST(base)), number_serviced++);
257				continue;
258			}
259			sgptr = (struct aha1740_sg *) SCtmp->host_scribble;
260			scsi_dma_unmap(SCtmp);
261
262			/* Free the sg block */
263			dma_free_coherent (&edev->dev,
264					   sizeof (struct aha1740_sg),
265					   SCtmp->host_scribble,
266					   sgptr->sg_dma_addr);
267	    
268			/* Fetch the sense data, and tuck it away, in
269			   the required slot.  The Adaptec
270			   automatically fetches it, and there is no
271			   guarantee that we will still have it in the
272			   cdb when we come back */
273			if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) {
274				memcpy_and_pad(SCtmp->sense_buffer,
275					       SCSI_SENSE_BUFFERSIZE,
276					       ecbptr->sense,
277					       sizeof(ecbptr->sense),
278					       0);
279				errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status);
280			} else
281				errstatus = 0;
282			DEB(if (errstatus)
283			    printk("aha1740_intr_handle: returning %6x\n",
284				   errstatus));
285			SCtmp->result = errstatus;
286			my_done = ecbptr->done;
287			memset(ecbptr,0,sizeof(struct ecb)); 
288			if ( my_done )
289				my_done(SCtmp);
290			break;
291			
292		case	G2INTST_HARDFAIL:
293			printk(KERN_ALERT "aha1740 hardware failure!\n");
294			panic("aha1740.c");	/* Goodbye */
295			
296		case	G2INTST_ASNEVENT:
297			printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n",
298			       adapstat,
299			       inb(MBOXIN0(base)),
300			       inb(MBOXIN1(base)),
301			       inb(MBOXIN2(base)),
302			       inb(MBOXIN3(base))); /* Say What? */
303			/* Host Ready -> Mailbox in complete */
304			outb(G2CNTRL_HRDY,G2CNTRL(base));
305			break;
306			
307		case	G2INTST_CMDGOOD:
308			/* set immediate command success flag here: */
309			break;
310			
311		case	G2INTST_CMDERROR:
312			/* Set immediate command failure flag here: */
313			break;
314		}
315		number_serviced++;
316	}
317
318	spin_unlock_irqrestore(host->host_lock, flags);
319	return IRQ_RETVAL(handled);
320}
321
322static int aha1740_queuecommand_lck(struct scsi_cmnd *SCpnt)
323{
324	void (*done)(struct scsi_cmnd *) = scsi_done;
325	unchar direction;
326	unchar *cmd = (unchar *) SCpnt->cmnd;
327	unchar target = scmd_id(SCpnt);
328	struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host);
329	unsigned long flags;
330	dma_addr_t sg_dma;
331	struct aha1740_sg *sgptr;
332	int ecbno, nseg;
333	DEB(int i);
334
335	if(*cmd == REQUEST_SENSE) {
336		SCpnt->result = 0;
337		done(SCpnt); 
338		return 0;
339	}
340
341#ifdef DEBUG
342	if (*cmd == READ_10 || *cmd == WRITE_10)
343		i = xscsi2int(cmd+2);
344	else if (*cmd == READ_6 || *cmd == WRITE_6)
345		i = scsi2int(cmd+2);
346	else
347		i = -1;
348	printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",
349	       target, *cmd, i, bufflen);
350	printk("scsi cmd:");
351	for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);
352	printk("\n");
353#endif
354
355	/* locate an available ecb */
356	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
357	ecbno = host->last_ecb_used + 1; /* An optimization */
358	if (ecbno >= AHA1740_ECBS)
359		ecbno = 0;
360	do {
361		if (!host->ecb[ecbno].cmdw)
362			break;
363		ecbno++;
364		if (ecbno >= AHA1740_ECBS)
365			ecbno = 0;
366	} while (ecbno != host->last_ecb_used);
367
368	if (host->ecb[ecbno].cmdw)
369		panic("Unable to find empty ecb for aha1740.\n");
370
371	host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command
372						    doubles as reserved flag */
373
374	host->last_ecb_used = ecbno;    
375	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
376
377#ifdef DEBUG
378	printk("Sending command (%d %x)...", ecbno, done);
379#endif
380
381	host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command
382						   * Descriptor Block
383						   * Length */
384
385	direction = 0;
386	if (*cmd == READ_10 || *cmd == READ_6)
387		direction = 1;
388	else if (*cmd == WRITE_10 || *cmd == WRITE_6)
389		direction = 0;
390
391	memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);
392
393	SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,
394						   sizeof (struct aha1740_sg),
395						   &sg_dma, GFP_ATOMIC);
396	if(SCpnt->host_scribble == NULL) {
397		printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");
398		return 1;
399	}
400	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;
401	sgptr->sg_dma_addr = sg_dma;
402
403	nseg = scsi_dma_map(SCpnt);
404	BUG_ON(nseg < 0);
405	if (nseg) {
406		struct scatterlist *sg;
407		struct aha1740_chain * cptr;
408		int i;
409		DEB(unsigned char * ptr);
410
411		host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command
412					   * w/scatter-gather*/
413		cptr = sgptr->sg_chain;
414		scsi_for_each_sg(SCpnt, sg, nseg, i) {
415			cptr[i].datalen = sg_dma_len (sg);
416			cptr[i].dataptr = sg_dma_address (sg);
417		}
418		host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);
419		host->ecb[ecbno].dataptr = sg_dma;
420#ifdef DEBUG
421		printk("cptr %x: ",cptr);
422		ptr = (unsigned char *) cptr;
423		for(i=0;i<24;i++) printk("%02x ", ptr[i]);
424#endif
425	} else {
426		host->ecb[ecbno].datalen = 0;
427		host->ecb[ecbno].dataptr = 0;
428	}
429	host->ecb[ecbno].lun = SCpnt->device->lun;
430	host->ecb[ecbno].ses = 1; /* Suppress underrun errors */
431	host->ecb[ecbno].dir = direction;
432	host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */
433	host->ecb[ecbno].senselen = 12;
434	host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,
435						    host->ecb[ecbno].sense);
436	host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,
437						     host->ecb[ecbno].status);
438	host->ecb[ecbno].done = done;
439	host->ecb[ecbno].SCpnt = SCpnt;
440#ifdef DEBUG
441	{
442		int i;
443		printk("aha1740_command: sending.. ");
444		for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)
445			printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);
446	}
447	printk("\n");
448#endif
449	if (done) {
450	/* The Adaptec Spec says the card is so fast that the loops
451           will only be executed once in the code below. Even if this
452           was true with the fastest processors when the spec was
453           written, it doesn't seem to be true with today's fast
454           processors. We print a warning if the code is executed more
455           often than LOOPCNT_WARN. If this happens, it should be
456           investigated. If the count reaches LOOPCNT_MAX, we assume
457           something is broken; since there is no way to return an
458           error (the return value is ignored by the mid-level scsi
459           layer) we have to panic (and maybe that's the best thing we
460           can do then anyhow). */
461
462#define LOOPCNT_WARN 10		/* excessive mbxout wait -> syslog-msg */
463#define LOOPCNT_MAX 1000000	/* mbxout deadlock -> panic() after ~ 2 sec. */
464		int loopcnt;
465		unsigned int base = SCpnt->device->host->io_port;
466		DEB(printk("aha1740[%d] critical section\n",ecbno));
467
468		spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
469		for (loopcnt = 0; ; loopcnt++) {
470			if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;
471			if (loopcnt == LOOPCNT_WARN) {
472				printk("aha1740[%d]_mbxout wait!\n",ecbno);
473			}
474			if (loopcnt == LOOPCNT_MAX)
475				panic("aha1740.c: mbxout busy!\n");
476		}
477		outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),
478		      MBOXOUT0(base));
479		for (loopcnt = 0; ; loopcnt++) {
480			if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;
481			if (loopcnt == LOOPCNT_WARN) {
482				printk("aha1740[%d]_attn wait!\n",ecbno);
483			}
484			if (loopcnt == LOOPCNT_MAX)
485				panic("aha1740.c: attn wait failed!\n");
486		}
487		outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */
488		spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
489		DEB(printk("aha1740[%d] request queued.\n",ecbno));
490	} else
491		printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");
492	return 0;
493}
494
495static DEF_SCSI_QCMD(aha1740_queuecommand)
496
497/* Query the board for its irq_level and irq_type.  Nothing else matters
498   in enhanced mode on an EISA bus. */
499
500static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,
501			      unsigned int *irq_type,
502			      unsigned int *translation)
503{
504	static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };
505
506	*irq_level = intab[inb(INTDEF(base)) & 0x7];
507	*irq_type  = (inb(INTDEF(base)) & 0x8) >> 3;
508	*translation = inb(RESV1(base)) & 0x1;
509	outb(inb(INTDEF(base)) | 0x10, INTDEF(base));
510}
511
512static int aha1740_biosparam(struct scsi_device *sdev,
513			     struct block_device *dev,
514			     sector_t capacity, int* ip)
515{
516	int size = capacity;
517	int extended = HOSTDATA(sdev->host)->translation;
518
519	DEB(printk("aha1740_biosparam\n"));
520	if (extended && (ip[2] > 1024))	{
521		ip[0] = 255;
522		ip[1] = 63;
523		ip[2] = size / (255 * 63);
524	} else {
525		ip[0] = 64;
526		ip[1] = 32;
527		ip[2] = size >> 11;
528	}
529	return 0;
530}
531
532static int aha1740_eh_abort_handler (struct scsi_cmnd *dummy)
533{
534/*
535 * From Alan Cox :
536 * The AHA1740 has firmware handled abort/reset handling. The "head in
537 * sand" kernel code is correct for once 8)
538 *
539 * So we define a dummy handler just to keep the kernel SCSI code as
540 * quiet as possible...
541 */
542
543	return SUCCESS;
544}
545
546static const struct scsi_host_template aha1740_template = {
547	.module           = THIS_MODULE,
548	.proc_name        = "aha1740",
549	.show_info        = aha1740_show_info,
550	.name             = "Adaptec 174x (EISA)",
551	.queuecommand     = aha1740_queuecommand,
552	.bios_param       = aha1740_biosparam,
553	.can_queue        = AHA1740_ECBS,
554	.this_id          = 7,
555	.sg_tablesize     = AHA1740_SCATTER,
 
 
556	.eh_abort_handler = aha1740_eh_abort_handler,
557};
558
559static int aha1740_probe (struct device *dev)
560{
561	int slotbase, rc;
562	unsigned int irq_level, irq_type, translation;
563	struct Scsi_Host *shpnt;
564	struct aha1740_hostdata *host;
565	struct eisa_device *edev = to_eisa_device (dev);
566
567	DEB(printk("aha1740_probe: \n"));
568	
569	slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;
570	if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */
571		return -EBUSY;
572	if (!aha1740_test_port(slotbase))
573		goto err_release_region;
574	aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);
575	if ((inb(G2STAT(slotbase)) &
576	     (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {
577		/* If the card isn't ready, hard reset it */
578		outb(G2CNTRL_HRST, G2CNTRL(slotbase));
579		outb(0, G2CNTRL(slotbase));
580	}
581	printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",
582	       edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");
583	printk(KERN_INFO "aha174x: Extended translation %sabled.\n",
584	       translation ? "en" : "dis");
585	shpnt = scsi_host_alloc(&aha1740_template,
586			      sizeof(struct aha1740_hostdata));
587	if(shpnt == NULL)
588		goto err_release_region;
589
590	shpnt->base = 0;
591	shpnt->io_port = slotbase;
592	shpnt->n_io_port = SLOTSIZE;
593	shpnt->irq = irq_level;
594	shpnt->dma_channel = 0xff;
595	host = HOSTDATA(shpnt);
596	host->edev = edev;
597	host->translation = translation;
598	host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,
599					     sizeof (host->ecb),
600					     DMA_BIDIRECTIONAL);
601	if (!host->ecb_dma_addr) {
602		printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");
 
603		goto err_host_put;
604	}
605	
606	DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));
607	if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,
608			"aha1740",shpnt)) {
609		printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",
610		       irq_level);
611		goto err_unmap;
612	}
613
614	eisa_set_drvdata (edev, shpnt);
615
616	rc = scsi_add_host (shpnt, dev);
617	if (rc)
618		goto err_irq;
619
620	scsi_scan_host (shpnt);
621	return 0;
622
623 err_irq:
624 	free_irq(irq_level, shpnt);
625 err_unmap:
626	dma_unmap_single (&edev->dev, host->ecb_dma_addr,
627			  sizeof (host->ecb), DMA_BIDIRECTIONAL);
628 err_host_put:
629	scsi_host_put (shpnt);
630 err_release_region:
631	release_region(slotbase, SLOTSIZE);
632
633	return -ENODEV;
634}
635
636static int aha1740_remove (struct device *dev)
637{
638	struct Scsi_Host *shpnt = dev_get_drvdata(dev);
639	struct aha1740_hostdata *host = HOSTDATA (shpnt);
640
641	scsi_remove_host(shpnt);
642	
643	free_irq (shpnt->irq, shpnt);
644	dma_unmap_single (dev, host->ecb_dma_addr,
645			  sizeof (host->ecb), DMA_BIDIRECTIONAL);
646	release_region (shpnt->io_port, SLOTSIZE);
647
648	scsi_host_put (shpnt);
649	
650	return 0;
651}
652
653static struct eisa_device_id aha1740_ids[] = {
654	{ "ADP0000" },		/* 1740  */
655	{ "ADP0001" },		/* 1740A */
656	{ "ADP0002" },		/* 1742A */
657	{ "ADP0400" },		/* 1744  */
658	{ "" }
659};
660MODULE_DEVICE_TABLE(eisa, aha1740_ids);
661
662static struct eisa_driver aha1740_driver = {
663	.id_table = aha1740_ids,
664	.driver   = {
665		.name    = "aha1740",
666		.probe   = aha1740_probe,
667		.remove  = aha1740_remove,
668	},
669};
670
671static __init int aha1740_init (void)
672{
673	return eisa_driver_register (&aha1740_driver);
674}
675
676static __exit void aha1740_exit (void)
677{
678	eisa_driver_unregister (&aha1740_driver);
679}
680
681module_init (aha1740_init);
682module_exit (aha1740_exit);
683
684MODULE_DESCRIPTION("Adaptec AHA1740 SCSI host adapter driver");
685MODULE_LICENSE("GPL");