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

1     /****************************************************************************
2      * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
3      *
4      * pci2000.c - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
5      *
6      * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
7      * All Rights Reserved.
8      *
9      * Redistribution and use in source and binary forms, with or without
10      * modification, are permitted provided that redistributions of source
11      * code retain the above copyright notice and this comment without
12      * modification.
13      *
14      * Technical updates and product information at:
15      *  http://www.psidisk.com
16      *
17      * Please send questions, comments, bug reports to:
18      *  tech@psidisk.com Technical Support
19      *
20      *
21      *	Revisions	1.10	Jan-21-1999
22      *		- Fixed sign on message to reflect proper controller name.
23      *		- Added support for RAID status monitoring and control.
24      *
25      *  Revisions	1.11	Mar-22-1999
26      *		- Fixed control timeout to not lock up the entire system if
27      *		  controller goes offline completely.
28      *
29      *	Revisions 1.12		Mar-26-1999
30      *		- Fixed spinlock and PCI configuration.
31      *
32      *	Revisions 1.20		Mar-27-2000
33      *		- Added support for dynamic DMA
34      *
35      ****************************************************************************/
36     #define PCI2000_VERSION		"1.20"
37     
38     #include <linux/module.h>
39     
40     #include <linux/kernel.h>
41     #include <linux/types.h>
42     #include <linux/string.h>
43     #include <linux/pci.h>
44     #include <linux/ioport.h>
45     #include <linux/delay.h>
46     #include <linux/sched.h>
47     #include <linux/proc_fs.h>
48     #include <asm/dma.h>
49     #include <asm/system.h>
50     #include <asm/io.h>
51     #include <linux/blk.h>
52     #include "scsi.h"
53     #include "hosts.h"
54     #include <linux/stat.h>
55     #include <linux/spinlock.h>
56     
57     #include "pci2000.h"
58     #include "psi_roy.h"
59     
60     
61     //#define DEBUG 1
62     
63     #ifdef DEBUG
64     #define DEB(x) x
65     #define STOP_HERE	{int st;for(st=0;st<100;st++){st=1;}}
66     #else
67     #define DEB(x)
68     #define STOP_HERE
69     #endif
70     
71     typedef struct
72     	{
73     	unsigned int	address;
74     	unsigned int	length;
75     	}	SCATGATH, *PSCATGATH;
76     
77     typedef struct
78     	{
79     	Scsi_Cmnd		*SCpnt;
80     	PSCATGATH		 scatGath;
81     	dma_addr_t		 scatGathDma;
82     	UCHAR			*cdb;
83     	dma_addr_t		 cdbDma; 
84     	UCHAR			 tag;
85     	}	DEV2000, *PDEV2000;
86     
87     typedef struct
88     	{
89     	ULONG			 basePort;
90     	ULONG			 mb0;
91     	ULONG			 mb1;
92     	ULONG			 mb2;
93     	ULONG			 mb3;
94     	ULONG			 mb4;
95     	ULONG			 cmd;
96     	ULONG			 tag;
97     	ULONG			 irqOwned;
98     	struct pci_dev	*pdev;
99     	DEV2000	 		 dev[MAX_BUS][MAX_UNITS];
100     	}	ADAPTER2000, *PADAPTER2000;
101     
102     #define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
103     #define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
104     
105     
106     static struct	Scsi_Host 	   *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
107     static			int				NumAdapters = 0;
108     /****************************************************************
109      *	Name:			WaitReady	:LOCAL
110      *
111      *	Description:	Wait for controller ready.
112      *
113      *	Parameters:		padapter - Pointer adapter data structure.
114      *
115      *	Returns:		TRUE on not ready.
116      *
117      ****************************************************************/
118     static int WaitReady (PADAPTER2000 padapter)
119     	{
120     	ULONG	z;
121     
122     	for ( z = 0;  z < (TIMEOUT_COMMAND * 4);  z++ )
123     		{
124     		if ( !inb_p (padapter->cmd) )
125     			return FALSE;
126     		udelay (250);
127     		};								
128     	return TRUE;
129     	}
130     /****************************************************************
131      *	Name:			WaitReadyLong	:LOCAL
132      *
133      *	Description:	Wait for controller ready.
134      *
135      *	Parameters:		padapter - Pointer adapter data structure.
136      *
137      *	Returns:		TRUE on not ready.
138      *
139      ****************************************************************/
140     static int WaitReadyLong (PADAPTER2000 padapter)
141     	{
142     	ULONG	z;
143     
144     	for ( z = 0;  z < (5000 * 4);  z++ )
145     		{
146     		if ( !inb_p (padapter->cmd) )
147     			return FALSE;
148     		udelay (250);
149     		};								
150     	return TRUE;
151     	}
152     /****************************************************************
153      *	Name:	OpDone	:LOCAL
154      *
155      *	Description:	Clean up operation and issue done to caller.
156      *
157      *	Parameters:		SCpnt	- Pointer to SCSI command structure.
158      *					status	- Caller status.
159      *
160      *	Returns:		Nothing.
161      *
162      ****************************************************************/
163     static void OpDone (Scsi_Cmnd *SCpnt, ULONG status)
164     	{
165     	SCpnt->result = status;
166     	SCpnt->scsi_done (SCpnt);
167     	}
168     /****************************************************************
169      *	Name:	Command		:LOCAL
170      *
171      *	Description:	Issue queued command to the PCI-2000.
172      *
173      *	Parameters:		padapter - Pointer to adapter information structure.
174      *					cmd		 - PCI-2000 command byte.
175      *
176      *	Returns:		Non-zero command tag if operation is accepted.
177      *
178      ****************************************************************/
179     static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
180     	{
181     	outb_p (cmd, padapter->cmd);
182     	if ( WaitReady (padapter) )
183     		return 0;
184     
185     	if ( inw_p (padapter->mb0) )
186     		return 0;
187     
188     	return inb_p (padapter->mb1);
189     	}
190     /****************************************************************
191      *	Name:	BuildSgList		:LOCAL
192      *
193      *	Description:	Build the scatter gather list for controller.
194      *
195      *	Parameters:		SCpnt	 - Pointer to SCSI command structure.
196      *					padapter - Pointer to adapter information structure.
197      *					pdev	 - Pointer to adapter device structure.
198      *
199      *	Returns:		Non-zero in not scatter gather.
200      *
201      ****************************************************************/
202     static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
203     	{
204     	int					 z;
205     	int					 zc;
206     	struct scatterlist	*sg;
207     
208     	if ( SCpnt->use_sg )
209     		{
210     		sg = (struct scatterlist *)SCpnt->request_buffer;
211     		zc = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
212     		for ( z = 0;  z < zc;  z++ )
213     			{
214     			pdev->scatGath[z].address = cpu_to_le32 (sg_dma_address (sg));
215     			pdev->scatGath[z].length = cpu_to_le32 (sg_dma_len (sg++));
216     			}
217     		outl (pdev->scatGathDma, padapter->mb2);
218     		outl ((zc << 24) | SCpnt->request_bufflen, padapter->mb3);
219     		return FALSE;
220     		}
221     	if ( !SCpnt->request_bufflen)
222     		{
223     		outl (0, padapter->mb2);
224     		outl (0, padapter->mb3);
225     		return TRUE;
226     		}
227     	SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
228     	outl (SCpnt->SCp.have_data_in, padapter->mb2);
229     	outl (SCpnt->request_bufflen, padapter->mb3);
230     	return TRUE;
231     	}
232     /*********************************************************************
233      *	Name:	PsiRaidCmd
234      *
235      *	Description:	Execute a simple command.
236      *
237      *	Parameters:		padapter - Pointer to adapter control structure.
238      *					cmd		 - Roy command byte.
239      *
240      *	Returns:		Return error status.
241      *
242      ********************************************************************/
243     static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
244     	{
245     	if ( WaitReady (padapter) )						// test for command register ready
246     		return DID_TIME_OUT;
247     	outb_p (cmd, padapter->cmd);					// issue command
248     	if ( WaitReadyLong (padapter) )					// wait for adapter ready
249     		return DID_TIME_OUT;
250     	return DID_OK;
251     	}
252     /****************************************************************
253      *	Name:	Irq_Handler	:LOCAL
254      *
255      *	Description:	Interrupt handler.
256      *
257      *	Parameters:		irq		- Hardware IRQ number.
258      *					dev_id	-
259      *					regs	-
260      *
261      *	Returns:		TRUE if drive is not ready in time.
262      *
263      ****************************************************************/
264     static void Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
265     	{
266     	struct Scsi_Host   *shost = NULL;	// Pointer to host data block
267     	PADAPTER2000		padapter;		// Pointer to adapter control structure
268     	PDEV2000			pdev;
269     	Scsi_Cmnd		   *SCpnt;
270     	UCHAR				tag = 0;
271     	UCHAR				tag0;
272     	ULONG				error;
273     	int					pun;
274     	int					bus;
275     	int					z;
276         unsigned long		flags;
277     
278         /*
279          * Disable interrupts, if they aren't already disabled and acquire
280          * the I/O spinlock.
281          */
282         spin_lock_irqsave (&io_request_lock, flags);
283     
284     	DEB(printk ("\npci2000 received interrupt "));
285     	for ( z = 0; z < NumAdapters;  z++ )										// scan for interrupt to process
286     		{
287     		if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
288     			{
289     			tag = inb_p (HOSTDATA(PsiHost[z])->tag);
290     			if (  tag )
291     				{
292     				shost = PsiHost[z];
293     				break;
294     				}
295     			}
296     		}
297     
298     	if ( !shost )
299     		{
300     		DEB (printk ("\npci2000: not my interrupt"));
301     		goto irq_return;
302     		}
303     
304     	padapter = HOSTDATA(shost);
305     
306     	tag0 = tag & 0x7F;															// mask off the error bit
307     	for ( bus = 0;  bus < MAX_BUS;  bus++ )										// scan the busses
308         	{
309     		for ( pun = 0;  pun < MAX_UNITS;  pun++ )								// scan the targets
310         		{
311     			pdev = &padapter->dev[bus][pun];
312     			if ( !pdev->tag )
313         			continue;
314     			if ( pdev->tag == tag0 )											// is this it?
315     				{
316     				pdev->tag = 0;
317     				SCpnt = pdev->SCpnt;
318     				goto unmapProceed;
319         			}
320     			}
321         	}
322     
323     	outb_p (0xFF, padapter->tag);												// clear the op interrupt
324     	outb_p (CMD_DONE, padapter->cmd);											// complete the op
325     	goto irq_return;;															// done, but, with what?
326     
327     unmapProceed:;
328     	if ( !bus )
329     		{
330     		switch ( SCpnt->cmnd[0] )
331     			{
332     			case SCSIOP_TEST_UNIT_READY:
333     				pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
334     				goto irqProceed;
335     			case SCSIOP_READ_CAPACITY:
336     				pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
337     				goto irqProceed;
338     			case SCSIOP_VERIFY:
339     			case SCSIOP_START_STOP_UNIT:
340     			case SCSIOP_MEDIUM_REMOVAL:
341     				goto irqProceed;
342     			}
343     		}
344     	if ( SCpnt->SCp.have_data_in )
345     		pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
346     	else 
347     		{
348     		if ( SCpnt->use_sg )
349     			pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
350     		}
351     
352     irqProceed:;
353     	if ( tag & ERR08_TAGGED )												// is there an error here?
354     		{
355     		if ( WaitReady (padapter) )
356     			{
357     			OpDone (SCpnt, DID_TIME_OUT << 16);
358     			goto irq_return;;
359     			}
360     
361     		outb_p (tag0, padapter->mb0);										// get real error code
362     		outb_p (CMD_ERROR, padapter->cmd);
363     		if ( WaitReady (padapter) )											// wait for controller to suck up the op
364     			{
365     			OpDone (SCpnt, DID_TIME_OUT << 16);
366     			goto irq_return;;
367     			}
368     
369     		error = inl (padapter->mb0);										// get error data
370     		outb_p (0xFF, padapter->tag);										// clear the op interrupt
371     		outb_p (CMD_DONE, padapter->cmd);									// complete the op
372     
373     		DEB (printk ("status: %lX ", error));
374     		if ( error == 0x00020002 )											// is this error a check condition?
375     			{
376     			if ( bus )														// are we doint SCSI commands?
377     				{
378     				OpDone (SCpnt, (DID_OK << 16) | 2);
379     				goto irq_return;;
380     				}
381     			if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
382     				OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);	// test caller we have sense data too
383     			else
384     				OpDone (SCpnt, DID_ERROR << 16);
385     			goto irq_return;;
386     			}
387     		OpDone (SCpnt, DID_ERROR << 16);
388     		goto irq_return;;
389     		}
390     
391     	outb_p (0xFF, padapter->tag);											// clear the op interrupt
392     	outb_p (CMD_DONE, padapter->cmd);										// complete the op
393     	OpDone (SCpnt, DID_OK << 16);
394     
395     irq_return:;
396         /*
397          * Release the I/O spinlock and restore the original flags
398          * which will enable interrupts if and only if they were
399          * enabled on entry.
400          */
401         spin_unlock_irqrestore (&io_request_lock, flags);
402     	}
403     /****************************************************************
404      *	Name:	Pci2000_QueueCommand
405      *
406      *	Description:	Process a queued command from the SCSI manager.
407      *
408      *	Parameters:		SCpnt - Pointer to SCSI command structure.
409      *					done  - Pointer to done function to call.
410      *
411      *	Returns:		Status code.
412      *
413      ****************************************************************/
414     int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
415     	{
416     	UCHAR		   *cdb = (UCHAR *)SCpnt->cmnd;					// Pointer to SCSI CDB
417     	PADAPTER2000	padapter = HOSTDATA(SCpnt->host);			// Pointer to adapter control structure
418     	int				rc		 = -1;								// command return code
419     	UCHAR			bus		 = SCpnt->channel;
420     	UCHAR			pun		 = SCpnt->target;
421     	UCHAR			lun		 = SCpnt->lun;
422     	UCHAR			cmd;
423     	PDEV2000		pdev	 = &padapter->dev[bus][pun];
424     
425     	if ( !done )
426     		{
427     		printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
428     		return 0;
429     		}
430     
431     	SCpnt->scsi_done = done;
432     	SCpnt->SCp.have_data_in = 0;
433     	pdev->SCpnt = SCpnt;  									// Save this command data
434     
435     	if ( WaitReady (padapter) )
436     		{
437     		rc = DID_ERROR;
438     		goto finished;
439     		}
440     
441     	outw_p (pun | (lun << 8), padapter->mb0);
442     
443     	if ( bus )
444     		{
445     		DEB (if(*cdb) printk ("\nCDB: %X-  %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
446     		DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d, internal_timout: %d", SCpnt->timeout_per_command,
447     							  SCpnt->timeout_total, SCpnt->timeout, SCpnt->internal_timeout));
448     		outl (SCpnt->timeout_per_command, padapter->mb1);
449     		outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
450     		if ( WaitReady (padapter) )
451     			{
452     			rc = DID_ERROR;
453     			goto finished;
454     			}
455     
456     		outw_p (pun | (lun << 8), padapter->mb0);
457     		outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
458     		memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
459     
460     		outl (pdev->cdbDma, padapter->mb1);
461     		if ( BuildSgList (SCpnt, padapter, pdev) )
462     			cmd = CMD_SCSI_THRU;
463     		else
464     			cmd = CMD_SCSI_THRU_SG;
465     		if ( (pdev->tag = Command (padapter, cmd)) == 0 )
466     			rc = DID_TIME_OUT;
467     		goto finished;
468     		}
469     	else
470     		{
471     		if ( lun )
472     			{
473     			rc = DID_BAD_TARGET;
474     			goto finished;
475     			}
476     		}
477     
478     	switch ( *cdb )
479     		{
480     		case SCSIOP_INQUIRY:   					// inquiry CDB
481     			if ( cdb[2] == SC_MY_RAID )
482     				{
483     				switch ( cdb[3] ) 
484     					{
485     					case MY_SCSI_REBUILD:
486     						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
487     						return 0;
488     					case MY_SCSI_ALARMMUTE:
489     						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
490     						return 0;
491     					case MY_SCSI_DEMOFAIL:
492     						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
493     						return 0;
494     					default:
495     						if ( SCpnt->use_sg )
496     							{
497     							rc = DID_ERROR;
498     							goto finished;
499     							}
500     						else
501     							{
502     							SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
503     													  scsi_to_pci_dma_dir(SCpnt->sc_data_direction));
504     							outl (SCpnt->SCp.have_data_in, padapter->mb2);
505     							}
506     						outl (cdb[5], padapter->mb0);
507     						outl (cdb[3], padapter->mb3);
508     						cmd = CMD_DASD_RAID_RQ;
509     						break;
510     					}
511     				break;
512     				}
513     			
514     			if ( SCpnt->use_sg )
515     				{
516     				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)SCpnt->request_buffer)->address, 
517     										  SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
518     				}
519     			else
520     				{
521     				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 
522     										  SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction));
523     				}
524     			outl (SCpnt->SCp.have_data_in, padapter->mb2);
525     			outl (SCpnt->request_bufflen, padapter->mb3);
526     			cmd = CMD_DASD_SCSI_INQ;
527     			break;
528     
529     		case SCSIOP_TEST_UNIT_READY:			// test unit ready CDB
530     			SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
531     			outl (SCpnt->SCp.have_data_in, padapter->mb2);
532     			outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
533     			cmd = CMD_TEST_READY;
534     			break;
535     
536     		case SCSIOP_READ_CAPACITY:			  	// read capacity CDB
537     			if ( SCpnt->use_sg )
538     				{
539     				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
540     										  8, PCI_DMA_FROMDEVICE);
541     				}
542     			else
543     				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
544     			outl (SCpnt->SCp.have_data_in, padapter->mb2);
545     			outl (8, padapter->mb3);
546     			cmd = CMD_DASD_CAP;
547     			break;
548     		case SCSIOP_VERIFY:						// verify CDB
549     			outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
550     			outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
551     			cmd = CMD_READ_SG;
552     			break;
553     		case SCSIOP_READ:						// read10 CDB
554     			outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
555     			outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
556     			if ( BuildSgList (SCpnt, padapter, pdev) )
557     				cmd = CMD_READ;
558     			else
559     				cmd = CMD_READ_SG;
560     			break;
561     		case SCSIOP_READ6:						// read6  CDB
562     			outw_p (cdb[4], padapter->mb0 + 2);
563     			outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
564     			if ( BuildSgList (SCpnt, padapter, pdev) )
565     				cmd = CMD_READ;
566     			else
567     				cmd = CMD_READ_SG;
568     			break;
569     		case SCSIOP_WRITE:						// write10 CDB
570     			outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
571     			outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
572     			if ( BuildSgList (SCpnt, padapter, pdev) )
573     				cmd = CMD_WRITE;
574     			else
575     				cmd = CMD_WRITE_SG;
576     			break;
577     		case SCSIOP_WRITE6:						// write6  CDB
578     			outw_p (cdb[4], padapter->mb0 + 2);
579     			outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
580     			if ( BuildSgList (SCpnt, padapter, pdev) )
581     				cmd = CMD_WRITE;
582     			else
583     				cmd = CMD_WRITE_SG;
584     			break;
585     		case SCSIOP_START_STOP_UNIT:
586     			cmd = CMD_EJECT_MEDIA;
587     			break;
588     		case SCSIOP_MEDIUM_REMOVAL:
589     			switch ( cdb[4] )
590     				{
591     				case 0:
592     					cmd = CMD_UNLOCK_DOOR;
593     					break;
594     				case 1:
595     					cmd = CMD_LOCK_DOOR;
596     					break;
597     				default:
598     					cmd = 0;
599     					break;
600     				}
601     			if ( cmd )
602     				break;
603     		default:
604     			DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
605     			OpDone (SCpnt, DID_ERROR << 16);
606     			return 0;
607     		}
608     
609     	if ( (pdev->tag = Command (padapter, cmd)) == 0 )
610     		rc = DID_TIME_OUT;
611     finished:;
612     	if ( rc != -1 )
613     		OpDone (SCpnt, rc << 16);
614     	return 0;
615     	}
616     /****************************************************************
617      *	Name:	internal_done :LOCAL
618      *
619      *	Description:	Done handler for non-queued commands
620      *
621      *	Parameters:		SCpnt - Pointer to SCSI command structure.
622      *
623      *	Returns:		Nothing.
624      *
625      ****************************************************************/
626     static void internal_done (Scsi_Cmnd * SCpnt)
627     	{
628     	SCpnt->SCp.Status++;
629     	}
630     /****************************************************************
631      *	Name:	Pci2000_Command
632      *
633      *	Description:	Process a command from the SCSI manager.
634      *
635      *	Parameters:		SCpnt - Pointer to SCSI command structure.
636      *
637      *	Returns:		Status code.
638      *
639      ****************************************************************/
640     int Pci2000_Command (Scsi_Cmnd *SCpnt)
641     	{
642     	DEB(printk("pci2000_command: ..calling pci2000_queuecommand\n"));
643     
644     	Pci2000_QueueCommand (SCpnt, internal_done);
645     
646         SCpnt->SCp.Status = 0;
647     	while (!SCpnt->SCp.Status)
648     		barrier ();
649     	return SCpnt->result;
650     	}
651     /****************************************************************
652      *	Name:	Pci2000_Detect
653      *
654      *	Description:	Detect and initialize our boards.
655      *
656      *	Parameters:		tpnt - Pointer to SCSI host template structure.
657      *
658      *	Returns:		Number of adapters installed.
659      *
660      ****************************************************************/
661     int Pci2000_Detect (Scsi_Host_Template *tpnt)
662     	{
663     	int					found = 0;
664     	int					installed = 0;
665     	struct Scsi_Host   *pshost;
666     	PADAPTER2000	    padapter;
667     	int					z, zz;
668     	int					setirq;
669     	struct pci_dev	   *pdev = NULL;
670     	UCHAR			   *consistent;
671     	dma_addr_t			consistentDma;
672     
673     
674     	if ( !pci_present () )
675     		{
676     		printk ("pci2000: PCI BIOS not present\n");
677     		return 0;
678     		}
679     
680     	while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
681     		{
682     		if (pci_enable_device(pdev))
683     			continue;
684     		pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
685     		if(pshost == NULL)
686     			continue;
687     		padapter = HOSTDATA(pshost);
688     
689     		padapter->basePort = pci_resource_start (pdev, 1);
690     		DEB (printk ("\nBase Regs = %#04X", padapter->basePort));			// get the base I/O port address
691     		padapter->mb0	= padapter->basePort + RTR_MAILBOX;		   			// get the 32 bit mail boxes
692     		padapter->mb1	= padapter->basePort + RTR_MAILBOX + 4;
693     		padapter->mb2	= padapter->basePort + RTR_MAILBOX + 8;
694     		padapter->mb3	= padapter->basePort + RTR_MAILBOX + 12;
695     		padapter->mb4	= padapter->basePort + RTR_MAILBOX + 16;
696     		padapter->cmd	= padapter->basePort + RTR_LOCAL_DOORBELL;			// command register
697     		padapter->tag	= padapter->basePort + RTR_PCI_DOORBELL;			// tag/response register
698     		padapter->pdev = pdev;
699     
700     		if ( WaitReady (padapter) )
701     			goto unregister;
702     		outb_p (0x84, padapter->mb0);
703     		outb_p (CMD_SPECIFY, padapter->cmd);
704     		if ( WaitReady (padapter) )
705     			goto unregister;
706     
707     		consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
708     		if ( !consistent )
709     			{
710     			printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
711     			goto unregister;
712     			}
713     		
714     		scsi_set_pci_device(pshost, pdev);
715     		pshost->irq = pdev->irq;
716     		setirq = 1;
717     		padapter->irqOwned = 0;
718     		for ( z = 0;  z < installed;  z++ )									// scan for shared interrupts
719     			{
720     			if ( PsiHost[z]->irq == pshost->irq )							// if shared then, don't posses
721     				setirq = 0;
722     			}
723     		if ( setirq )												// if not shared, posses
724     			{
725     			if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
726     				{
727     				if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
728     					{
729     					printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
730     					pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
731     					goto unregister;
732     					}
733     				}
734     			padapter->irqOwned = pshost->irq;						// set IRQ as owned
735     			}
736     		PsiHost[installed]	= pshost;										// save SCSI_HOST pointer
737     
738     		pshost->io_port		= padapter->basePort;
739     		pshost->n_io_port	= 0xFF;
740     		pshost->unique_id	= padapter->basePort;
741     		pshost->max_id		= 16;
742     		pshost->max_channel	= 1;
743     
744     		for ( zz = 0;  zz < MAX_BUS;  zz++ )
745     			for ( z = 0; z < MAX_UNITS;  z++ )
746     				{
747     				padapter->dev[zz][z].tag = 0;
748     				padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
749     				padapter->dev[zz][z].scatGathDma = consistentDma;
750     				consistent += 16 * sizeof (SCATGATH);
751     				consistentDma += 16 * sizeof (SCATGATH);
752     				padapter->dev[zz][z].cdb = (UCHAR *)consistent;
753     				padapter->dev[zz][z].cdbDma = consistentDma;
754     				consistent += MAX_COMMAND_SIZE;
755     				consistentDma += MAX_COMMAND_SIZE;
756     				}
757     			
758     		printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX  IRQ = %d\n", padapter->basePort, pshost->irq);
759     		printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION,  __DATE__, __TIME__);
760     		found++;
761     		if ( ++installed < MAXADAPTER )
762     			continue;
763     		break;
764     unregister:;
765     		scsi_unregister (pshost);
766     		found++;
767     		}
768     	NumAdapters = installed;
769     	return installed;
770     	}
771     /****************************************************************
772      *	Name:	Pci2000_Abort
773      *
774      *	Description:	Process the Abort command from the SCSI manager.
775      *
776      *	Parameters:		SCpnt - Pointer to SCSI command structure.
777      *
778      *	Returns:		Allways snooze.
779      *
780      ****************************************************************/
781     int Pci2000_Abort (Scsi_Cmnd *SCpnt)
782     	{
783     	DEB (printk ("pci2000_abort\n"));
784     	return SCSI_ABORT_SNOOZE;
785     	}
786     /****************************************************************
787      *	Name:	Pci2000_Reset
788      *
789      *	Description:	Process the Reset command from the SCSI manager.
790      *
791      *	Parameters:		SCpnt - Pointer to SCSI command structure.
792      *					flags - Flags about the reset command
793      *
794      *	Returns:		No active command at this time, so this means
795      *					that each time we got some kind of response the
796      *					last time through.  Tell the mid-level code to
797      *					request sense information in order to decide what
798      *					to do next.
799      *
800      ****************************************************************/
801     int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
802     	{
803     	return SCSI_RESET_PUNT;
804     	}
805     /****************************************************************
806      *	Name:	Pci2000_Release
807      *
808      *	Description:	Release resources allocated for a single each adapter.
809      *
810      *	Parameters:		pshost - Pointer to SCSI command structure.
811      *
812      *	Returns:		zero.
813      *
814      ****************************************************************/
815     int Pci2000_Release (struct Scsi_Host *pshost)
816     	{
817         PADAPTER2000	padapter = HOSTDATA (pshost);
818     
819     	if ( padapter->irqOwned )
820     		free_irq (pshost->irq, padapter);
821     	pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
822     	release_region (pshost->io_port, pshost->n_io_port);
823         scsi_unregister(pshost);
824         return 0;
825     	}
826     
827     #include "sd.h"
828     /****************************************************************
829      *	Name:	Pci2000_BiosParam
830      *
831      *	Description:	Process the biosparam request from the SCSI manager to
832      *					return C/H/S data.
833      *
834      *	Parameters:		disk - Pointer to SCSI disk structure.
835      *					dev	 - Major/minor number from kernel.
836      *					geom - Pointer to integer array to place geometry data.
837      *
838      *	Returns:		zero.
839      *
840      ****************************************************************/
841     int Pci2000_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[])
842     	{
843     	PADAPTER2000	    padapter;
844     
845     	padapter = HOSTDATA(disk->device->host);
846     
847     	if ( WaitReady (padapter) )
848     		return 0;
849     	outb_p (disk->device->id, padapter->mb0);
850     	outb_p (CMD_GET_PARMS, padapter->cmd);
851     	if ( WaitReady (padapter) )
852     		return 0;
853     
854     	geom[0] = inb_p (padapter->mb2 + 3);
855     	geom[1] = inb_p (padapter->mb2 + 2);
856     	geom[2] = inw_p (padapter->mb2);
857     	return 0;
858     	}
859     
860     
861     /* Eventually this will go into an include file, but this will be later */
862     static Scsi_Host_Template driver_template = PCI2000;
863     
864     #include "scsi_module.c"
865