File: /usr/src/linux/drivers/net/wan/sdladrv.c

1     /*****************************************************************************
2     * sdladrv.c	SDLA Support Module.  Main module.
3     *
4     *		This module is a library of common hardware-specific functions
5     *		used by all Sangoma drivers.
6     *
7     * Author:	Gideon Hack	
8     *
9     * Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
10     *
11     *		This program is free software; you can redistribute it and/or
12     *		modify it under the terms of the GNU General Public License
13     *		as published by the Free Software Foundation; either version
14     *		2 of the License, or (at your option) any later version.
15     * ============================================================================
16     * Mar 20, 2001  Nenad Corbic	Added the auto_pci_cfg filed, to support
17     *                               the PCISLOT #0. 
18     * Apr 04, 2000  Nenad Corbic	Fixed the auto memory detection code.
19     *                               The memory test at address 0xC8000.
20     * Mar 09, 2000  Nenad Corbic 	Added Gideon's Bug Fix: clear pci
21     *                               interrupt flags on initial load.
22     * Jun 02, 1999  Gideon Hack     Added support for the S514 adapter.
23     *				Updates for Linux 2.2.X kernels.	
24     * Sep 17, 1998	Jaspreet Singh	Updates for linux 2.2.X kernels
25     * Dec 20, 1996	Gene Kozin	Version 3.0.0. Complete overhaul.
26     * Jul 12, 1996	Gene Kozin	Changes for Linux 2.0 compatibility.
27     * Jun 12, 1996	Gene Kozin 	Added support for S503 card.
28     * Apr 30, 1996	Gene Kozin	SDLA hardware interrupt is acknowledged before
29     *				calling protocolspecific ISR.
30     *				Register I/O ports with Linux kernel.
31     *				Miscellaneous bug fixes.
32     * Dec 20, 1995	Gene Kozin	Fixed a bug in interrupt routine.
33     * Oct 14, 1995	Gene Kozin	Initial version.
34     *****************************************************************************/
35     
36     /*****************************************************************************
37      * Notes:
38      * ------
39      * 1. This code is ment to be system-independent (as much as possible).  To
40      *    achive this, various macros are used to hide system-specific interfaces.
41      *    To compile this code, one of the following constants must be defined:
42      *
43      *	Platform	Define
44      *	--------	------
45      *	Linux		_LINUX_
46      *	SCO Unix	_SCO_UNIX_
47      *
48      * 2. Supported adapter types:
49      *
50      *	S502A
51      *	ES502A (S502E)
52      *	S503
53      *	S507
54      *	S508 (S509)
55      *
56      * 3. S502A Notes:
57      *
58      *	There is no separate DPM window enable/disable control in S502A.  It
59      *	opens immediately after a window number it written to the HMCR
60      *	register.  To close the window, HMCR has to be written a value
61      *	????1111b (e.g. 0x0F or 0xFF).
62      *
63      *	S502A DPM window cannot be located at offset E000 (e.g. 0xAE000).
64      *
65      *	There should be a delay of ??? before reading back S502A status
66      *	register.
67      *
68      * 4. S502E Notes:
69      *
70      *	S502E has a h/w bug: although default IRQ line state is HIGH, enabling
71      *	interrupts by setting bit 1 of the control register (BASE) to '1'
72      *	causes it to go LOW! Therefore, disabling interrupts by setting that
73      *	bit to '0' causes low-to-high transition on IRQ line (ghosty
74      *	interrupt). The same occurs when disabling CPU by resetting bit 0 of
75      *	CPU control register (BASE+3) - see the next note.
76      *
77      *	S502E CPU and DPM control is limited:
78      *
79      *	o CPU cannot be stopped independently. Resetting bit 0 of the CPUi
80      *	  control register (BASE+3) shuts the board down entirely, including
81      *	  DPM;
82      *
83      *	o DPM access cannot be controlled dynamically. Ones CPU is started,
84      *	  bit 1 of the control register (BASE) is used to enable/disable IRQ,
85      *	  so that access to shared memory cannot be disabled while CPU is
86      *	  running.
87      ****************************************************************************/
88     
89     #define	_LINUX_
90     
91     #if	defined(_LINUX_)	/****** Linux *******************************/
92     
93     #include <linux/config.h>
94     #include <linux/version.h>
95     #include <linux/kernel.h>	/* printk(), and other useful stuff */
96     #include <linux/stddef.h>	/* offsetof(), etc. */
97     #include <linux/errno.h>	/* return codes */
98     #include <linux/string.h>	/* inline memset(), etc. */
99     #include <linux/module.h>	/* support for loadable modules */
100     #include <linux/sched.h>	/* for jiffies, HZ, etc. */
101     #include <linux/sdladrv.h>	/* API definitions */
102     #include <linux/sdlasfm.h>	/* SDLA firmware module definitions */
103     #include <linux/sdlapci.h>	/* SDLA PCI hardware definitions */
104     #include <linux/pci.h>		/* PCI defines and function prototypes */
105     #include <asm/io.h>		/* for inb(), outb(), etc. */
106     
107     #define _INB(port)		(inb(port))
108     #define _OUTB(port, byte)	(outb((byte),(port)))
109     #define	SYSTEM_TICK		jiffies
110     
111     
112     #if defined(LINUX_2_1) || defined(LINUX_2_4) 
113      #include <linux/init.h>
114     #else
115      #include <linux/bios32.h>/* BIOS32, PCI BIOS functions and definitions */
116      #define ioremap vremap
117      #define iounmap vfree
118      extern void * vremap (unsigned long offset, unsigned long size);
119      extern void vfree (void *addr);
120     #endif
121     
122     #elif	defined(_SCO_UNIX_)	/****** SCO Unix ****************************/
123     
124     #if	!defined(INKERNEL)
125     #error	This code MUST be compiled in kernel mode!
126     #endif
127     #include <sys/sdladrv.h>	/* API definitions */
128     #include <sys/sdlasfm.h>	/* SDLA firmware module definitions */
129     #include <sys/inline.h>		/* for inb(), outb(), etc. */
130     #define _INB(port)		(inb(port))
131     #define _OUTB(port, byte)	(outb((port),(byte)))
132     #define	SYSTEM_TICK		lbolt
133     
134     #else
135     #error	Unknown system type!
136     #endif
137     
138     #define	MOD_VERSION	3
139     #define	MOD_RELEASE	0
140     
141     #define	SDLA_IODELAY	100	/* I/O Rd/Wr delay, 10 works for 486DX2-66 */
142     #define	EXEC_DELAY	20	/* shared memory access delay, mks */
143     #define	EXEC_TIMEOUT	(HZ*2)	/* command timeout, in ticks */
144     
145     /* I/O port address range */
146     #define S502A_IORANGE	3
147     #define S502E_IORANGE	4
148     #define S503_IORANGE	3
149     #define S507_IORANGE	4
150     #define S508_IORANGE	4
151     
152     /* Maximum amount of memory */
153     #define S502_MAXMEM	0x10000L
154     #define S503_MAXMEM	0x10000L
155     #define S507_MAXMEM	0x40000L
156     #define S508_MAXMEM	0x40000L
157     
158     /* Minimum amount of memory */
159     #define S502_MINMEM	0x8000L
160     #define S503_MINMEM	0x8000L
161     #define S507_MINMEM	0x20000L
162     #define S508_MINMEM	0x20000L
163     #define NO_PORT         -1
164     
165     
166     
167     
168     
169     /****** Function Prototypes *************************************************/
170     
171     /* Module entry points. These are called by the OS and must be public. */
172     int init_module (void);
173     void cleanup_module (void);
174     
175     /* Hardware-specific functions */
176     static int sdla_detect	(sdlahw_t* hw);
177     static int sdla_autodpm	(sdlahw_t* hw);
178     static int sdla_setdpm	(sdlahw_t* hw);
179     static int sdla_load	(sdlahw_t* hw, sfm_t* sfm, unsigned len);
180     static int sdla_init	(sdlahw_t* hw);
181     static unsigned long sdla_memtest (sdlahw_t* hw);
182     static int sdla_bootcfg	(sdlahw_t* hw, sfm_info_t* sfminfo);
183     static unsigned char make_config_byte (sdlahw_t* hw);
184     static int sdla_start	(sdlahw_t* hw, unsigned addr);
185     
186     static int init_s502a	(sdlahw_t* hw);
187     static int init_s502e	(sdlahw_t* hw);
188     static int init_s503	(sdlahw_t* hw);
189     static int init_s507	(sdlahw_t* hw);
190     static int init_s508	(sdlahw_t* hw);
191                 
192     static int detect_s502a	(int port);
193     static int detect_s502e	(int port);
194     static int detect_s503	(int port);
195     static int detect_s507	(int port);
196     static int detect_s508	(int port);
197     static int detect_s514  (sdlahw_t* hw);
198     static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card);
199     
200     /* Miscellaneous functions */
201     static void peek_by_4 (unsigned long src, void* buf, unsigned len);
202     static void poke_by_4 (unsigned long dest, void* buf, unsigned len);
203     static int calibrate_delay (int mks);
204     static int get_option_index (unsigned* optlist, unsigned optval);
205     static unsigned check_memregion (void* ptr, unsigned len);
206     static unsigned	test_memregion (void* ptr, unsigned len);
207     static unsigned short checksum (unsigned char* buf, unsigned len);
208     static int init_pci_slot(sdlahw_t *);
209     
210     static int pci_probe(sdlahw_t *hw);
211     
212     /****** Global Data **********************************************************
213      * Note: All data must be explicitly initialized!!!
214      */
215     
216     static struct pci_device_id sdladrv_pci_tbl[] __initdata = {
217     	{ V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
218     	{ }			/* Terminating entry */
219     };
220     MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl);
221     
222     MODULE_LICENSE("GPL");
223     
224     /* private data */
225     static char modname[]	= "sdladrv";
226     static char fullname[]	= "SDLA Support Module";
227     static char copyright[]	= "(c) 1995-1999 Sangoma Technologies Inc.";
228     static unsigned	exec_idle;
229     
230     /* Hardware configuration options.
231      * These are arrays of configuration options used by verification routines.
232      * The first element of each array is its size (i.e. number of options).
233      */
234     static unsigned	s502_port_options[] =
235     	{ 4, 0x250, 0x300, 0x350, 0x360 }
236     ;
237     static unsigned	s503_port_options[] =
238     	{ 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 }
239     ;
240     static unsigned	s508_port_options[] =
241     	{ 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 }
242     ;
243     
244     static unsigned s502a_irq_options[] = { 0 };
245     static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 };
246     static unsigned s503_irq_options[]  = { 5, 2, 3, 4, 5, 7 };
247     static unsigned s508_irq_options[]  = { 8, 3, 4, 5, 7, 10, 11, 12, 15 };
248     
249     static unsigned s502a_dpmbase_options[] =
250     {
251     	28,
252     	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000,
253     	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000,
254     	0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000,
255     	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000,
256     };
257     static unsigned s507_dpmbase_options[] =
258     {
259     	32,
260     	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
261     	0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
262     	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
263     	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
264     };
265     static unsigned s508_dpmbase_options[] =	/* incl. S502E and S503 */
266     {
267     	32,
268     	0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
269     	0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
270     	0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
271     	0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000,
272     };
273     
274     /*
275     static unsigned	s502_dpmsize_options[] = { 2, 0x2000, 0x10000 };
276     static unsigned	s507_dpmsize_options[] = { 2, 0x2000, 0x4000 };
277     static unsigned	s508_dpmsize_options[] = { 1, 0x2000 };
278     */
279     
280     static unsigned	s502a_pclk_options[] = { 2, 3600, 7200 };
281     static unsigned	s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 };
282     static unsigned	s503_pclk_options[]  = { 3, 7200, 8000, 10000 };
283     static unsigned	s507_pclk_options[]  = { 1, 12288 };
284     static unsigned	s508_pclk_options[]  = { 1, 16000 };
285     
286     /* Host memory control register masks */
287     static unsigned char s502a_hmcr[] =
288     {
289     	0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C,	/* A0000 - AC000 */
290     	0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C,	/* C0000 - CC000 */
291     	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C,	/* D0000 - DC000 */
292     	0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C,	/* E0000 - EC000 */
293     };
294     static unsigned char s502e_hmcr[] =
295     {
296     	0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,	/* A0000 - AE000 */
297     	0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E,	/* C0000 - CE000 */
298     	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,	/* D0000 - DE000 */
299     	0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E,	/* E0000 - EE000 */
300     };
301     static unsigned char s507_hmcr[] =
302     {
303     	0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,	/* A0000 - AE000 */
304     	0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E,	/* B0000 - BE000 */
305     	0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E,	/* C0000 - CE000 */
306     	0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,	/* E0000 - EE000 */
307     };
308     static unsigned char s508_hmcr[] =
309     {
310     	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* A0000 - AE000 */
311     	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,	/* C0000 - CE000 */
312     	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,	/* D0000 - DE000 */
313     	0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,	/* E0000 - EE000 */
314     };
315     
316     static unsigned char s507_irqmask[] =
317     {
318     	0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0
319     };
320     
321     static int pci_slot_ar[MAX_S514_CARDS];
322     
323     /******* Kernel Loadable Module Entry Points ********************************/
324     
325     /*============================================================================
326      * Module 'insert' entry point.
327      * o print announcement
328      * o initialize static data
329      * o calibrate SDLA shared memory access delay.
330      *
331      * Return:	0	Ok
332      *		< 0	error.
333      * Context:	process
334      */
335     
336     #ifdef MODULE
337     int init_module (void)
338     #else
339     int sdladrv_init(void)
340     #endif
341     {
342     	int i=0;
343     
344     	printk(KERN_INFO "%s v%u.%u %s\n",
345     		fullname, MOD_VERSION, MOD_RELEASE, copyright);
346     	exec_idle = calibrate_delay(EXEC_DELAY);
347     #ifdef WANDEBUG	
348     	printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle);
349     #endif	
350     
351     	/* Initialize the PCI Card array, which
352              * will store flags, used to mark 
353              * card initialization state */
354     	for (i=0; i<MAX_S514_CARDS; i++)
355     		pci_slot_ar[i] = 0xFF;
356     
357     	return 0;
358     }
359     
360     #ifdef MODULE
361     /*============================================================================
362      * Module 'remove' entry point.
363      * o release all remaining system resources
364      */
365     void cleanup_module (void)
366     {
367     }
368     #endif
369     
370     /******* Kernel APIs ********************************************************/
371     
372     /*============================================================================
373      * Set up adapter.
374      * o detect adapter type
375      * o verify hardware configuration options
376      * o check for hardware conflicts
377      * o set up adapter shared memory
378      * o test adapter memory
379      * o load firmware
380      * Return:	0	ok.
381      *		< 0	error
382      */
383     
384     #if defined(LINUX_2_1) || defined(LINUX_2_4) 
385     EXPORT_SYMBOL(sdla_setup);
386     #endif
387     
388     int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len)
389     {
390     	unsigned* irq_opt	= NULL;	/* IRQ options */
391     	unsigned* dpmbase_opt	= NULL;	/* DPM window base options */
392     	unsigned* pclk_opt	= NULL;	/* CPU clock rate options */
393     	int err=0;
394     
395     	if (sdla_detect(hw)) {
396                     if(hw->type != SDLA_S514)
397                             printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n",
398                             modname, hw->port);
399     		return -EINVAL;
400     	}
401     
402     	if(hw->type != SDLA_S514) {
403                     printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n",
404                     modname, hw->type, hw->port);
405     
406                     hw->dpmsize = SDLA_WINDOWSIZE;
407                     switch (hw->type) {
408                     case SDLA_S502A:
409                             hw->io_range    = S502A_IORANGE;
410                             irq_opt         = s502a_irq_options;
411                             dpmbase_opt     = s502a_dpmbase_options;
412                             pclk_opt        = s502a_pclk_options;
413                             break;
414     
415                     case SDLA_S502E:
416                             hw->io_range    = S502E_IORANGE;
417                             irq_opt         = s502e_irq_options;
418                             dpmbase_opt     = s508_dpmbase_options;
419                             pclk_opt        = s502e_pclk_options;
420                             break;
421     
422                     case SDLA_S503:
423                             hw->io_range    = S503_IORANGE;
424                             irq_opt         = s503_irq_options;
425                             dpmbase_opt     = s508_dpmbase_options;
426                             pclk_opt        = s503_pclk_options;
427                             break;
428     
429                     case SDLA_S507:
430                             hw->io_range    = S507_IORANGE;
431                             irq_opt         = s508_irq_options;
432                             dpmbase_opt     = s507_dpmbase_options;
433                             pclk_opt        = s507_pclk_options;
434                             break;
435     
436                     case SDLA_S508:
437                             hw->io_range    = S508_IORANGE;
438                             irq_opt         = s508_irq_options;
439                             dpmbase_opt     = s508_dpmbase_options;
440                             pclk_opt        = s508_pclk_options;
441                             break;
442                     }
443     
444                     /* Verify IRQ configuration options */
445                     if (!get_option_index(irq_opt, hw->irq)) {
446                             printk(KERN_INFO "%s: IRQ %d is illegal!\n",
447                             	modname, hw->irq);
448                           return -EINVAL;
449                     } 
450     
451                     /* Verify CPU clock rate configuration options */
452                     if (hw->pclk == 0)
453                             hw->pclk = pclk_opt[1];  /* use default */
454             
455                     else if (!get_option_index(pclk_opt, hw->pclk)) {
456                             printk(KERN_INFO "%s: CPU clock %u is illegal!\n",
457     				modname, hw->pclk);
458                             return -EINVAL;
459                     } 
460                     printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n",
461     			modname, hw->pclk);
462     
463                     /* Setup adapter dual-port memory window and test memory */
464                     if (hw->dpmbase == 0) {
465                             err = sdla_autodpm(hw);
466                             if (err) {
467                                     printk(KERN_INFO
468     				"%s: can't find available memory region!\n",
469     					modname);
470                                     return err;
471                             }
472                     }
473                     else if (!get_option_index(dpmbase_opt,
474     			virt_to_phys(hw->dpmbase))) {
475                             printk(KERN_INFO
476     				"%s: memory address 0x%lX is illegal!\n",
477     				modname, virt_to_phys(hw->dpmbase));
478                             return -EINVAL;
479                     }               
480                     else if (sdla_setdpm(hw)) {
481                             printk(KERN_INFO
482     			"%s: 8K memory region at 0x%lX is not available!\n",
483     				modname, virt_to_phys(hw->dpmbase));
484                             return -EINVAL;
485                     } 
486                     printk(KERN_INFO
487     			"%s: dual-port memory window is set at 0x%lX.\n",
488     				modname, virt_to_phys(hw->dpmbase));
489     
490     
491     		/* If we find memory in 0xE**** Memory region, 
492                      * warn the user to disable the SHADOW RAM.  
493                      * Since memory corruption can occur if SHADOW is
494                      * enabled. This can causes random crashes ! */
495     		if (virt_to_phys(hw->dpmbase) >= 0xE0000){
496     			printk(KERN_WARNING "\n%s: !!!!!!!!  WARNING !!!!!!!!\n",modname);
497     			printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n",
498     						modname, virt_to_phys(hw->dpmbase));
499     			printk(KERN_WARNING "         Please disable the SHADOW RAM, otherwise\n");
500     			printk(KERN_WARNING "         your system might crash randomly from time to time !\n");
501     			printk(KERN_WARNING "%s: !!!!!!!!  WARNING !!!!!!!!\n\n",modname);
502     		}
503             }
504     
505     	else {
506     		hw->memory = test_memregion((void*)hw->dpmbase, 
507     			MAX_SIZEOF_S514_MEMORY);
508     		if(hw->memory < (256 * 1024)) {
509     			printk(KERN_INFO
510     				"%s: error in testing S514 memory (0x%lX)\n",
511     				modname, hw->memory);
512     			sdla_down(hw);
513     			return -EINVAL;
514     		}
515     	}
516         
517     	printk(KERN_INFO "%s: found %luK bytes of on-board memory\n",
518     		modname, hw->memory / 1024);
519     
520     	/* Load firmware. If loader fails then shut down adapter */
521     	err = sdla_load(hw, sfm, len);
522     	if (err) sdla_down(hw);		/* shutdown adapter */
523     
524     	return err;
525     } 
526     
527     /*============================================================================
528      * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
529      */
530     
531     #if defined(LINUX_2_1) || defined(LINUX_2_4)
532     EXPORT_SYMBOL(sdla_down);
533     #endif
534     
535     int sdla_down (sdlahw_t* hw)
536     {
537     	unsigned port = hw->port;
538     	int i;
539             unsigned char CPU_no;
540             u32 int_config, int_status;
541     
542             if(!port && (hw->type != SDLA_S514))
543                     return -EFAULT;
544     
545     	switch (hw->type) {
546     	case SDLA_S502A:
547     		_OUTB(port, 0x08);		/* halt CPU */
548     		_OUTB(port, 0x08);
549     		_OUTB(port, 0x08);
550     		hw->regs[0] = 0x08;
551     		_OUTB(port + 1, 0xFF);		/* close memory window */
552     		hw->regs[1] = 0xFF;
553     		break;
554     
555     	case SDLA_S502E:
556     		_OUTB(port + 3, 0);		/* stop CPU */
557     		_OUTB(port, 0);			/* reset board */
558     		for (i = 0; i < S502E_IORANGE; ++i)
559     			hw->regs[i] = 0
560     		;
561     		break;
562     
563     	case SDLA_S503:
564     	case SDLA_S507:
565     	case SDLA_S508:
566     		_OUTB(port, 0);			/* reset board logic */
567     		hw->regs[0] = 0;
568     		break;
569     
570     	case SDLA_S514:
571     		/* halt the adapter */
572                     *(char *)hw->vector = S514_CPU_HALT;
573             	CPU_no = hw->S514_cpu_no[0];
574     
575     #if defined(LINUX_2_1) || defined(LINUX_2_4)
576     		/* disable the PCI IRQ and disable memory access */
577                     pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config);
578     	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;
579                     pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config);
580     		read_S514_int_stat(hw, &int_status);
581     		S514_intack(hw, int_status);
582     		if(CPU_no == S514_CPU_A)
583                             pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD,
584     				PCI_CPU_A_MEM_DISABLE);
585     		else
586                             pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD,
587     				PCI_CPU_B_MEM_DISABLE);
588     #else
589                     /* disable the PCI IRQ and disable memory access */
590                  	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
591     			PCI_INT_CONFIG, &int_config);
592     	        int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A :	~PCI_DISABLE_IRQ_CPU_B;
593             	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
594     			PCI_INT_CONFIG, int_config);
595                     read_S514_int_stat(hw, &int_status);
596                     S514_intack(hw, int_status);
597          		// disable PCI memory access
598     		if(CPU_no == S514_CPU_A)
599     	     		pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,
600     				PCI_MAP0_DWORD, PCI_CPU_A_MEM_DISABLE);
601     		else
602                             pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func,							PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE);
603     #endif
604     
605     		/* free up the allocated virtual memory */
606      		iounmap((void *)hw->dpmbase);
607             	iounmap((void *)hw->vector);
608      		break;
609     
610     
611     	default:
612     		return -EINVAL;
613     	}
614     	return 0;
615     }
616     
617     /*============================================================================
618      * Map shared memory window into SDLA address space.
619      */
620     
621     #if defined(LINUX_2_1) || defined(LINUX_2_4)
622     EXPORT_SYMBOL(sdla_mapmem);
623     #endif
624     
625     int sdla_mapmem (sdlahw_t* hw, unsigned long addr)
626     {
627     	unsigned port = hw->port;
628     	register int tmp;
629     
630     	switch (hw->type) {
631     	case SDLA_S502A:
632     	case SDLA_S502E:
633     		if (addr < S502_MAXMEM)	{ /* verify parameter */
634     			tmp = addr >> 13;	/* convert to register mask */
635     			_OUTB(port + 2, tmp);
636     			hw->regs[2] = tmp;
637     		}
638     		else return -EINVAL;
639     		break;
640     
641     	case SDLA_S503:
642     		if (addr < S503_MAXMEM)	{ /* verify parameter */
643     			tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70);
644     			_OUTB(port, tmp);
645     			hw->regs[0] = tmp;
646     		}
647     		else return -EINVAL;
648     		break;
649     
650     	case SDLA_S507:
651     		if (addr < S507_MAXMEM) {
652     			if (!(_INB(port) & 0x02))
653     				return -EIO;
654     			tmp = addr >> 13;	/* convert to register mask */
655     			_OUTB(port + 2, tmp);
656     			hw->regs[2] = tmp;
657     		}
658     		else return -EINVAL;
659     		break;
660     
661     	case SDLA_S508:
662     		if (addr < S508_MAXMEM) {
663     			tmp = addr >> 13;	/* convert to register mask */
664     			_OUTB(port + 2, tmp);
665     			hw->regs[2] = tmp;
666     		}
667     		else return -EINVAL;
668     		break;
669     
670     	case SDLA_S514:
671     		return 0;
672     
673      	default:
674     		return -EINVAL;
675     	}
676     	hw->vector = addr & 0xFFFFE000L;
677     	return 0;
678     }
679     
680     /*============================================================================
681      * Enable interrupt generation.
682      */
683     
684     #if defined(LINUX_2_1) || defined(LINUX_2_4)
685     EXPORT_SYMBOL(sdla_inten);
686     #endif
687     
688     int sdla_inten (sdlahw_t* hw)
689     {
690     	unsigned port = hw->port;
691     	int tmp, i;
692     
693     	switch (hw->type) {
694     	case SDLA_S502E:
695     		/* Note thar interrupt control operations on S502E are allowed
696     		 * only if CPU is enabled (bit 0 of status register is set).
697     		 */
698     		if (_INB(port) & 0x01) {
699     			_OUTB(port, 0x02);	/* bit1 = 1, bit2 = 0 */
700     			_OUTB(port, 0x06);	/* bit1 = 1, bit2 = 1 */
701     			hw->regs[0] = 0x06;
702     		}
703     		else return -EIO;
704     		break;
705     
706     	case SDLA_S503:
707     		tmp = hw->regs[0] | 0x04;
708     		_OUTB(port, tmp);
709     		hw->regs[0] = tmp;		/* update mirror */
710     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
711     		if (!(_INB(port) & 0x02))		/* verify */
712     			return -EIO;
713     		break;
714     
715     	case SDLA_S508:
716     		tmp = hw->regs[0] | 0x10;
717     		_OUTB(port, tmp);
718     		hw->regs[0] = tmp;		/* update mirror */
719     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
720     		if (!(_INB(port + 1) & 0x10))		/* verify */
721     			return -EIO;
722     		break;
723     
724     	case SDLA_S502A:
725     	case SDLA_S507:
726     		break;
727     
728             case SDLA_S514:
729                     break;
730     
731     	default:
732     		return -EINVAL;
733     
734     	}
735     	return 0;
736     }
737     
738     /*============================================================================
739      * Disable interrupt generation.
740      */
741     
742     #if defined(LINUX_2_1) || defined(LINUX_2_4)
743     EXPORT_SYMBOL(sdla_intde);
744     #endif
745     
746     int sdla_intde (sdlahw_t* hw)
747     {
748     	unsigned port = hw->port;
749     	int tmp, i;
750     
751     	switch (hw->type) {
752     	case SDLA_S502E:
753     		/* Notes:
754     		 *  1) interrupt control operations are allowed only if CPU is
755     		 *     enabled (bit 0 of status register is set).
756     		 *  2) disabling interrupts using bit 1 of control register
757     		 *     causes IRQ line go high, therefore we are going to use
758     		 *     0x04 instead: lower it to inhibit interrupts to PC.
759     		 */
760     		if (_INB(port) & 0x01) {
761     			_OUTB(port, hw->regs[0] & ~0x04);
762     			hw->regs[0] &= ~0x04;
763     		}
764     		else return -EIO;
765     		break;
766     
767     	case SDLA_S503:
768     		tmp = hw->regs[0] & ~0x04;
769     		_OUTB(port, tmp);
770     		hw->regs[0] = tmp;			/* update mirror */
771     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
772     		if (_INB(port) & 0x02)			/* verify */
773     			return -EIO;
774     		break;
775     
776     	case SDLA_S508:
777     		tmp = hw->regs[0] & ~0x10;
778     		_OUTB(port, tmp);
779     		hw->regs[0] = tmp;			/* update mirror */
780     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
781     		if (_INB(port) & 0x10)			/* verify */
782     			return -EIO;
783     		break;
784     
785     	case SDLA_S502A:
786     	case SDLA_S507:
787     		break;
788     
789     	default:
790     		return -EINVAL;
791     	}
792     	return 0;
793     }
794     
795     /*============================================================================
796      * Acknowledge SDLA hardware interrupt.
797      */
798     
799     #if defined(LINUX_2_1) || defined(LINUX_2_4)
800     EXPORT_SYMBOL(sdla_intack);
801     #endif
802     
803     int sdla_intack (sdlahw_t* hw)
804     {
805     	unsigned port = hw->port;
806     	int tmp;
807     
808     	switch (hw->type) {
809     	case SDLA_S502E:
810     		/* To acknoledge hardware interrupt we have to toggle bit 3 of
811     		 * control register: \_/
812     		 * Note that interrupt control operations on S502E are allowed
813     		 * only if CPU is enabled (bit 1 of status register is set).
814     		 */
815     		if (_INB(port) & 0x01) {
816     			tmp = hw->regs[0] & ~0x04;
817     			_OUTB(port, tmp);
818     			tmp |= 0x04;
819     			_OUTB(port, tmp);
820     			hw->regs[0] = tmp;
821     		}
822     		else return -EIO;
823     		break;
824     
825     	case SDLA_S503:
826     		if (_INB(port) & 0x04) {
827     			tmp = hw->regs[0] & ~0x08;
828     			_OUTB(port, tmp);
829     			tmp |= 0x08;
830     			_OUTB(port, tmp);
831     			hw->regs[0] = tmp;
832     		}
833     		break;
834     
835     	case SDLA_S502A:
836     	case SDLA_S507:
837     	case SDLA_S508:
838     	break;
839     
840     	default:
841     		return -EINVAL;
842     	}
843     	return 0;
844     }
845     
846     
847     /*============================================================================
848      * Acknowledge S514 hardware interrupt.
849      */
850     
851     #if defined(LINUX_2_1) || defined(LINUX_2_4)
852     EXPORT_SYMBOL(S514_intack);
853     #endif
854     
855     void S514_intack (sdlahw_t* hw, u32 int_status)
856     {
857     #if defined(LINUX_2_1) || defined(LINUX_2_4)
858             pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
859     #else
860     	pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
861                     PCI_INT_STATUS, int_status);
862     #endif
863     }
864     
865     
866     /*============================================================================
867      * Read the S514 hardware interrupt status.
868      */
869     
870     #if defined(LINUX_2_1) || defined(LINUX_2_4)
871     EXPORT_SYMBOL(read_S514_int_stat);
872     #endif
873     
874     void read_S514_int_stat (sdlahw_t* hw, u32* int_status)
875     {
876     #if defined(LINUX_2_1) || defined(LINUX_2_4)
877     	pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status);
878     #else
879             pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_STATUS,
880     		int_status);
881     #endif
882     }
883     
884     
885     /*============================================================================
886      * Generate an interrupt to adapter's CPU.
887      */
888     
889     #if defined(LINUX_2_1) || defined(LINUX_2_4)
890     EXPORT_SYMBOL(sdla_intr);
891     #endif
892     
893     int sdla_intr (sdlahw_t* hw)
894     {
895     	unsigned port = hw->port;
896     
897     	switch (hw->type) {
898     	case SDLA_S502A:
899     		if (!(_INB(port) & 0x40)) {
900     			_OUTB(port, 0x10);		/* issue NMI to CPU */
901     			hw->regs[0] = 0x10;
902     		}
903     		else return -EIO;
904     		break;
905     
906     	case SDLA_S507:
907     		if ((_INB(port) & 0x06) == 0x06) {
908     			_OUTB(port + 3, 0);
909     		}
910     		else return -EIO;
911     		break;
912     
913     	case SDLA_S508:
914     		if (_INB(port + 1) & 0x02) {
915     			_OUTB(port, 0x08);
916     		}
917     		else return -EIO;
918     		break;
919     
920     	case SDLA_S502E:
921     	case SDLA_S503:
922     	default:
923     		return -EINVAL;
924     	}
925     	return 0;
926     }
927     
928     /*============================================================================
929      * Execute Adapter Command.
930      * o Set exec flag.
931      * o Busy-wait until flag is reset.
932      * o Return number of loops made, or 0 if command timed out.
933      */
934     
935     #if defined(LINUX_2_1) || defined(LINUX_2_4)
936     EXPORT_SYMBOL(sdla_exec);
937     #endif
938     
939     int sdla_exec (void* opflag)
940     {
941     	volatile unsigned char* flag = opflag;
942     	unsigned long tstop;
943     	int nloops;
944     
945     	if(readb(flag) != 0x00) {
946     		printk(KERN_INFO
947     			"WANPIPE: opp flag set on entry to sdla_exec\n");
948     		return 0;
949     	}
950     	
951     	writeb(0x01, flag);
952     
953     	tstop = SYSTEM_TICK + EXEC_TIMEOUT;
954     
955     	for (nloops = 1; (readb(flag) == 0x01); ++ nloops) {
956     		unsigned delay = exec_idle;
957     		while (-- delay);			/* delay */
958     		if (SYSTEM_TICK > tstop) return 0;	/* time is up! */
959     	}
960     	return nloops;
961     }
962     
963     /*============================================================================
964      * Read absolute adapter memory.
965      * Transfer data from adapter's memory to data buffer.
966      *
967      * Note:
968      * Care should be taken when crossing dual-port memory window boundary.
969      * This function is not atomic, so caller must disable interrupt if
970      * interrupt routines are accessing adapter shared memory.
971      */
972     
973     #if defined(LINUX_2_1) || defined(LINUX_2_4)
974     EXPORT_SYMBOL(sdla_peek);
975     #endif
976     
977     int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
978     {
979     
980     	if (addr + len > hw->memory)	/* verify arguments */
981     		return -EINVAL;
982     
983             if(hw->type == SDLA_S514) {	/* copy data for the S514 adapter */
984                     peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
985                     return 0;
986     	}
987     
988             else {				/* copy data for the S508 adapter */
989     	        unsigned long oldvec = hw->vector;
990             	unsigned winsize = hw->dpmsize;
991     	        unsigned curpos, curlen;   /* current offset and block size */
992             	unsigned long curvec;      /* current DPM window vector */
993     	        int err = 0;
994     
995                     while (len && !err) {
996                             curpos = addr % winsize;  /* current window offset */
997                             curvec = addr - curpos;   /* current window vector */
998                             curlen = (len > (winsize - curpos)) ?
999     				(winsize - curpos) : len;
1000                             /* Relocate window and copy block of data */
1001                             err = sdla_mapmem(hw, curvec);
1002                             peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
1003     				curlen);
1004                             addr       += curlen;
1005                             (char*)buf += curlen;
1006                             len        -= curlen;
1007                     }
1008     
1009                     /* Restore DPM window position */
1010                     sdla_mapmem(hw, oldvec);
1011                     return err;
1012             }
1013     }
1014     
1015     
1016     /*============================================================================
1017      * Read data from adapter's memory to a data buffer in 4-byte chunks.
1018      * Note that we ensure that the SDLA memory address is on a 4-byte boundary
1019      * before we begin moving the data in 4-byte chunks.
1020     */
1021     
1022     static void peek_by_4 (unsigned long src, void* buf, unsigned len)
1023     {
1024     
1025             /* byte copy data until we get to a 4-byte boundary */
1026             while (len && (src & 0x03)) {
1027                     *(char *)buf ++ = readb(src ++);
1028                     len --;
1029             }
1030     
1031             /* copy data in 4-byte chunks */
1032             while (len >= 4) {
1033                     *(unsigned long *)buf = readl(src);
1034                     buf += 4;
1035                     src += 4;
1036                     len -= 4;
1037             }
1038     
1039             /* byte copy any remaining data */
1040             while (len) {
1041                     *(char *)buf ++ = readb(src ++);
1042                     len --;
1043             }
1044     }
1045     
1046     
1047     /*============================================================================
1048      * Write Absolute Adapter Memory.
1049      * Transfer data from data buffer to adapter's memory.
1050      *
1051      * Note:
1052      * Care should be taken when crossing dual-port memory window boundary.
1053      * This function is not atomic, so caller must disable interrupt if
1054      * interrupt routines are accessing adapter shared memory.
1055      */
1056     
1057     #if defined(LINUX_2_1) || defined(LINUX_2_4)
1058     EXPORT_SYMBOL(sdla_poke);
1059     #endif
1060      
1061     int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
1062     {
1063     
1064     	if (addr + len > hw->memory)	/* verify arguments */
1065     		return -EINVAL;
1066        
1067             if(hw->type == SDLA_S514) {	/* copy data for the S514 adapter */
1068                     poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len);
1069                     return 0;
1070     	}
1071     	
1072     	else {				/* copy data for the S508 adapter */
1073         		unsigned long oldvec = hw->vector;
1074     	        unsigned winsize = hw->dpmsize;
1075             	unsigned curpos, curlen;     /* current offset and block size */
1076             	unsigned long curvec;        /* current DPM window vector */
1077             	int err = 0;
1078     
1079     		while (len && !err) {
1080                             curpos = addr % winsize;    /* current window offset */
1081                             curvec = addr - curpos;     /* current window vector */
1082                             curlen = (len > (winsize - curpos)) ?
1083     				(winsize - curpos) : len;
1084                             /* Relocate window and copy block of data */
1085                             sdla_mapmem(hw, curvec);
1086                             poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
1087     				curlen);
1088     	                addr       += curlen;
1089                             (char*)buf += curlen;
1090                             len        -= curlen;
1091                     }
1092     
1093                     /* Restore DPM window position */
1094                     sdla_mapmem(hw, oldvec);
1095                     return err;
1096             }
1097     }
1098     
1099     
1100     /*============================================================================
1101      * Write from a data buffer to adapter's memory in 4-byte chunks.
1102      * Note that we ensure that the SDLA memory address is on a 4-byte boundary
1103      * before we begin moving the data in 4-byte chunks.
1104     */
1105     
1106     static void poke_by_4 (unsigned long dest, void* buf, unsigned len)
1107     {
1108     
1109             /* byte copy data until we get to a 4-byte boundary */
1110             while (len && (dest & 0x03)) {
1111                     writeb (*(char *)buf ++, dest ++);
1112                     len --;
1113             }
1114     
1115             /* copy data in 4-byte chunks */
1116             while (len >= 4) {
1117                     writel (*(unsigned long *)buf, dest);
1118                     dest += 4;
1119                     buf += 4;
1120                     len -= 4;
1121             }
1122     
1123             /* byte copy any remaining data */
1124             while (len) {
1125                     writeb (*(char *)buf ++ , dest ++);
1126                     len --;
1127             }
1128     }
1129     
1130     
1131     #ifdef	DONT_COMPIPLE_THIS
1132     #endif	/* DONT_COMPIPLE_THIS */
1133     
1134     /****** Hardware-Specific Functions *****************************************/
1135     
1136     /*============================================================================
1137      * Detect adapter type.
1138      * o if adapter type is specified then call detection routine for that adapter
1139      *   type.  Otherwise call detection routines for every adapter types until
1140      *   adapter is detected.
1141      *
1142      * Notes:
1143      * 1) Detection tests are destructive! Adapter will be left in shutdown state
1144      *    after the test.
1145      */
1146     static int sdla_detect (sdlahw_t* hw)
1147     {
1148     	unsigned port = hw->port;
1149     	int err = 0;
1150     
1151     	if (!port && (hw->type != SDLA_S514))
1152     		return -EFAULT;
1153     
1154         	switch (hw->type) {
1155     	case SDLA_S502A:
1156     		if (!detect_s502a(port)) err = -ENODEV;
1157     		break;
1158     
1159     	case SDLA_S502E:
1160     		if (!detect_s502e(port)) err = -ENODEV;
1161     		break;
1162     
1163     	case SDLA_S503:
1164     		if (!detect_s503(port)) err = -ENODEV;
1165     		break;
1166     
1167     	case SDLA_S507:
1168     		if (!detect_s507(port)) err = -ENODEV;
1169     		break;
1170     
1171     	case SDLA_S508:
1172     		if (!detect_s508(port)) err = -ENODEV;
1173     		break;
1174     
1175     	case SDLA_S514:
1176                     if (!detect_s514(hw)) err = -ENODEV;
1177     		break;
1178     
1179     	default:
1180     		if (detect_s502a(port))
1181     			hw->type = SDLA_S502A;
1182     		else if (detect_s502e(port))
1183     			hw->type = SDLA_S502E;
1184     		else if (detect_s503(port))
1185     			hw->type = SDLA_S503;
1186     		else if (detect_s507(port))
1187     			hw->type = SDLA_S507;
1188     		else if (detect_s508(port))
1189     			hw->type = SDLA_S508;
1190     		else err = -ENODEV;
1191     	}
1192     	return err;
1193     }
1194     
1195     /*============================================================================
1196      * Autoselect memory region. 
1197      * o try all available DMP address options from the top down until success.
1198      */
1199     static int sdla_autodpm (sdlahw_t* hw)
1200     {
1201     	int i, err = -EINVAL;
1202     	unsigned* opt;
1203     
1204     	switch (hw->type) {
1205     	case SDLA_S502A:
1206     		opt = s502a_dpmbase_options;
1207     		break;
1208     
1209     	case SDLA_S502E:
1210     	case SDLA_S503:
1211     	case SDLA_S508:
1212     		opt = s508_dpmbase_options;
1213     		break;
1214     
1215     	case SDLA_S507:
1216     		opt = s507_dpmbase_options;
1217     		break;
1218     
1219     	default:
1220     		return -EINVAL;
1221     	}
1222     
1223     	/* Start testing from 8th position, address
1224              * 0xC8000 from the 508 address table. 
1225              * We don't want to test A**** addresses, since
1226              * they are usually used for Video */
1227     	for (i = 8; i <= opt[0] && err; i++) {
1228     		hw->dpmbase = phys_to_virt(opt[i]);
1229     		err = sdla_setdpm(hw);
1230     	}
1231     	return err;
1232     }
1233     
1234     /*============================================================================
1235      * Set up adapter dual-port memory window. 
1236      * o shut down adapter
1237      * o make sure that no physical memory exists in this region, i.e entire
1238      *   region reads 0xFF and is not writable when adapter is shut down.
1239      * o initialize adapter hardware
1240      * o make sure that region is usable with SDLA card, i.e. we can write to it
1241      *   when adapter is configured.
1242      */
1243     static int sdla_setdpm (sdlahw_t* hw)
1244     {
1245     	int err;
1246     
1247     	/* Shut down card and verify memory region */
1248     	sdla_down(hw);
1249     	if (check_memregion(hw->dpmbase, hw->dpmsize))
1250     		return -EINVAL;
1251     
1252     	/* Initialize adapter and test on-board memory segment by segment.
1253     	 * If memory size appears to be less than shared memory window size,
1254     	 * assume that memory region is unusable.
1255     	 */
1256     	err = sdla_init(hw);
1257     	if (err) return err;
1258     
1259     	if (sdla_memtest(hw) < hw->dpmsize) {	/* less than window size */
1260     		sdla_down(hw);
1261     		return -EIO;
1262     	}
1263     	sdla_mapmem(hw, 0L);	/* set window vector at bottom */
1264     	return 0;
1265     }
1266     
1267     /*============================================================================
1268      * Load adapter from the memory image of the SDLA firmware module. 
1269      * o verify firmware integrity and compatibility
1270      * o start adapter up
1271      */
1272     static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len)
1273     {
1274     
1275     	int i;
1276     
1277     	/* Verify firmware signature */
1278     	if (strcmp(sfm->signature, SFM_SIGNATURE)) {
1279     		printk(KERN_INFO "%s: not SDLA firmware!\n",
1280     			modname);
1281     		return -EINVAL;
1282     	}
1283     
1284     	/* Verify firmware module format version */
1285     	if (sfm->version != SFM_VERSION) {
1286     		printk(KERN_INFO
1287     			"%s: firmware format %u rejected! Expecting %u.\n",
1288     			modname, sfm->version, SFM_VERSION);
1289     		return -EINVAL;
1290     	}
1291     
1292     	/* Verify firmware module length and checksum */
1293     	if ((len - offsetof(sfm_t, image) != sfm->info.codesize) ||
1294     		(checksum((void*)&sfm->info,
1295     		sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) {
1296     		printk(KERN_INFO "%s: firmware corrupted!\n", modname);
1297     		return -EINVAL;
1298     	}
1299     
1300     	/* Announce */
1301     	printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname,
1302     		(sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware",
1303     		sfm->info.codeid);
1304     
1305     	if(hw->type == SDLA_S514)
1306     		printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n",
1307     			modname, hw->S514_cpu_no[0]);
1308     
1309     	/* Scan through the list of compatible adapters and make sure our
1310     	 * adapter type is listed.
1311     	 */
1312     	for (i = 0;
1313     	     (i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type);
1314     	     ++i);
1315     	
1316     	if (i == SFM_MAX_SDLA) {
1317     		printk(KERN_INFO "%s: firmware is not compatible with S%u!\n",
1318     			modname, hw->type);
1319     		return -EINVAL;
1320     	}
1321     
1322     
1323     	/* Make sure there is enough on-board memory */
1324     	if (hw->memory < sfm->info.memsize) {
1325     		printk(KERN_INFO
1326     			"%s: firmware needs %lu bytes of on-board memory!\n",
1327     			modname, sfm->info.memsize);
1328     		return -EINVAL;
1329     	}
1330     
1331     	/* Move code onto adapter */
1332     	if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) {
1333     		printk(KERN_INFO "%s: failed to load code segment!\n",
1334     			modname);
1335     		return -EIO;
1336     	}
1337     
1338     	/* Prepare boot-time configuration data and kick-off CPU */
1339     	sdla_bootcfg(hw, &sfm->info);
1340     	if (sdla_start(hw, sfm->info.startoffs)) {
1341     		printk(KERN_INFO "%s: Damn... Adapter won't start!\n",
1342     			modname);
1343     		return -EIO;
1344     	}
1345     
1346     	/* position DPM window over the mailbox and enable interrupts */
1347             if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) {
1348     		printk(KERN_INFO "%s: adapter hardware failure!\n",
1349     			modname);
1350     		return -EIO;
1351     	}
1352     	hw->fwid = sfm->info.codeid;		/* set firmware ID */
1353     	return 0;
1354     }
1355     
1356     /*============================================================================
1357      * Initialize SDLA hardware: setup memory window, IRQ, etc.
1358      */
1359     static int sdla_init (sdlahw_t* hw)
1360     {
1361     	int i;
1362     
1363     	for (i = 0; i < SDLA_MAXIORANGE; ++i)
1364     		hw->regs[i] = 0;
1365     
1366     	switch (hw->type) {
1367     	case SDLA_S502A: return init_s502a(hw);
1368     	case SDLA_S502E: return init_s502e(hw);
1369     	case SDLA_S503:  return init_s503(hw);
1370     	case SDLA_S507:  return init_s507(hw);
1371     	case SDLA_S508:  return init_s508(hw);
1372     	}
1373     	return -EINVAL;
1374     }
1375     
1376     /*============================================================================
1377      * Test adapter on-board memory.
1378      * o slide DPM window from the bottom up and test adapter memory segment by
1379      *   segment.
1380      * Return adapter memory size.
1381      */
1382     static unsigned long sdla_memtest (sdlahw_t* hw)
1383     {
1384     	unsigned long memsize;
1385     	unsigned winsize;
1386     
1387     	for (memsize = 0, winsize = hw->dpmsize;
1388     	     !sdla_mapmem(hw, memsize) &&
1389     		(test_memregion(hw->dpmbase, winsize) == winsize)
1390     	     ;
1391     	     memsize += winsize)
1392     	;
1393     	hw->memory = memsize;
1394     	return memsize;
1395     }
1396     
1397     /*============================================================================
1398      * Prepare boot-time firmware configuration data.
1399      * o position DPM window
1400      * o initialize configuration data area
1401      */
1402     static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo)
1403     {
1404     	unsigned char* data;
1405     
1406     	if (!sfminfo->datasize) return 0;	/* nothing to do */
1407     
1408     	if (sdla_mapmem(hw, sfminfo->dataoffs) != 0)
1409     		return -EIO;
1410     
1411     	if(hw->type == SDLA_S514)
1412                     data = (void*)(hw->dpmbase + sfminfo->dataoffs);
1413             else
1414                     data = (void*)((u8 *)hw->dpmbase +
1415                             (sfminfo->dataoffs - hw->vector));
1416     
1417     	memset_io (data, 0, sfminfo->datasize);
1418     
1419     	writeb (make_config_byte(hw), &data[0x00]);
1420     
1421     	switch (sfminfo->codeid) {
1422     	case SFID_X25_502:
1423     	case SFID_X25_508:
1424                     writeb (3, &data[0x01]);        /* T1 timer */
1425                     writeb (10, &data[0x03]);       /* N2 */
1426                     writeb (7, &data[0x06]);        /* HDLC window size */
1427                     writeb (1, &data[0x0B]);        /* DTE */
1428                     writeb (2, &data[0x0C]);        /* X.25 packet window size */
1429                     writew (128, &data[0x0D]);	/* default X.25 data size */
1430                     writew (128, &data[0x0F]);	/* maximum X.25 data size */
1431     		break;
1432     	}
1433     	return 0;
1434     }
1435     
1436     /*============================================================================
1437      * Prepare configuration byte identifying adapter type and CPU clock rate.
1438      */
1439     static unsigned char make_config_byte (sdlahw_t* hw)
1440     {
1441     	unsigned char byte = 0;
1442     
1443     	switch (hw->pclk) {
1444     		case 5000:  byte = 0x01; break;
1445     		case 7200:  byte = 0x02; break;
1446     		case 8000:  byte = 0x03; break;
1447     		case 10000: byte = 0x04; break;
1448     		case 16000: byte = 0x05; break;
1449     	}
1450     
1451     	switch (hw->type) {
1452     		case SDLA_S502E: byte |= 0x80; break;
1453     		case SDLA_S503:  byte |= 0x40; break;
1454     	}
1455     	return byte;
1456     }
1457     
1458     /*============================================================================
1459      * Start adapter's CPU.
1460      * o calculate a pointer to adapter's cold boot entry point
1461      * o position DPM window
1462      * o place boot instruction (jp addr) at cold boot entry point
1463      * o start CPU
1464      */
1465     static int sdla_start (sdlahw_t* hw, unsigned addr)
1466     {
1467     	unsigned port = hw->port;
1468     	unsigned char *bootp;
1469     	int err, tmp, i;
1470     
1471     	if (!port && (hw->type != SDLA_S514)) return -EFAULT;
1472     
1473      	switch (hw->type) {
1474     	case SDLA_S502A:
1475     		bootp = hw->dpmbase;
1476     		bootp += 0x66;
1477     		break;
1478     
1479     	case SDLA_S502E:
1480     	case SDLA_S503:
1481     	case SDLA_S507:
1482     	case SDLA_S508:
1483     	case SDLA_S514:
1484     		bootp = hw->dpmbase;
1485     		break;
1486     
1487     	default:
1488     		return -EINVAL;
1489     	}
1490     
1491     	err = sdla_mapmem(hw, 0);
1492     	if (err) return err;
1493     
1494           	writeb (0xC3, bootp);   /* Z80: 'jp' opcode */
1495     	bootp ++;
1496     	writew (addr, bootp);
1497     
1498     	switch (hw->type) {
1499     	case SDLA_S502A:
1500     		_OUTB(port, 0x10);		/* issue NMI to CPU */
1501     		hw->regs[0] = 0x10;
1502     		break;
1503     
1504     	case SDLA_S502E:
1505     		_OUTB(port + 3, 0x01);		/* start CPU */
1506     		hw->regs[3] = 0x01;
1507     		for (i = 0; i < SDLA_IODELAY; ++i);
1508     		if (_INB(port) & 0x01) {	/* verify */
1509     			/*
1510     			 * Enabling CPU changes functionality of the
1511     			 * control register, so we have to reset its
1512     			 * mirror.
1513     			 */
1514     			_OUTB(port, 0);		/* disable interrupts */
1515     			hw->regs[0] = 0;
1516     		}
1517     		else return -EIO;
1518     		break;
1519     
1520     	case SDLA_S503:
1521     		tmp = hw->regs[0] | 0x09;	/* set bits 0 and 3 */
1522     		_OUTB(port, tmp);
1523     		hw->regs[0] = tmp;		/* update mirror */
1524     		for (i = 0; i < SDLA_IODELAY; ++i);
1525     		if (!(_INB(port) & 0x01))	/* verify */
1526     			return -EIO;
1527     		break;
1528     
1529     	case SDLA_S507:
1530     		tmp = hw->regs[0] | 0x02;
1531     		_OUTB(port, tmp);
1532     		hw->regs[0] = tmp;		/* update mirror */
1533     		for (i = 0; i < SDLA_IODELAY; ++i);
1534     		if (!(_INB(port) & 0x04))	/* verify */
1535     			return -EIO;
1536     		break;
1537     
1538     	case SDLA_S508:
1539     		tmp = hw->regs[0] | 0x02;
1540     		_OUTB(port, tmp);
1541     		hw->regs[0] = tmp;	/* update mirror */
1542     		for (i = 0; i < SDLA_IODELAY; ++i);
1543     		if (!(_INB(port + 1) & 0x02))	/* verify */
1544     			return -EIO;
1545     		break;
1546     
1547     	case SDLA_S514:
1548     		writeb (S514_CPU_START, hw->vector);
1549     		break;
1550     
1551     	default:
1552     		return -EINVAL;
1553     	}
1554     	return 0;
1555     }
1556     
1557     /*============================================================================
1558      * Initialize S502A adapter.
1559      */
1560     static int init_s502a (sdlahw_t* hw)
1561     {
1562     	unsigned port = hw->port;
1563     	int tmp, i;
1564     
1565     	if (!detect_s502a(port))
1566     		return -ENODEV;
1567     
1568     	hw->regs[0] = 0x08;
1569     	hw->regs[1] = 0xFF;
1570     
1571     	/* Verify configuration options */
1572     	i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase));
1573     	if (i == 0)
1574     		return -EINVAL;
1575     
1576     	tmp = s502a_hmcr[i - 1];
1577     	switch (hw->dpmsize) {
1578     	case 0x2000:
1579     		tmp |= 0x01;
1580     		break;
1581     
1582     	case 0x10000L:
1583     		break;
1584     
1585     	default:
1586     		return -EINVAL;
1587     	}
1588     
1589     	/* Setup dual-port memory window (this also enables memory access) */
1590     	_OUTB(port + 1, tmp);
1591     	hw->regs[1] = tmp;
1592     	hw->regs[0] = 0x08;
1593     	return 0;
1594     }
1595     
1596     /*============================================================================
1597      * Initialize S502E adapter.
1598      */
1599     static int init_s502e (sdlahw_t* hw)
1600     {
1601     	unsigned port = hw->port;
1602     	int tmp, i;
1603     
1604     	if (!detect_s502e(port))
1605     		return -ENODEV;
1606     
1607     	/* Verify configuration options */
1608     	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
1609     	if (i == 0)
1610     		return -EINVAL;
1611     
1612     	tmp = s502e_hmcr[i - 1];
1613     	switch (hw->dpmsize) {
1614     	case 0x2000:
1615     		tmp |= 0x01;
1616     		break;
1617     
1618     	case 0x10000L:
1619     		break;
1620     
1621     	default:
1622     		return -EINVAL;
1623     	}
1624     
1625     	/* Setup dual-port memory window */
1626     	_OUTB(port + 1, tmp);
1627     	hw->regs[1] = tmp;
1628     
1629     	/* Enable memory access */
1630     	_OUTB(port, 0x02);
1631     	hw->regs[0] = 0x02;
1632     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1633     	return (_INB(port) & 0x02) ? 0 : -EIO;
1634     }
1635     
1636     /*============================================================================
1637      * Initialize S503 adapter.
1638      * ---------------------------------------------------------------------------
1639      */
1640     static int init_s503 (sdlahw_t* hw)
1641     {
1642     	unsigned port = hw->port;
1643     	int tmp, i;
1644     
1645     	if (!detect_s503(port))
1646     		return -ENODEV;
1647     
1648     	/* Verify configuration options */
1649     	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
1650     	if (i == 0)
1651     		return -EINVAL;
1652     
1653     	tmp = s502e_hmcr[i - 1];
1654     	switch (hw->dpmsize) {
1655     	case 0x2000:
1656     		tmp |= 0x01;
1657     		break;
1658     
1659     	case 0x10000L:
1660     		break;
1661     
1662     	default:
1663     		return -EINVAL;
1664     	}
1665     
1666     	/* Setup dual-port memory window */
1667     	_OUTB(port + 1, tmp);
1668     	hw->regs[1] = tmp;
1669     
1670     	/* Enable memory access */
1671     	_OUTB(port, 0x02);
1672     	hw->regs[0] = 0x02;	/* update mirror */
1673     	return 0;
1674     }
1675     
1676     /*============================================================================
1677      * Initialize S507 adapter.
1678      */
1679     static int init_s507 (sdlahw_t* hw)
1680     {
1681     	unsigned port = hw->port;
1682     	int tmp, i;
1683     
1684     	if (!detect_s507(port))
1685     		return -ENODEV;
1686     
1687     	/* Verify configuration options */
1688     	i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase));
1689     	if (i == 0)
1690     		return -EINVAL;
1691     
1692     	tmp = s507_hmcr[i - 1];
1693     	switch (hw->dpmsize) {
1694     	case 0x2000:
1695     		tmp |= 0x01;
1696     		break;
1697     
1698     	case 0x10000L:
1699     		break;
1700     
1701     	default:
1702     		return -EINVAL;
1703     	}
1704     
1705     	/* Enable adapter's logic */
1706     	_OUTB(port, 0x01);
1707     	hw->regs[0] = 0x01;
1708     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1709     	if (!(_INB(port) & 0x20))
1710     		return -EIO;
1711     
1712     	/* Setup dual-port memory window */
1713     	_OUTB(port + 1, tmp);
1714     	hw->regs[1] = tmp;
1715     
1716     	/* Enable memory access */
1717     	tmp = hw->regs[0] | 0x04;
1718     	if (hw->irq) {
1719     		i = get_option_index(s508_irq_options, hw->irq);
1720     		if (i) tmp |= s507_irqmask[i - 1];
1721     	}
1722     	_OUTB(port, tmp);
1723     	hw->regs[0] = tmp;		/* update mirror */
1724     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1725     	return (_INB(port) & 0x08) ? 0 : -EIO;
1726     }
1727     
1728     /*============================================================================
1729      * Initialize S508 adapter.
1730      */
1731     static int init_s508 (sdlahw_t* hw)
1732     {
1733     	unsigned port = hw->port;
1734     	int tmp, i;
1735     
1736     	if (!detect_s508(port))
1737     		return -ENODEV;
1738     
1739     	/* Verify configuration options */
1740     	i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase));
1741     	if (i == 0)
1742     		return -EINVAL;
1743     
1744     	/* Setup memory configuration */
1745     	tmp = s508_hmcr[i - 1];
1746     	_OUTB(port + 1, tmp);
1747     	hw->regs[1] = tmp;
1748     
1749     	/* Enable memory access */
1750     	_OUTB(port, 0x04);
1751     	hw->regs[0] = 0x04;		/* update mirror */
1752     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1753     	return (_INB(port + 1) & 0x04) ? 0 : -EIO;
1754     }
1755     
1756     /*============================================================================
1757      * Detect S502A adapter.
1758      *	Following tests are used to detect S502A adapter:
1759      *	1. All registers other than status (BASE) should read 0xFF
1760      *	2. After writing 00001000b to control register, status register should
1761      *	   read 01000000b.
1762      *	3. After writing 0 to control register, status register should still
1763      *	   read  01000000b.
1764      *	4. After writing 00000100b to control register, status register should
1765      *	   read 01000100b.
1766      *	Return 1 if detected o.k. or 0 if failed.
1767      *	Note:	This test is destructive! Adapter will be left in shutdown
1768      *		state after the test.
1769      */
1770     static int detect_s502a (int port)
1771     {
1772     	int i, j;
1773     
1774     	if (!get_option_index(s502_port_options, port))
1775     		return 0;
1776     	
1777     	for (j = 1; j < SDLA_MAXIORANGE; ++j) {
1778     		if (_INB(port + j) != 0xFF)
1779     			return 0;
1780     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1781     	}
1782     
1783     	_OUTB(port, 0x08);			/* halt CPU */
1784     	_OUTB(port, 0x08);
1785     	_OUTB(port, 0x08);
1786     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1787     	if (_INB(port) != 0x40)
1788     		return 0;
1789     	_OUTB(port, 0x00);
1790     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1791     	if (_INB(port) != 0x40)
1792     		return 0;
1793     	_OUTB(port, 0x04);
1794     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1795     	if (_INB(port) != 0x44)
1796     		return 0;
1797     
1798     	/* Reset adapter */
1799     	_OUTB(port, 0x08);
1800     	_OUTB(port, 0x08);
1801     	_OUTB(port, 0x08);
1802     	_OUTB(port + 1, 0xFF);
1803     	return 1;
1804     }
1805     
1806     /*============================================================================
1807      * Detect S502E adapter.
1808      *	Following tests are used to verify adapter presence:
1809      *	1. All registers other than status (BASE) should read 0xFF.
1810      *	2. After writing 0 to CPU control register (BASE+3), status register
1811      *	   (BASE) should read 11111000b.
1812      *	3. After writing 00000100b to port BASE (set bit 2), status register
1813      *	   (BASE) should read 11111100b.
1814      *	Return 1 if detected o.k. or 0 if failed.
1815      *	Note:	This test is destructive! Adapter will be left in shutdown
1816      *		state after the test.
1817      */
1818     static int detect_s502e (int port)
1819     {
1820     	int i, j;
1821     
1822     	if (!get_option_index(s502_port_options, port))
1823     		return 0;
1824     	for (j = 1; j < SDLA_MAXIORANGE; ++j) {
1825     		if (_INB(port + j) != 0xFF)
1826     			return 0;
1827     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1828     	}
1829     
1830     	_OUTB(port + 3, 0);			/* CPU control reg. */
1831     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1832     	if (_INB(port) != 0xF8)			/* read status */
1833     		return 0;
1834     	_OUTB(port, 0x04);			/* set bit 2 */
1835     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1836     	if (_INB(port) != 0xFC)			/* verify */
1837     		return 0;
1838     
1839     	/* Reset adapter */
1840     	_OUTB(port, 0);
1841     	return 1;
1842     }
1843     
1844     /*============================================================================
1845      * Detect s503 adapter.
1846      *	Following tests are used to verify adapter presence:
1847      *	1. All registers other than status (BASE) should read 0xFF.
1848      *	2. After writing 0 to control register (BASE), status register (BASE)
1849      *	   should read 11110000b.
1850      *	3. After writing 00000100b (set bit 2) to control register (BASE),
1851      *	   status register should read 11110010b.
1852      *	Return 1 if detected o.k. or 0 if failed.
1853      *	Note:	This test is destructive! Adapter will be left in shutdown
1854      *		state after the test.
1855      */
1856     static int detect_s503 (int port)
1857     {
1858     	int i, j;
1859     
1860     	if (!get_option_index(s503_port_options, port))
1861     		return 0;
1862     	for (j = 1; j < SDLA_MAXIORANGE; ++j) {
1863     		if (_INB(port + j) != 0xFF)
1864     			return 0;
1865     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1866     	}
1867     
1868     	_OUTB(port, 0);				/* reset control reg.*/
1869     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1870     	if (_INB(port) != 0xF0)			/* read status */
1871     		return 0;
1872     	_OUTB(port, 0x04);			/* set bit 2 */
1873     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1874     	if (_INB(port) != 0xF2)			/* verify */
1875     		return 0;
1876     
1877     	/* Reset adapter */
1878     	_OUTB(port, 0);
1879     	return 1;
1880     }
1881     
1882     /*============================================================================
1883      * Detect s507 adapter.
1884      *	Following tests are used to detect s507 adapter:
1885      *	1. All ports should read the same value.
1886      *	2. After writing 0x00 to control register, status register should read
1887      *	   ?011000?b.
1888      *	3. After writing 0x01 to control register, status register should read
1889      *	   ?011001?b.
1890      *	Return 1 if detected o.k. or 0 if failed.
1891      *	Note:	This test is destructive! Adapter will be left in shutdown
1892      *		state after the test.
1893      */
1894     static int detect_s507 (int port)
1895     {
1896     	int tmp, i, j;
1897     
1898     	if (!get_option_index(s508_port_options, port))
1899     		return 0;
1900     	tmp = _INB(port);
1901     	for (j = 1; j < S507_IORANGE; ++j) {
1902     		if (_INB(port + j) != tmp)
1903     			return 0;
1904     		for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1905     	}
1906     
1907     	_OUTB(port, 0x00);
1908     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1909     	if ((_INB(port) & 0x7E) != 0x30)
1910     		return 0;
1911     	_OUTB(port, 0x01);
1912     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1913     	if ((_INB(port) & 0x7E) != 0x32)
1914     		return 0;
1915     
1916     	/* Reset adapter */
1917     	_OUTB(port, 0x00);
1918     	return 1;
1919     }
1920     
1921     /*============================================================================
1922      * Detect s508 adapter.
1923      *	Following tests are used to detect s508 adapter:
1924      *	1. After writing 0x00 to control register, status register should read
1925      *	   ??000000b.
1926      *	2. After writing 0x10 to control register, status register should read
1927      *	   ??010000b
1928      *	Return 1 if detected o.k. or 0 if failed.
1929      *	Note:	This test is destructive! Adapter will be left in shutdown
1930      *		state after the test.
1931      */
1932     static int detect_s508 (int port)
1933     {
1934     	int i;
1935     
1936     	if (!get_option_index(s508_port_options, port))
1937     		return 0;
1938     	_OUTB(port, 0x00);
1939     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1940     	if ((_INB(port + 1) & 0x3F) != 0x00)
1941     		return 0;
1942     	_OUTB(port, 0x10);
1943     	for (i = 0; i < SDLA_IODELAY; ++i);	/* delay */
1944     	if ((_INB(port + 1) & 0x3F) != 0x10)
1945     		return 0;
1946     
1947     	/* Reset adapter */
1948     	_OUTB(port, 0x00);
1949     	return 1;
1950     }
1951     
1952     /*============================================================================
1953      * Detect s514 PCI adapter.
1954      *      Return 1 if detected o.k. or 0 if failed.
1955      *      Note:   This test is destructive! Adapter will be left in shutdown
1956      *              state after the test.
1957      */
1958     static int detect_s514 (sdlahw_t* hw)
1959     {
1960     	unsigned char CPU_no, slot_no, auto_slot_cfg;
1961     	int number_S514_cards = 0;
1962     	u32 S514_mem_base_addr = 0;
1963     	u32 ut_u32;
1964     
1965     #if defined(LINUX_2_1) || defined(LINUX_2_4)
1966     	struct pci_dev *pci_dev;
1967     #else
1968     	u8 ut_u8;
1969     #endif
1970     
1971     
1972     #ifdef CONFIG_PCI
1973     #if defined(LINUX_2_1) || defined(LINUX_2_4)
1974             if(!pci_present())
1975     #else
1976     	if(!pcibios_present())
1977     #endif
1978             {
1979                     printk(KERN_INFO "%s: PCI BIOS not present!\n", modname);
1980                     return 0;
1981             }
1982     #else
1983             printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname);
1984             return 0;
1985     #endif
1986     
1987     	/*
1988     	The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the
1989     	slot number defined in 'router.conf' via the 'port' definition.
1990     	*/
1991     	CPU_no = hw->S514_cpu_no[0];
1992     	slot_no = hw->S514_slot_no;
1993     	auto_slot_cfg = hw->auto_pci_cfg;
1994     
1995     	if (auto_slot_cfg){
1996     		printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n",
1997     		modname, CPU_no);
1998     
1999     	}else{
2000     		printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n",
2001     		modname, CPU_no, slot_no);
2002     	}
2003     	
2004     	/* check to see that CPU A or B has been selected in 'router.conf' */
2005     	switch(CPU_no) {
2006     		case S514_CPU_A:
2007     		case S514_CPU_B:
2008     			break;
2009     	
2010     		default:
2011     			printk(KERN_INFO "%s: S514 CPU definition invalid.\n", 
2012     				modname);
2013     			printk(KERN_INFO "Must be 'A' or 'B'\n");
2014     			return 0;
2015     	}
2016     
2017     	number_S514_cards = find_s514_adapter(hw, 0);
2018     	if(!number_S514_cards)
2019     		return 0;
2020     
2021     	/* we are using a single S514 adapter with a slot of 0 so re-read the */	
2022     	/* location of this adapter */
2023     	if((number_S514_cards == 1) && auto_slot_cfg) {	
2024             	number_S514_cards = find_s514_adapter(hw, 1);
2025     		if(!number_S514_cards) {
2026     			printk(KERN_INFO "%s: Error finding PCI card\n",
2027     				modname);
2028     			return 0;
2029     		}
2030     	}
2031     
2032           #if defined(LINUX_2_4)
2033     	pci_dev = hw->pci_dev;
2034     	/* read the physical memory base address */
2035     	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 
2036     		(pci_dev->resource[1].start) :
2037     		(pci_dev->resource[2].start);
2038     	
2039           #elif defined (LINUX_2_1)
2040     	pci_dev = hw->pci_dev;
2041     	/* read the physical memory base address */
2042     	S514_mem_base_addr = (CPU_no == S514_CPU_A) ? 
2043     		(pci_dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK) :
2044     		(pci_dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK);
2045     	
2046           #else
2047     	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
2048     		(CPU_no == S514_CPU_A) ? PCI_MEM_BASE0_DWORD :
2049     		PCI_MEM_BASE1_DWORD, &S514_mem_base_addr);
2050           #endif
2051     
2052     	printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n",
2053     		modname, S514_mem_base_addr);
2054     	if(!S514_mem_base_addr) {
2055     		if(CPU_no == S514_CPU_B)
2056     			printk(KERN_INFO "%s: CPU #B not present on the card\n", 				modname);
2057     		else
2058     			printk(KERN_INFO "%s: No PCI memory allocated to card\n",				modname);
2059     		return 0;
2060     	}
2061     
2062     	/* enable the PCI memory */
2063     #if defined(LINUX_2_1) || defined(LINUX_2_4)
2064     	pci_read_config_dword(pci_dev, 
2065     		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
2066     		&ut_u32);
2067     	pci_write_config_dword(pci_dev,
2068     		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
2069     		(ut_u32 | PCI_MEMORY_ENABLE));
2070     #else
2071             pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func,
2072     		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
2073     		&ut_u32); 
2074             pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func,
2075     		(CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD,
2076     		(ut_u32 | PCI_MEMORY_ENABLE));
2077     #endif
2078     
2079     	/* check the IRQ allocated and enable IRQ usage */
2080     #if defined(LINUX_2_1) || defined(LINUX_2_4)
2081     	if(!(hw->irq = pci_dev->irq)) {
2082     		printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
2083     			modname);
2084                     return 0;
2085     	}
2086     
2087     	/* BUG FIX : Mar 6 2000
2088      	 * On a initial loading of the card, we must check
2089              * and clear PCI interrupt bits, due to a reset
2090              * problem on some other boards.  i.e. An interrupt
2091              * might be pending, even after system bootup, 
2092              * in which case, when starting wanrouter the machine
2093              * would crash. 
2094     	 */
2095     	if (init_pci_slot(hw))
2096     		return 0;
2097     
2098             pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32);
2099             ut_u32 |= (CPU_no == S514_CPU_A) ?
2100                     PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
2101             pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32);
2102     #else
2103     	/* the INTPIN must not be 0 - if it is, then the S514 adapter is not */
2104     	/* configured for IRQ usage */
2105     	pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
2106     		PCI_INT_PIN_BYTE, &ut_u8);
2107             if(!ut_u8) {
2108                     printk(KERN_INFO "%s: invalid setting for INTPIN on S514 card\n", modname);
2109                     printk(KERN_INFO "Please contact your Sangoma representative\n");
2110                     return 0;
2111             }
2112             pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
2113     		PCI_INT_LINE_BYTE, (unsigned char *)&hw->irq);
2114             if(hw->irq == PCI_IRQ_NOT_ALLOCATED) {
2115                     printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n",
2116     			modname);
2117                     return 0;
2118             }
2119     	pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_CONFIG, &ut_u32);
2120     	ut_u32 |= (CPU_no == S514_CPU_A) ?
2121     		PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B;
2122             pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, 
2123     		PCI_INT_CONFIG, ut_u32);
2124     #endif
2125     
2126     	printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n",
2127     		modname, hw->irq);
2128     
2129     	/* map the physical PCI memory to virtual memory */
2130     	(void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
2131     		(unsigned long)MAX_SIZEOF_S514_MEMORY);
2132         	/* map the physical control register memory to virtual memory */
2133     	(void *)hw->vector = ioremap(
2134     		(unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
2135     		(unsigned long)16);
2136          
2137             if(!hw->dpmbase || !hw->vector) {
2138     		printk(KERN_INFO "%s: PCI virtual memory allocation failed\n",
2139     			modname);
2140                     return 0;
2141     	}
2142     
2143     	/* halt the adapter */
2144     	writeb (S514_CPU_HALT, hw->vector);	
2145     
2146     	return 1;
2147     }
2148     
2149     /*============================================================================
2150      * Find the S514 PCI adapter in the PCI bus.
2151      *      Return the number of S514 adapters found (0 if no adapter found).
2152      */
2153     static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card)
2154     {
2155             unsigned char slot_no;
2156             int number_S514_cards = 0;
2157     	char S514_found_in_slot = 0;
2158             u16 PCI_subsys_vendor;
2159     
2160     #if defined(LINUX_2_1) || defined(LINUX_2_4)
2161             struct pci_dev *pci_dev = NULL;
2162     #else
2163             int pci_index;
2164     #endif
2165      
2166            slot_no = hw->S514_slot_no;
2167       
2168     #if defined(LINUX_2_1) || defined(LINUX_2_4)
2169     	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
2170             	!= NULL) {
2171                     
2172     		pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
2173                             &PCI_subsys_vendor);
2174                     
2175     		if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
2176                     	continue;
2177             	
2178     		hw->pci_dev = pci_dev;
2179     		
2180     		if(find_first_S514_card)
2181     			return(1);
2182     		
2183                     number_S514_cards ++;
2184                     
2185     		printk(KERN_INFO
2186     			"%s: S514 card found, slot #%d (devfn 0x%X)\n",
2187                             modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
2188     			pci_dev->devfn);
2189     		
2190     		if (hw->auto_pci_cfg){
2191     			hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK);
2192     			slot_no = hw->S514_slot_no;
2193     			
2194     		}else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){
2195                             S514_found_in_slot = 1;
2196                             break;
2197                     }
2198             }
2199     
2200     #else
2201     	//LINUX VERSION 2.0.X 
2202             for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) {
2203                     if (pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index,
2204                             &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) {
2205                                     break;
2206                     }
2207                     
2208     		pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func,
2209                             PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor);
2210                     
2211     		if (PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
2212                             continue;
2213                     
2214     		if (find_first_S514_card)
2215                             return(1);
2216                	
2217     		number_S514_cards ++;
2218     		
2219                     printk(KERN_INFO "%s: S514 card found, bus #%d, slot #%d\n",
2220                             modname, hw->pci_bus,
2221                             ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK));
2222     
2223     		if (hw->auto_pci_cfg){
2224     			hw->S514_slot_no = ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK)
2225     			slot_no = hw->S514_slot_no;
2226     				
2227     		}else if (((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK) == slot_no) {
2228                             S514_found_in_slot = 1;
2229                             break;
2230                     }
2231             }
2232     #endif
2233     
2234     	/* if no S514 adapter has been found, then exit */
2235             if (!number_S514_cards) {
2236                     printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname);
2237                     return 0;
2238             }
2239             /* if more than one S514 card has been found, then the user must have */        /* defined a slot number so that the correct adapter is used */
2240             else if ((number_S514_cards > 1) && hw->auto_pci_cfg) {
2241                     printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n"
2242     				 "%s:        More than one S514 adapter found.\n"
2243     				 "%s:        Disable the Autodetect feature and supply\n"
2244     				 "%s:        the PCISLOT numbers for each card.\n",
2245                             modname,modname,modname,modname);
2246                     return 0;
2247             }
2248             /* if the user has specified a slot number and the S514 adapter has */
2249             /* not been found in that slot, then exit */
2250             else if (!hw->auto_pci_cfg && !S514_found_in_slot) {
2251                     printk(KERN_INFO
2252     			"%s: Error, S514 card not found in specified slot #%d\n",
2253                             modname, slot_no);
2254                     return 0;
2255             }
2256     
2257     	return (number_S514_cards);
2258     }
2259     
2260     
2261     
2262     /******* Miscellaneous ******************************************************/
2263     
2264     /*============================================================================
2265      * Calibrate SDLA memory access delay.
2266      * Count number of idle loops made within 1 second and then calculate the
2267      * number of loops that should be made to achive desired delay.
2268      */
2269     static int calibrate_delay (int mks)
2270     {
2271     	unsigned int delay;
2272     	unsigned long stop;
2273     
2274     	for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay);
2275     	return (delay/(1000000L/mks) + 1);
2276     }
2277     
2278     /*============================================================================
2279      * Get option's index into the options list.
2280      *	Return option's index (1 .. N) or zero if option is invalid.
2281      */
2282     static int get_option_index (unsigned* optlist, unsigned optval)
2283     {
2284     	int i;
2285     
2286     	for (i = 1; i <= optlist[0]; ++i)
2287     		if ( optlist[i] == optval)
2288     			return i;
2289     	return 0;
2290     }
2291     
2292     /*============================================================================
2293      * Check memory region to see if it's available. 
2294      * Return:	0	ok.
2295      */
2296     static unsigned check_memregion (void* ptr, unsigned len)
2297     {
2298     	volatile unsigned char* p = ptr;
2299     
2300             for (; len && (readb (p) == 0xFF); --len, ++p) {
2301                     writeb (0, p);          /* attempt to write 0 */
2302                     if (readb(p) != 0xFF) { /* still has to read 0xFF */
2303                             writeb (0xFF, p);/* restore original value */
2304                             break;          /* not good */
2305                     }
2306             }
2307     
2308     	return len;
2309     }
2310     
2311     /*============================================================================
2312      * Test memory region.
2313      * Return:	size of the region that passed the test.
2314      * Note:	Region size must be multiple of 2 !
2315      */
2316     static unsigned test_memregion (void* ptr, unsigned len)
2317     {
2318     	volatile unsigned short* w_ptr;
2319     	unsigned len_w = len >> 1;	/* region len in words */
2320     	unsigned i;
2321     
2322             for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
2323                     writew (0xAA55, w_ptr);
2324             
2325     	for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
2326                     if (readw (w_ptr) != 0xAA55) {
2327                             len_w = i;
2328                             break;
2329                     }
2330     
2331             for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
2332                     writew (0x55AA, w_ptr);
2333             
2334             for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
2335                     if (readw(w_ptr) != 0x55AA) {
2336                             len_w = i;
2337                             break;
2338                     }
2339             
2340             for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr)
2341     		writew (0, w_ptr);
2342     
2343             return len_w << 1;
2344     }
2345     
2346     /*============================================================================
2347      * Calculate 16-bit CRC using CCITT polynomial.
2348      */
2349     static unsigned short checksum (unsigned char* buf, unsigned len)
2350     {
2351     	unsigned short crc = 0;
2352     	unsigned mask, flag;
2353     
2354     	for (; len; --len, ++buf) {
2355     		for (mask = 0x80; mask; mask >>= 1) {
2356     			flag = (crc & 0x8000);
2357     			crc <<= 1;
2358     			crc |= ((*buf & mask) ? 1 : 0);
2359     			if (flag) crc ^= 0x1021;
2360     		}
2361     	}
2362     	return crc;
2363     }
2364     
2365     static int init_pci_slot(sdlahw_t *hw)
2366     {
2367     
2368     	u32 int_status;
2369     	int volatile found=0;
2370     	int i=0;
2371     
2372     	/* Check if this is a very first load for a specific
2373              * pci card. If it is, clear the interrput bits, and
2374              * set the flag indicating that this card was initialized.
2375     	 */
2376     	
2377     	for (i=0; (i<MAX_S514_CARDS) && !found; i++){
2378     		if (pci_slot_ar[i] == hw->S514_slot_no){
2379     			found=1;
2380     			break;
2381     		}
2382     		if (pci_slot_ar[i] == 0xFF){
2383     			break;
2384     		}
2385     	}
2386     
2387     	if (!found){
2388     		read_S514_int_stat(hw,&int_status);
2389     		S514_intack(hw,int_status);
2390     		if (i == MAX_S514_CARDS){
2391     			printk(KERN_INFO "%s: Critical Error !!!\n",modname);
2392     			printk(KERN_INFO 
2393     				"%s: Number of Sangoma PCI cards exceeded maximum limit.\n",
2394     					modname);
2395     			printk(KERN_INFO "Please contact Sangoma Technologies\n");
2396     			return 1;
2397     		}
2398     		pci_slot_ar[i] = hw->S514_slot_no;
2399     	}
2400     	return 0;
2401     }
2402     
2403     static int pci_probe(sdlahw_t *hw)
2404     {
2405     
2406             unsigned char slot_no;
2407             int number_S514_cards = 0;
2408             u16 PCI_subsys_vendor;
2409     	u16 PCI_card_type;
2410     
2411     #if defined(LINUX_2_1) || defined(LINUX_2_4)
2412             struct pci_dev *pci_dev = NULL;
2413     	struct pci_bus *bus = NULL;
2414     #else
2415             int pci_index;
2416     	u8 irq;
2417     #endif
2418      
2419            slot_no = 0;
2420       
2421     #if defined(LINUX_2_1) || defined(LINUX_2_4)
2422     	while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev))
2423             	!= NULL) {
2424     		
2425                     pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD,
2426                             &PCI_subsys_vendor);
2427     		
2428                     if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
2429                     	continue;
2430     
2431     		pci_read_config_word(pci_dev, PCI_CARD_TYPE,
2432                             &PCI_card_type);
2433     	
2434     		bus = pci_dev->bus;
2435     		
2436     		/* A dual cpu card can support up to 4 physical connections,
2437     		 * where a single cpu card can support up to 2 physical
2438     		 * connections.  The FT1 card can only support a single 
2439     		 * connection, however we cannot distinguish between a Single
2440     		 * CPU card and an FT1 card. */
2441     		if (PCI_card_type == S514_DUAL_CPU){
2442                     	number_S514_cards += 4;
2443     			 printk(KERN_INFO
2444     				"wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
2445                             	bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
2446     				pci_dev->irq);
2447     		}else{
2448     			number_S514_cards += 2;
2449     			printk(KERN_INFO
2450     				"wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
2451                             	bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK),
2452     				pci_dev->irq);
2453     		}
2454             }
2455     
2456     #else
2457             for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) {
2458     		
2459                     if(pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index,
2460                             &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) {
2461                                     break;
2462                     }
2463                     pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func,
2464                             PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor);
2465                     if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR)
2466                             continue;
2467     		
2468     		pcibios_read_config_word(hw->pci_bus,hw->pci_dev_func,PCI_CARD_TYPE,
2469                             &PCI_card_type);
2470     
2471     		pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func,
2472     				PCI_INT_LINE_BYTE, &irq);
2473     
2474     		/* A dual cpu card can support up to 4 physical connections,
2475     		 * where a single cpu card can support up to 2 physical
2476     		 * connections.  The FT1 card can only support a single 
2477     		 * connection, however we cannot distinguish between a Single
2478     		 * CPU card and an FT1 card. */
2479     		if (PCI_card_type == S514_DUAL_CPU){
2480                     	number_S514_cards += 4;
2481     			 printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n",
2482                             	modname, hw->pci_bus,
2483                             	((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq);
2484     		}else{
2485     			printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n",
2486                             	modname, hw->pci_bus,
2487                             	((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq);
2488     			number_S514_cards += 2;
2489     		}
2490             }
2491     #endif
2492     
2493     	return number_S514_cards;
2494     
2495     }
2496     
2497     
2498     
2499     #if defined(LINUX_2_1) || defined(LINUX_2_4)
2500     EXPORT_SYMBOL(wanpipe_hw_probe);
2501     #endif
2502     
2503     unsigned wanpipe_hw_probe(void)
2504     {
2505     	sdlahw_t hw;
2506     	unsigned* opt = s508_port_options; 
2507     	unsigned cardno=0;
2508     	int i;
2509     	
2510     	memset(&hw, 0, sizeof(hw));
2511     	
2512     	for (i = 1; i <= opt[0]; i++) {
2513     		if (detect_s508(opt[i])){
2514     			/* S508 card can support up to two physical links */
2515     			cardno+=2;
2516     			printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]);
2517     		}
2518     	}
2519     
2520           #ifdef CONFIG_PCI
2521     	hw.S514_slot_no = 0;
2522     	cardno += pci_probe(&hw);
2523           #else
2524     	printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n");
2525     	printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n");
2526           #endif
2527     
2528     	return cardno;
2529     }
2530     
2531     /****** End *****************************************************************/
2532