File: /usr/src/linux/drivers/scsi/sym53c416.c

1     /* 
2      *  sym53c416.c
3      *  Low-level SCSI driver for sym53c416 chip.
4      *  Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com)
5      * 
6      *  Changes : 
7      * 
8      *  Marcelo Tosatti <marcelo@conectiva.com.br> : Added io_request_lock locking
9      *  Alan Cox <alan@redhat.com> : Cleaned up code formatting
10      *				 Fixed an irq locking bug
11      *				 Added ISAPnP support
12      * 
13      *  LILO command line usage: sym53c416=<PORTBASE>[,<IRQ>]
14      *
15      *  This program is free software; you can redistribute it and/or modify it
16      *  under the terms of the GNU General Public License as published by the
17      *  Free Software Foundation; either version 2, or (at your option) any
18      *  later version.
19      *
20      *  This program is distributed in the hope that it will be useful, but
21      *  WITHOUT ANY WARRANTY; without even the implied warranty of
22      *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23      *  General Public License for more details.
24      *
25      */
26     
27     #include <linux/module.h>
28     #include <linux/kernel.h>
29     #include <linux/types.h>
30     #include <linux/string.h>
31     #include <linux/ioport.h>
32     #include <linux/sched.h>
33     #include <linux/interrupt.h>
34     #include <linux/delay.h>
35     #include <linux/proc_fs.h>
36     #include <linux/spinlock.h>
37     #include <asm/dma.h>
38     #include <asm/system.h>
39     #include <asm/io.h>
40     #include <linux/blk.h>
41     #include <linux/version.h>
42     #include <linux/isapnp.h>
43     #include "scsi.h"
44     #include "hosts.h"
45     #include "sd.h"
46     #include "sym53c416.h"
47     
48     #define VERSION_STRING        "Version 1.0.0-ac"
49     
50     #define TC_LOW       0x00     /* Transfer counter low        */
51     #define TC_MID       0x01     /* Transfer counter mid        */
52     #define SCSI_FIFO    0x02     /* SCSI FIFO register          */
53     #define COMMAND_REG  0x03     /* Command Register            */
54     #define STATUS_REG   0x04     /* Status Register (READ)      */
55     #define DEST_BUS_ID  0x04     /* Destination Bus ID (WRITE)  */
56     #define INT_REG      0x05     /* Interrupt Register (READ)   */
57     #define TOM          0x05     /* Time out multiplier (WRITE) */
58     #define STP          0x06     /* Synchronous Transfer period */
59     #define SYNC_OFFSET  0x07     /* Synchronous Offset          */
60     #define CONF_REG_1   0x08     /* Configuration register 1    */
61     #define CONF_REG_2   0x0B     /* Configuration register 2    */
62     #define CONF_REG_3   0x0C     /* Configuration register 3    */
63     #define CONF_REG_4   0x0D     /* Configuration register 4    */
64     #define TC_HIGH      0x0E     /* Transfer counter high       */
65     #define PIO_FIFO_1   0x10     /* PIO FIFO register 1         */
66     #define PIO_FIFO_2   0x11     /* PIO FIFO register 2         */
67     #define PIO_FIFO_3   0x12     /* PIO FIFO register 3         */
68     #define PIO_FIFO_4   0x13     /* PIO FIFO register 4         */
69     #define PIO_FIFO_CNT 0x14     /* PIO FIFO count              */
70     #define PIO_INT_REG  0x15     /* PIO interrupt register      */
71     #define CONF_REG_5   0x16     /* Configuration register 5    */
72     #define FEATURE_EN   0x1D     /* Feature Enable register     */
73     
74     /* Configuration register 1 entries: */
75     /* Bits 2-0: SCSI ID of host adapter */
76     #define SCM    0x80                     /* Slow Cable Mode              */
77     #define SRID   0x40                     /* SCSI Reset Interrupt Disable */
78     #define PTM    0x20                     /* Parity Test Mode             */
79     #define EPC    0x10                     /* Enable Parity Checking       */
80     #define CTME   0x08                     /* Special Test Mode            */
81     
82     /* Configuration register 2 entries: */
83     #define FE     0x40                     /* Features Enable              */
84     #define SCSI2  0x08                     /* SCSI 2 Enable                */
85     #define TBPA   0x04                     /* Target Bad Parity Abort      */
86     
87     /* Configuration register 3 entries: */
88     #define IDMRC  0x80                     /* ID Message Reserved Check    */
89     #define QTE    0x40                     /* Queue Tag Enable             */
90     #define CDB10  0x20                     /* Command Descriptor Block 10  */
91     #define FSCSI  0x10                     /* FastSCSI                     */
92     #define FCLK   0x08                     /* FastClock                    */
93     
94     /* Configuration register 4 entries: */
95     #define RBS    0x08                     /* Register bank select         */
96     #define EAN    0x04                     /* Enable Active Negotiation    */
97     
98     /* Configuration register 5 entries: */
99     #define LPSR   0x80                     /* Lower Power SCSI Reset       */
100     #define IE     0x20                     /* Interrupt Enable             */
101     #define LPM    0x02                     /* Low Power Mode               */
102     #define WSE0   0x01                     /* 0WS Enable                   */
103     
104     /* Interrupt register entries: */
105     #define SRST   0x80                     /* SCSI Reset                   */
106     #define ILCMD  0x40                     /* Illegal Command              */
107     #define DIS    0x20                     /* Disconnect                   */
108     #define BS     0x10                     /* Bus Service                  */
109     #define FC     0x08                     /* Function Complete            */
110     #define RESEL  0x04                     /* Reselected                   */
111     #define SI     0x03                     /* Selection Interrupt          */
112     
113     /* Status Register Entries: */
114     #define SCI    0x80                     /* SCSI Core Int                */
115     #define GE     0x40                     /* Gross Error                  */
116     #define PE     0x20                     /* Parity Error                 */
117     #define TC     0x10                     /* Terminal Count               */
118     #define VGC    0x08                     /* Valid Group Code             */
119     #define PHBITS 0x07                     /* Phase bits                   */
120     
121     /* PIO Interrupt Register Entries: */
122     #define SCI    0x80                     /* SCSI Core Int                */
123     #define PFI    0x40                     /* PIO FIFO Interrupt           */
124     #define FULL   0x20                     /* PIO FIFO Full                */
125     #define EMPTY  0x10                     /* PIO FIFO Empty               */
126     #define CE     0x08                     /* Collision Error              */
127     #define OUE    0x04                     /* Overflow / Underflow error   */
128     #define FIE    0x02                     /* Full Interrupt Enable        */
129     #define EIE    0x01                     /* Empty Interrupt Enable       */
130     
131     /* SYM53C416 SCSI phases (lower 3 bits of SYM53C416_STATUS_REG) */
132     #define PHASE_DATA_OUT    0x00
133     #define PHASE_DATA_IN     0x01
134     #define PHASE_COMMAND     0x02
135     #define PHASE_STATUS      0x03
136     #define PHASE_RESERVED_1  0x04
137     #define PHASE_RESERVED_2  0x05
138     #define PHASE_MESSAGE_OUT 0x06
139     #define PHASE_MESSAGE_IN  0x07
140     
141     /* SYM53C416 core commands */
142     #define NOOP                      0x00
143     #define FLUSH_FIFO                0x01
144     #define RESET_CHIP                0x02
145     #define RESET_SCSI_BUS            0x03
146     #define DISABLE_SEL_RESEL         0x45
147     #define RESEL_SEQ                 0x40
148     #define SEL_WITHOUT_ATN_SEQ       0x41
149     #define SEL_WITH_ATN_SEQ          0x42
150     #define SEL_WITH_ATN_AND_STOP_SEQ 0x43
151     #define ENABLE_SEL_RESEL          0x44
152     #define SEL_WITH_ATN3_SEQ         0x46
153     #define RESEL3_SEQ                0x47
154     #define SND_MSG                   0x20
155     #define SND_STAT                  0x21
156     #define SND_DATA                  0x22
157     #define DISCONNECT_SEQ            0x23
158     #define TERMINATE_SEQ             0x24
159     #define TARGET_COMM_COMPLETE_SEQ  0x25
160     #define DISCONN                   0x27
161     #define RECV_MSG_SEQ              0x28
162     #define RECV_CMD                  0x29
163     #define RECV_DATA                 0x2A
164     #define RECV_CMD_SEQ              0x2B
165     #define TARGET_ABORT_PIO          0x04
166     #define TRANSFER_INFORMATION      0x10
167     #define INIT_COMM_COMPLETE_SEQ    0x11
168     #define MSG_ACCEPTED              0x12
169     #define TRANSFER_PAD              0x18
170     #define SET_ATN                   0x1A
171     #define RESET_ATN                 0x1B
172     #define ILLEGAL                   0xFF
173     
174     #define PIO_MODE                  0x80
175     
176     #define IO_RANGE 0x20         /* 0x00 - 0x1F                   */
177     #define ID       "sym53c416"	/* Attention: copied to the sym53c416.h */
178     #define PIO_SIZE 128          /* Size of PIO fifo is 128 bytes */
179     
180     #define READ_TIMEOUT              150
181     #define WRITE_TIMEOUT             150
182     
183     #ifdef MODULE
184     
185     #define sym53c416_base sym53c416
186     #define sym53c416_base_1 sym53c416_1
187     #define sym53c416_base_2 sym53c416_2
188     #define sym53c416_base_3 sym53c416_3
189     
190     static unsigned int sym53c416_base[2] = {0,0};
191     static unsigned int sym53c416_base_1[2] = {0,0};
192     static unsigned int sym53c416_base_2[2] = {0,0};
193     static unsigned int sym53c416_base_3[2] = {0,0};
194     
195     #endif
196     
197     /* #define DEBUG */
198     
199     /* Macro for debugging purposes */
200     
201     #ifdef DEBUG
202     #define DEB(x) x
203     #else
204     #define DEB(x)
205     #endif
206     
207     #define MAXHOSTS 4
208     
209     enum phases
210     {
211     	idle,
212     	data_out,
213     	data_in,
214     	command_ph,
215     	status_ph,
216     	message_out,
217     	message_in
218     };
219     
220     typedef struct
221     {
222     	int base;
223     	int irq;
224     	int scsi_id;
225     } host;
226     
227     static host hosts[MAXHOSTS] = {
228                            {0, 0, SYM53C416_SCSI_ID},
229                            {0, 0, SYM53C416_SCSI_ID},
230                            {0, 0, SYM53C416_SCSI_ID},
231                            {0, 0, SYM53C416_SCSI_ID}
232                            };
233     
234     static int host_index = 0;
235     static char info[120];
236     static Scsi_Cmnd *current_command = NULL;
237     static int fastpio = 1;
238     
239     static int probeaddrs[] = {0x200, 0x220, 0x240, 0};
240     
241     static void sym53c416_set_transfer_counter(int base, unsigned int len)
242     {
243     	/* Program Transfer Counter */
244     	outb(len & 0x0000FF, base + TC_LOW);
245     	outb((len & 0x00FF00) >> 8, base + TC_MID);
246     	outb((len & 0xFF0000) >> 16, base + TC_HIGH);
247     }
248     
249     /* Returns the number of bytes read */
250     static __inline__ unsigned int sym53c416_read(int base, unsigned char *buffer, unsigned int len)
251     {
252     	unsigned int orig_len = len;
253     	unsigned long flags = 0;
254     	unsigned int bytes_left;
255     	int i;
256     	int timeout = READ_TIMEOUT;
257     
258     	/* Do transfer */
259     	save_flags(flags);
260     	cli();
261     	while(len && timeout)
262     	{
263     		bytes_left = inb(base + PIO_FIFO_CNT); /* Number of bytes in the PIO FIFO */
264     		if(fastpio && bytes_left > 3)
265     		{
266     			insl(base + PIO_FIFO_1, buffer, bytes_left >> 2);
267     			buffer += bytes_left & 0xFC;
268     			len -= bytes_left & 0xFC;
269     		}
270     		else if(bytes_left > 0)
271     		{
272     			len -= bytes_left;
273     			for(; bytes_left > 0; bytes_left--)
274     				*(buffer++) = inb(base + PIO_FIFO_1);
275     		}
276     		else
277     		{
278     			i = jiffies + timeout;
279     			restore_flags(flags);
280     			while(jiffies < i && (inb(base + PIO_INT_REG) & EMPTY) && timeout)
281     				if(inb(base + PIO_INT_REG) & SCI)
282     					timeout = 0;
283     			save_flags(flags);
284     			cli();
285     			if(inb(base + PIO_INT_REG) & EMPTY)
286     				timeout = 0;
287     		}
288     	}
289     	restore_flags(flags);
290     	return orig_len - len;
291     }
292     
293     /* Returns the number of bytes written */
294     static __inline__ unsigned int sym53c416_write(int base, unsigned char *buffer, unsigned int len)
295     {
296     	unsigned int orig_len = len;
297     	unsigned long flags = 0;
298     	unsigned int bufferfree;
299     	unsigned int i;
300     	unsigned int timeout = WRITE_TIMEOUT;
301     
302     	/* Do transfer */
303     	save_flags(flags);
304     	cli();
305     	while(len && timeout)
306     	{
307     		bufferfree = PIO_SIZE - inb(base + PIO_FIFO_CNT);
308     		if(bufferfree > len)
309     			bufferfree = len;
310     		if(fastpio && bufferfree > 3)
311     		{
312     			outsl(base + PIO_FIFO_1, buffer, bufferfree >> 2);
313     			buffer += bufferfree & 0xFC;
314     			len -= bufferfree & 0xFC;
315     		}
316     		else if(bufferfree > 0)
317     		{
318     			len -= bufferfree;
319     			for(; bufferfree > 0; bufferfree--)
320     				outb(*(buffer++), base + PIO_FIFO_1);
321     		}
322     		else
323     		{
324     			i = jiffies + timeout;
325     			restore_flags(flags);
326     			while(jiffies < i && (inb(base + PIO_INT_REG) & FULL) && timeout)
327     				;
328     			save_flags(flags);
329     			cli();
330     			if(inb(base + PIO_INT_REG) & FULL)
331     				timeout = 0;
332     		}
333     	}
334     	restore_flags(flags);
335     	return orig_len - len;
336     }
337     
338     static void sym53c416_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
339     {
340     	int base = 0;
341     	int i;
342     	unsigned long flags = 0;
343     	unsigned char status_reg, pio_int_reg, int_reg;
344     	struct scatterlist *sglist;
345     	unsigned int sgcount;
346     	unsigned int tot_trans = 0;
347     
348     	/* We search the base address of the host adapter which caused the interrupt */
349     	/* FIXME: should pass dev_id sensibly as hosts[i] */
350     	for(i = 0; i < host_index && !base; i++)
351     		if(irq == hosts[i].irq)
352     			base = hosts[i].base;
353     	/* If no adapter found, we cannot handle the interrupt. Leave a message */
354     	/* and continue. This should never happen...                            */
355     	if(!base)
356     	{
357     		printk(KERN_ERR "sym53c416: No host adapter defined for interrupt %d\n", irq);
358     		return;
359     	}
360     	/* Now we have the base address and we can start handling the interrupt */
361     
362     	spin_lock_irqsave(&io_request_lock,flags);
363     	status_reg = inb(base + STATUS_REG);
364     	pio_int_reg = inb(base + PIO_INT_REG);
365     	int_reg = inb(base + INT_REG);
366     	spin_unlock_irqrestore(&io_request_lock, flags);
367     
368     	/* First, we handle error conditions */
369     	if(int_reg & SCI)         /* SCSI Reset */
370     	{
371     		printk(KERN_DEBUG "sym53c416: Reset received\n");
372     		current_command->SCp.phase = idle;
373     		current_command->result = DID_RESET << 16;
374     		spin_lock_irqsave(&io_request_lock, flags);
375     		current_command->scsi_done(current_command);
376     		spin_unlock_irqrestore(&io_request_lock, flags);
377     		return;
378     	}
379     	if(int_reg & ILCMD)       /* Illegal Command */
380     	{
381     		printk(KERN_WARNING "sym53c416: Illegal Command: 0x%02x.\n", inb(base + COMMAND_REG));
382     		current_command->SCp.phase = idle;
383     		current_command->result = DID_ERROR << 16;
384     		spin_lock_irqsave(&io_request_lock, flags);
385     		current_command->scsi_done(current_command);
386     		spin_unlock_irqrestore(&io_request_lock, flags);
387     		return;
388     	}
389     	if(status_reg & GE)         /* Gross Error */
390     	{
391     		printk(KERN_WARNING "sym53c416: Controller reports gross error.\n");
392     		current_command->SCp.phase = idle;
393     		current_command->result = DID_ERROR << 16;
394     		spin_lock_irqsave(&io_request_lock, flags);
395     		current_command->scsi_done(current_command);
396     		spin_unlock_irqrestore(&io_request_lock, flags);
397     		return;
398     	}
399     	if(status_reg & PE)         /* Parity Error */
400     	{
401     		printk(KERN_WARNING "sym53c416:SCSI parity error.\n");
402     		current_command->SCp.phase = idle;
403     		current_command->result = DID_PARITY << 16;
404     		spin_lock_irqsave(&io_request_lock, flags);
405     		current_command->scsi_done(current_command);
406     		spin_unlock_irqrestore(&io_request_lock, flags);
407     		return;
408     	}
409     	if(pio_int_reg & (CE | OUE))
410     	{
411     		printk(KERN_WARNING "sym53c416: PIO interrupt error.\n");
412     		current_command->SCp.phase = idle;
413     		current_command->result = DID_ERROR << 16;
414     		spin_lock_irqsave(&io_request_lock, flags);
415     		current_command->scsi_done(current_command);
416     		spin_unlock_irqrestore(&io_request_lock, flags);
417     		return;
418     	}
419     	if(int_reg & DIS)           /* Disconnect */
420     	{
421     		if(current_command->SCp.phase != message_in)
422     			current_command->result = DID_NO_CONNECT << 16;
423     		else
424     			current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16);
425     		current_command->SCp.phase = idle;
426     		spin_lock_irqsave(&io_request_lock, flags);
427     		current_command->scsi_done(current_command);
428     		spin_unlock_irqrestore(&io_request_lock, flags);
429     		return;
430     	}
431     	/* Now we handle SCSI phases         */
432     
433     	switch(status_reg & PHBITS)       /* Filter SCSI phase out of status reg */
434     	{
435     		case PHASE_DATA_OUT:
436     		{
437     			if(int_reg & BS)
438     			{
439     				current_command->SCp.phase = data_out;
440     				outb(FLUSH_FIFO, base + COMMAND_REG);
441     				sym53c416_set_transfer_counter(base, current_command->request_bufflen);
442     				outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
443     				if(!current_command->use_sg)
444     					tot_trans = sym53c416_write(base, current_command->request_buffer, current_command->request_bufflen);
445     				else
446     				{
447     					sgcount = current_command->use_sg;
448     					sglist = current_command->request_buffer;
449     					while(sgcount--)
450     					{
451     						tot_trans += sym53c416_write(base, sglist->address, sglist->length);
452     						sglist++;
453     					}
454     				}
455     				if(tot_trans < current_command->underflow)
456     					printk(KERN_WARNING "sym53c416: Underflow, wrote %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
457     			}
458     			break;
459     		}
460     
461     		case PHASE_DATA_IN:
462     		{
463     			if(int_reg & BS)
464     			{
465     				current_command->SCp.phase = data_in;
466     				outb(FLUSH_FIFO, base + COMMAND_REG);
467     				sym53c416_set_transfer_counter(base, current_command->request_bufflen);
468     				outb(TRANSFER_INFORMATION | PIO_MODE, base + COMMAND_REG);
469     				if(!current_command->use_sg)
470     					tot_trans = sym53c416_read(base, current_command->request_buffer, current_command->request_bufflen);
471     				else
472     				{
473     					sgcount = current_command->use_sg;
474     					sglist = current_command->request_buffer;
475     					while(sgcount--)
476     					{
477     						tot_trans += sym53c416_read(base, sglist->address, sglist->length);
478     						sglist++;
479     					}
480     				}
481     				if(tot_trans < current_command->underflow)
482     					printk(KERN_WARNING "sym53c416: Underflow, read %d bytes, request for %d bytes.\n", tot_trans, current_command->underflow);
483     			}
484     			break;
485     		}
486     
487     		case PHASE_COMMAND:
488     		{
489     			current_command->SCp.phase = command_ph;
490     			printk(KERN_ERR "sym53c416: Unknown interrupt in command phase.\n");
491     			break;
492     		}
493     
494     		case PHASE_STATUS:
495     		{
496     			current_command->SCp.phase = status_ph;
497     			outb(FLUSH_FIFO, base + COMMAND_REG);
498     			outb(INIT_COMM_COMPLETE_SEQ, base + COMMAND_REG);
499     			break;
500     		}
501     		
502     		case PHASE_RESERVED_1:
503     		case PHASE_RESERVED_2:
504     		{
505     			printk(KERN_ERR "sym53c416: Reserved phase occurred.\n");
506     			break;
507     		}
508     
509     		case PHASE_MESSAGE_OUT:
510     		{
511     			current_command->SCp.phase = message_out;
512     			outb(SET_ATN, base + COMMAND_REG);
513     			outb(MSG_ACCEPTED, base + COMMAND_REG);
514     			break;
515     		}
516     
517     		case PHASE_MESSAGE_IN:
518     		{
519     			current_command->SCp.phase = message_in;
520     			current_command->SCp.Status = inb(base + SCSI_FIFO);
521     			current_command->SCp.Message = inb(base + SCSI_FIFO);
522     			if(current_command->SCp.Message == SAVE_POINTERS || current_command->SCp.Message == DISCONNECT)
523     				outb(SET_ATN, base + COMMAND_REG);
524     			outb(MSG_ACCEPTED, base + COMMAND_REG);
525     			break;
526     		}
527     	}
528     }
529     
530     static void sym53c416_init(int base, int scsi_id)
531     {
532     	outb(RESET_CHIP, base + COMMAND_REG);
533     	outb(NOOP, base + COMMAND_REG);
534     	outb(0x99, base + TOM); /* Time out of 250 ms */
535     	outb(0x05, base + STP);
536     	outb(0x00, base + SYNC_OFFSET);
537     	outb(EPC | scsi_id, base + CONF_REG_1);
538     	outb(FE | SCSI2 | TBPA, base + CONF_REG_2);
539     	outb(IDMRC | QTE | CDB10 | FSCSI | FCLK, base + CONF_REG_3);
540     	outb(0x83 | EAN, base + CONF_REG_4);
541     	outb(IE | WSE0, base + CONF_REG_5);
542     	outb(0, base + FEATURE_EN);
543     }
544     
545     static int sym53c416_probeirq(int base, int scsi_id)
546     {
547     	int irq, irqs, i;
548     
549     	/* Clear interrupt register */
550     	inb(base + INT_REG);
551     	/* Start probing for irq's */
552     	irqs = probe_irq_on();
553     	/* Reinit chip */
554     	sym53c416_init(base, scsi_id);
555     	/* Cause interrupt */
556     	outb(NOOP, base + COMMAND_REG);
557     	outb(ILLEGAL, base + COMMAND_REG);
558     	outb(0x07, base + DEST_BUS_ID);
559     	outb(0x00, base + DEST_BUS_ID);
560     	/* Wait for interrupt to occur */
561     	i = jiffies + 20;
562     	while(i > jiffies && !(inb(base + STATUS_REG) & SCI))
563     		barrier();
564     	if(i <= jiffies) /* timed out */
565     		return 0;
566     	/* Get occurred irq */
567     	irq = probe_irq_off(irqs);
568     	sym53c416_init(base, scsi_id);
569     	return irq;
570     }
571     
572     /* Setup: sym53c416=base,irq */
573     void sym53c416_setup(char *str, int *ints)
574     {
575     	int i;
576     
577     	if(host_index >= MAXHOSTS)
578     	{
579     		printk(KERN_WARNING "sym53c416: Too many hosts defined\n");
580     		return;
581     	}
582     	if(ints[0] < 1 || ints[0] > 2)
583     	{
584     		printk(KERN_ERR "sym53c416: Wrong number of parameters:\n");
585     		printk(KERN_ERR "sym53c416: usage: sym53c416=<base>[,<irq>]\n");
586     		return;
587     	}
588     	for(i = 0; i < host_index && i >= 0; i++)
589     	        if(hosts[i].base == ints[1])
590             		i = -2;
591     	if(i >= 0)
592     	{
593             	hosts[host_index].base = ints[1];
594             	hosts[host_index].irq = (ints[0] == 2)? ints[2] : 0;
595             	host_index++;
596     	}
597     }
598     
599     static int sym53c416_test(int base)
600     {
601     	outb(RESET_CHIP, base + COMMAND_REG);
602     	outb(NOOP, base + COMMAND_REG);
603     	if(inb(base + COMMAND_REG) != NOOP)
604     		return 0;
605     	if(!inb(base + TC_HIGH) || inb(base + TC_HIGH) == 0xFF)
606     		return 0;
607     	if((inb(base + PIO_INT_REG) & (FULL | EMPTY | CE | OUE | FIE | EIE)) != EMPTY)
608     		return 0;
609     	return 1;
610     }
611     
612     
613     static struct isapnp_device_id id_table[] = {
614     	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
615     		ISAPNP_VENDOR('S','L','I'), ISAPNP_FUNCTION(0x4163), 0 },
616     	{0}
617     };
618     
619     MODULE_DEVICE_TABLE(isapnp, id_table);
620     
621     void sym53c416_probe(void)
622     {
623     	int *base = probeaddrs;
624     	int ints[2];
625     
626     	ints[0] = 1;
627     	for(; *base; base++)
628     	{
629     		if(!check_region(*base, IO_RANGE) && sym53c416_test(*base))
630     		{
631     			ints[1] = *base;
632     			sym53c416_setup(NULL, ints);
633     		}
634     	}
635     }
636     
637     int sym53c416_detect(Scsi_Host_Template *tpnt)
638     {
639     	unsigned long flags;
640     	struct Scsi_Host * shpnt = NULL;
641     	int i;
642     	int count;
643     	struct pci_dev *idev = NULL;
644     	
645     #ifdef MODULE
646     	int ints[3];
647     
648     	ints[0] = 2;
649     	if(sym53c416_base)
650     	{
651     		ints[1] = sym53c416_base[0];
652     		ints[2] = sym53c416_base[1];
653     		sym53c416_setup(NULL, ints);
654     	}
655     	if(sym53c416_base_1)
656     	{
657     		ints[1] = sym53c416_base_1[0];
658     		ints[2] = sym53c416_base_1[1];
659     		sym53c416_setup(NULL, ints);
660     	}
661     	if(sym53c416_base_2)
662     	{
663     		ints[1] = sym53c416_base_2[0];
664     		ints[2] = sym53c416_base_2[1];
665     		sym53c416_setup(NULL, ints);
666     	}
667     	if(sym53c416_base_3)
668     	{
669     		ints[1] = sym53c416_base_3[0];
670     		ints[2] = sym53c416_base_3[1];
671     		sym53c416_setup(NULL, ints);
672     	}
673     #endif
674     	printk(KERN_INFO "sym53c416.c: %s\n", VERSION_STRING);
675     
676     	while((idev=isapnp_find_dev(NULL, ISAPNP_VENDOR('S','L','I'), 
677     				ISAPNP_FUNCTION(0x4163), idev))!=NULL)
678     	{
679     		int i[3];
680     		
681     		if(idev->prepare(idev)<0)
682     		{
683     			printk(KERN_WARNING "sym53c416: unable to prepare PnP card.\n");
684     			continue;
685     		}
686     		if(idev->activate(idev)<0)
687     		{
688     			printk(KERN_WARNING "sym53c416: unable to activate PnP card.\n");
689     			continue;
690     		}
691     		
692     		i[0] = 2;
693     		i[1] = idev->resource[0].start;
694     		i[2] = idev->irq_resource[0].start;
695     		
696     		printk(KERN_INFO "sym53c416: ISAPnP card found and configured at 0x%X, IRQ %d.\n",
697     			i[1], i[2]);
698     		sym53c416_setup(NULL, i);
699     	}
700     	sym53c416_probe();
701     
702     	/* Now we register and set up each host adapter found... */
703     	for(count = 0, i = 0; i < host_index; i++)
704     	{
705     		if(!sym53c416_test(hosts[i].base))
706     			printk(KERN_WARNING "No sym53c416 found at address 0x%03x\n", hosts[i].base);
707     		else
708     		{
709     			if(hosts[i].irq == 0)
710     			/* We don't have an irq yet, so we should probe for one */
711     				if((hosts[i].irq = sym53c416_probeirq(hosts[i].base, hosts[i].scsi_id)) == 0)
712     					printk(KERN_WARNING "IRQ autoprobing failed for sym53c416 at address 0x%03x\n", hosts[i].base);
713     			if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE))
714     			{
715     				shpnt = scsi_register(tpnt, 0);
716     				if(shpnt==NULL)
717     					continue;
718     				save_flags(flags);
719     				cli();
720     				/* FIXME: Request_irq with CLI is not safe */
721     				/* Request for specified IRQ */
722     				if(request_irq(hosts[i].irq, sym53c416_intr_handle, 0, ID, NULL))
723     				{
724     					restore_flags(flags);
725     					printk(KERN_ERR "sym53c416: Unable to assign IRQ %d\n", hosts[i].irq);
726     					scsi_unregister(shpnt);
727     				}
728     				else
729     				{
730     					/* Inform the kernel of our IO range */
731     					request_region(hosts[i].base, IO_RANGE, ID);
732     					shpnt->unique_id = hosts[i].base;
733     					shpnt->io_port = hosts[i].base;
734     					shpnt->n_io_port = IO_RANGE;
735     					shpnt->irq = hosts[i].irq;
736     					shpnt->this_id = hosts[i].scsi_id;
737     					sym53c416_init(hosts[i].base, hosts[i].scsi_id);
738     					count++;
739     					restore_flags(flags);
740     				}
741     			}
742     		}
743     	}
744     	return count;
745     }
746     
747     const char *sym53c416_info(struct Scsi_Host *SChost)
748     {
749     	int i;
750     	int base = SChost->io_port;
751     	int irq = SChost->irq;
752     	int scsi_id = 0;
753     	int rev = inb(base + TC_HIGH);
754     
755     	for(i = 0; i < host_index; i++)
756     		if(hosts[i].base == base)
757     			scsi_id = hosts[i].scsi_id;
758     	sprintf(info, "Symbios Logic 53c416 (rev. %d) at 0x%03x, irq %d, SCSI-ID %d, %s pio", rev, base, irq, scsi_id, (fastpio)? "fast" : "slow");
759     	return info;
760     }
761     
762     int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
763     {
764     	int base;
765     	unsigned long flags = 0;
766     	int i;
767     
768     	/* Store base register as we can have more than one controller in the system */
769     	base = SCpnt->host->io_port;
770     	current_command = SCpnt;                  /* set current command                */
771     	current_command->scsi_done = done;        /* set ptr to done function           */
772     	current_command->SCp.phase = command_ph;  /* currect phase is the command phase */
773     	current_command->SCp.Status = 0;
774     	current_command->SCp.Message = 0;
775     
776     	save_flags(flags);
777     	cli();
778     	outb(SCpnt->target, base + DEST_BUS_ID); /* Set scsi id target        */
779     	outb(FLUSH_FIFO, base + COMMAND_REG);    /* Flush SCSI and PIO FIFO's */
780     	/* Write SCSI command into the SCSI fifo */
781     	for(i = 0; i < SCpnt->cmd_len; i++)
782     		outb(SCpnt->cmnd[i], base + SCSI_FIFO);
783     	/* Start selection sequence */
784     	outb(SEL_WITHOUT_ATN_SEQ, base + COMMAND_REG);
785     	/* Now an interrupt will be generated which we will catch in out interrupt routine */
786     	restore_flags(flags);
787     	return 0;
788     }
789     
790     static void internal_done(Scsi_Cmnd *SCpnt)
791     {
792     	SCpnt->SCp.Status++;
793     }
794     
795     static int sym53c416_command(Scsi_Cmnd *SCpnt)
796     {
797     	sym53c416_queuecommand(SCpnt, internal_done);
798     	SCpnt->SCp.Status = 0;
799     	while(!SCpnt->SCp.Status)
800     		barrier();
801     	return SCpnt->result;
802     }
803     
804     static int sym53c416_abort(Scsi_Cmnd *SCpnt)
805     {
806     	//printk("sym53c416_abort\n");
807     	/* We don't know how to abort for the moment */
808     	return SCSI_ABORT_SNOOZE;
809     }
810     
811     static int sym53c416_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
812     {
813     	int base;
814     	int scsi_id = -1;	
815     	int i;
816     
817     	//printk("sym53c416_reset\n");
818     	base = SCpnt->host->io_port;
819     	/* search scsi_id */
820     	for(i = 0; i < host_index && scsi_id != -1; i++)
821     		if(hosts[i].base == base)
822     			scsi_id = hosts[i].scsi_id;
823     	outb(RESET_CHIP, base + COMMAND_REG);
824     	outb(NOOP | PIO_MODE, base + COMMAND_REG);
825     	outb(RESET_SCSI_BUS, base + COMMAND_REG);
826     	sym53c416_init(base, scsi_id);
827     	return SCSI_RESET_PENDING;
828     }
829     
830     static int sym53c416_bios_param(Disk *disk, kdev_t dev, int *ip)
831     {
832     	int size;
833     
834     	size = disk->capacity;
835     	ip[0] = 64;				/* heads                        */
836     	ip[1] = 32;				/* sectors                      */
837     	if((ip[2] = size >> 11) > 1024)		/* cylinders, test for big disk */
838     	{
839     		ip[0] = 255;			/* heads                        */
840     		ip[1] = 63;			/* sectors                      */
841     		ip[2] = size / (255 * 63);	/* cylinders                    */
842     	}
843     	return 0;
844     }
845     
846     /* Loadable module support */
847     #ifdef MODULE
848     
849     MODULE_AUTHOR("Lieven Willems");
850     MODULE_PARM(sym53c416, "1-2i");
851     MODULE_PARM(sym53c416_1, "1-2i");
852     MODULE_PARM(sym53c416_2, "1-2i");
853     MODULE_PARM(sym53c416_3, "1-2i");
854     
855     #endif
856     
857     static Scsi_Host_Template driver_template = SYM53C416;
858     
859     #include "scsi_module.c"
860