• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/alpha/kernel/
1/*
2 * SMC 37C669 initialization code
3 */
4#include <linux/kernel.h>
5
6#include <linux/mm.h>
7#include <linux/init.h>
8#include <linux/delay.h>
9#include <linux/spinlock.h>
10
11#include <asm/hwrpb.h>
12#include <asm/io.h>
13#include <asm/segment.h>
14
15# define DBG_DEVS(args)
16
17#define KB              1024
18#define MB              (1024*KB)
19#define GB              (1024*MB)
20
21#define SMC_DEBUG   0
22
23/* File:	smcc669_def.h
24 *
25 * Copyright (C) 1997 by
26 * Digital Equipment Corporation, Maynard, Massachusetts.
27 * All rights reserved.
28 *
29 * This software is furnished under a license and may be used and copied
30 * only  in  accordance  of  the  terms  of  such  license  and with the
31 * inclusion of the above copyright notice. This software or  any  other
32 * copies thereof may not be provided or otherwise made available to any
33 * other person.  No title to and  ownership of the  software is  hereby
34 * transferred.
35 *
36 * The information in this software is  subject to change without notice
37 * and  should  not  be  construed  as a commitment by Digital Equipment
38 * Corporation.
39 *
40 * Digital assumes no responsibility for the use  or  reliability of its
41 * software on equipment which is not supplied by Digital.
42 *
43 *
44 * Abstract:
45 *
46 *	This file contains header definitions for the SMC37c669
47 *	Super I/O controller.
48 *
49 * Author:
50 *
51 *	Eric Rasmussen
52 *
53 * Modification History:
54 *
55 *	er	28-Jan-1997	Initial Entry
56 */
57
58#ifndef __SMC37c669_H
59#define __SMC37c669_H
60
61/*
62** Macros for handling device IRQs
63**
64** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)
65** to device IRQs (A - H).
66*/
67#define SMC37c669_DEVICE_IRQ_MASK	0x80000000
68#define SMC37c669_DEVICE_IRQ( __i )	\
69	((SMC37c669_DEVICE_IRQ_MASK) | (__i))
70#define SMC37c669_IS_DEVICE_IRQ(__i)	\
71	(((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
72#define SMC37c669_RAW_DEVICE_IRQ(__i)	\
73	((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))
74
75/*
76** Macros for handling device DRQs
77**
78** The mask acts as a flag used in mapping actual ISA DMA
79** channels to device DMA channels (A - C).
80*/
81#define SMC37c669_DEVICE_DRQ_MASK	0x80000000
82#define SMC37c669_DEVICE_DRQ(__d)	\
83	((SMC37c669_DEVICE_DRQ_MASK) | (__d))
84#define SMC37c669_IS_DEVICE_DRQ(__d)	\
85	(((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
86#define SMC37c669_RAW_DEVICE_DRQ(__d)	\
87	((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))
88
89#define SMC37c669_DEVICE_ID	0x3
90
91/*
92** SMC37c669 Device Function Definitions
93*/
94#define SERIAL_0	0
95#define SERIAL_1	1
96#define PARALLEL_0	2
97#define FLOPPY_0	3
98#define IDE_0		4
99#define NUM_FUNCS	5
100
101/*
102** Default Device Function Mappings
103*/
104#define COM1_BASE	0x3F8
105#define COM1_IRQ	4
106#define COM2_BASE	0x2F8
107#define COM2_IRQ	3
108#define PARP_BASE	0x3BC
109#define PARP_IRQ	7
110#define PARP_DRQ	3
111#define FDC_BASE	0x3F0
112#define FDC_IRQ		6
113#define FDC_DRQ		2
114
115/*
116** Configuration On/Off Key Definitions
117*/
118#define SMC37c669_CONFIG_ON_KEY		0x55
119#define SMC37c669_CONFIG_OFF_KEY	0xAA
120
121/*
122** SMC 37c669 Device IRQs
123*/
124#define SMC37c669_DEVICE_IRQ_A	    ( SMC37c669_DEVICE_IRQ( 0x01 ) )
125#define SMC37c669_DEVICE_IRQ_B	    ( SMC37c669_DEVICE_IRQ( 0x02 ) )
126#define SMC37c669_DEVICE_IRQ_C	    ( SMC37c669_DEVICE_IRQ( 0x03 ) )
127#define SMC37c669_DEVICE_IRQ_D	    ( SMC37c669_DEVICE_IRQ( 0x04 ) )
128#define SMC37c669_DEVICE_IRQ_E	    ( SMC37c669_DEVICE_IRQ( 0x05 ) )
129#define SMC37c669_DEVICE_IRQ_F	    ( SMC37c669_DEVICE_IRQ( 0x06 ) )
130/*      SMC37c669_DEVICE_IRQ_G	    *** RESERVED ***/
131#define SMC37c669_DEVICE_IRQ_H	    ( SMC37c669_DEVICE_IRQ( 0x08 ) )
132
133/*
134** SMC 37c669 Device DMA Channel Definitions
135*/
136#define SMC37c669_DEVICE_DRQ_A		    ( SMC37c669_DEVICE_DRQ( 0x01 ) )
137#define SMC37c669_DEVICE_DRQ_B		    ( SMC37c669_DEVICE_DRQ( 0x02 ) )
138#define SMC37c669_DEVICE_DRQ_C		    ( SMC37c669_DEVICE_DRQ( 0x03 ) )
139
140/*
141** Configuration Register Index Definitions
142*/
143#define SMC37c669_CR00_INDEX	    0x00
144#define SMC37c669_CR01_INDEX	    0x01
145#define SMC37c669_CR02_INDEX	    0x02
146#define SMC37c669_CR03_INDEX	    0x03
147#define SMC37c669_CR04_INDEX	    0x04
148#define SMC37c669_CR05_INDEX	    0x05
149#define SMC37c669_CR06_INDEX	    0x06
150#define SMC37c669_CR07_INDEX	    0x07
151#define SMC37c669_CR08_INDEX	    0x08
152#define SMC37c669_CR09_INDEX	    0x09
153#define SMC37c669_CR0A_INDEX	    0x0A
154#define SMC37c669_CR0B_INDEX	    0x0B
155#define SMC37c669_CR0C_INDEX	    0x0C
156#define SMC37c669_CR0D_INDEX	    0x0D
157#define SMC37c669_CR0E_INDEX	    0x0E
158#define SMC37c669_CR0F_INDEX	    0x0F
159#define SMC37c669_CR10_INDEX	    0x10
160#define SMC37c669_CR11_INDEX	    0x11
161#define SMC37c669_CR12_INDEX	    0x12
162#define SMC37c669_CR13_INDEX	    0x13
163#define SMC37c669_CR14_INDEX	    0x14
164#define SMC37c669_CR15_INDEX	    0x15
165#define SMC37c669_CR16_INDEX	    0x16
166#define SMC37c669_CR17_INDEX	    0x17
167#define SMC37c669_CR18_INDEX	    0x18
168#define SMC37c669_CR19_INDEX	    0x19
169#define SMC37c669_CR1A_INDEX	    0x1A
170#define SMC37c669_CR1B_INDEX	    0x1B
171#define SMC37c669_CR1C_INDEX	    0x1C
172#define SMC37c669_CR1D_INDEX	    0x1D
173#define SMC37c669_CR1E_INDEX	    0x1E
174#define SMC37c669_CR1F_INDEX	    0x1F
175#define SMC37c669_CR20_INDEX	    0x20
176#define SMC37c669_CR21_INDEX	    0x21
177#define SMC37c669_CR22_INDEX	    0x22
178#define SMC37c669_CR23_INDEX	    0x23
179#define SMC37c669_CR24_INDEX	    0x24
180#define SMC37c669_CR25_INDEX	    0x25
181#define SMC37c669_CR26_INDEX	    0x26
182#define SMC37c669_CR27_INDEX	    0x27
183#define SMC37c669_CR28_INDEX	    0x28
184#define SMC37c669_CR29_INDEX	    0x29
185
186/*
187** Configuration Register Alias Definitions
188*/
189#define SMC37c669_DEVICE_ID_INDEX		    SMC37c669_CR0D_INDEX
190#define SMC37c669_DEVICE_REVISION_INDEX		    SMC37c669_CR0E_INDEX
191#define SMC37c669_FDC_BASE_ADDRESS_INDEX	    SMC37c669_CR20_INDEX
192#define SMC37c669_IDE_BASE_ADDRESS_INDEX	    SMC37c669_CR21_INDEX
193#define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX	    SMC37c669_CR22_INDEX
194#define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX	    SMC37c669_CR23_INDEX
195#define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX	    SMC37c669_CR24_INDEX
196#define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX	    SMC37c669_CR25_INDEX
197#define SMC37c669_PARALLEL_FDC_DRQ_INDEX	    SMC37c669_CR26_INDEX
198#define SMC37c669_PARALLEL_FDC_IRQ_INDEX	    SMC37c669_CR27_INDEX
199#define SMC37c669_SERIAL_IRQ_INDEX		    SMC37c669_CR28_INDEX
200
201/*
202** Configuration Register Definitions
203**
204** The INDEX (write only) and DATA (read/write) ports are effective
205** only when the chip is in the Configuration State.
206*/
207typedef struct _SMC37c669_CONFIG_REGS {
208    unsigned char index_port;
209    unsigned char data_port;
210} SMC37c669_CONFIG_REGS;
211
212/*
213** CR00 - default value 0x28
214**
215**  IDE_EN (CR00<1:0>):
216**	0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
217**	11 - IRQ_H available as IRQ output,
218**	     IRRX2, IRTX2 available as alternate IR pins
219**	10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
220**
221**  VALID (CR00<7>):
222**	A high level on this software controlled bit can
223**	be used to indicate that a valid configuration
224**	cycle has occurred.  The control software must
225**	take care to set this bit at the appropriate times.
226**	Set to zero after power up.  This bit has no
227**	effect on any other hardware in the chip.
228**
229*/
230typedef union _SMC37c669_CR00 {
231    unsigned char as_uchar;
232    struct {
233    	unsigned ide_en : 2;	    /* See note above		*/
234	unsigned reserved1 : 1;	    /* RAZ			*/
235	unsigned fdc_pwr : 1;	    /* 1 = supply power to FDC  */
236	unsigned reserved2 : 3;	    /* Read as 010b		*/
237	unsigned valid : 1;	    /* See note above		*/
238    }	by_field;
239} SMC37c669_CR00;
240
241/*
242** CR01 - default value 0x9C
243*/
244typedef union _SMC37c669_CR01 {
245    unsigned char as_uchar;
246    struct {
247    	unsigned reserved1 : 2;	    /* RAZ			    */
248	unsigned ppt_pwr : 1;	    /* 1 = supply power to PPT	    */
249	unsigned ppt_mode : 1;	    /* 1 = Printer mode, 0 = EPP    */
250	unsigned reserved2 : 1;	    /* Read as 1		    */
251	unsigned reserved3 : 2;	    /* RAZ			    */
252	unsigned lock_crx: 1;	    /* Lock CR00 - CR18		    */
253    }	by_field;
254} SMC37c669_CR01;
255
256/*
257** CR02 - default value 0x88
258*/
259typedef union _SMC37c669_CR02 {
260    unsigned char as_uchar;
261    struct {
262    	unsigned reserved1 : 3;	    /* RAZ			    */
263	unsigned uart1_pwr : 1;	    /* 1 = supply power to UART1    */
264	unsigned reserved2 : 3;	    /* RAZ			    */
265	unsigned uart2_pwr : 1;	    /* 1 = supply power to UART2    */
266    }	by_field;
267} SMC37c669_CR02;
268
269/*
270** CR03 - default value 0x78
271**
272**  CR03<7>	CR03<2>	    Pin 94
273**  -------	-------	    ------
274**     0	   X	    DRV2 (input)
275**     1	   0	    ADRX
276**     1	   1	    IRQ_B
277**
278**  CR03<6>	CR03<5>	    Op Mode
279**  -------	-------	    -------
280**     0	   0	    Model 30
281**     0	   1	    PS/2
282**     1	   0	    Reserved
283**     1	   1	    AT Mode
284*/
285typedef union _SMC37c669_CR03 {
286    unsigned char as_uchar;
287    struct {
288    	unsigned pwrgd_gamecs : 1;  /* 1 = PWRGD, 0 = GAMECS	    */
289	unsigned fdc_mode2 : 1;	    /* 1 = Enhanced Mode 2	    */
290	unsigned pin94_0 : 1;	    /* See note above		    */
291	unsigned reserved1 : 1;	    /* RAZ			    */
292	unsigned drvden : 1;	    /* 1 = high, 0 - output	    */
293	unsigned op_mode : 2;	    /* See note above		    */
294	unsigned pin94_1 : 1;	    /* See note above		    */
295    }	by_field;
296} SMC37c669_CR03;
297
298/*
299** CR04 - default value 0x00
300**
301**  PP_EXT_MODE:
302**	If CR01<PP_MODE> = 0 and PP_EXT_MODE =
303**	    00 - Standard and Bidirectional
304**	    01 - EPP mode and SPP
305**	    10 - ECP mode
306**		 In this mode, 2 drives can be supported
307**		 directly, 3 or 4 drives must use external
308**		 4 drive support.  SPP can be selected
309**		 through the ECR register of ECP as mode 000.
310**	    11 - ECP mode and EPP mode
311**		 In this mode, 2 drives can be supported
312**		 directly, 3 or 4 drives must use external
313**		 4 drive support.  SPP can be selected
314**		 through the ECR register of ECP as mode 000.
315**		 In this mode, EPP can be selected through
316**		 the ECR register of ECP as mode 100.
317**
318**  PP_FDC:
319**	00 - Normal
320**	01 - PPFD1
321**	10 - PPFD2
322**	11 - Reserved
323**
324**  MIDI1:
325**	Serial Clock Select:
326**	    A low level on this bit disables MIDI support,
327**	    clock = divide by 13.  A high level on this
328**	    bit enables MIDI support, clock = divide by 12.
329**
330**	MIDI operates at 31.25 Kbps which can be derived
331**	from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
332**
333**  ALT_IO:
334**	0 - Use pins IRRX, IRTX
335**	1 - Use pins IRRX2, IRTX2
336**
337**	If this bit is set, the IR receive and transmit
338**	functions will not be available on pins 25 and 26
339**	unless CR00<IDE_EN> = 11.
340*/
341typedef union _SMC37c669_CR04 {
342    unsigned char as_uchar;
343    struct {
344    	unsigned ppt_ext_mode : 2;  /* See note above		    */
345	unsigned ppt_fdc : 2;	    /* See note above		    */
346	unsigned midi1 : 1;	    /* See note above		    */
347	unsigned midi2 : 1;	    /* See note above		    */
348	unsigned epp_type : 1;	    /* 0 = EPP 1.9, 1 = EPP 1.7	    */
349	unsigned alt_io : 1;	    /* See note above		    */
350    }	by_field;
351} SMC37c669_CR04;
352
353/*
354** CR05 - default value 0x00
355**
356**  DEN_SEL:
357**	00 - Densel output normal
358**	01 - Reserved
359**	10 - Densel output 1
360**	11 - Densel output 0
361**
362*/
363typedef union _SMC37c669_CR05 {
364    unsigned char as_uchar;
365    struct {
366    	unsigned reserved1 : 2;	    /* RAZ					*/
367	unsigned fdc_dma_mode : 1;  /* 0 = burst, 1 = non-burst			*/
368	unsigned den_sel : 2;	    /* See note above				*/
369	unsigned swap_drv : 1;	    /* Swap the FDC motor selects		*/
370	unsigned extx4 : 1;	    /* 0 = 2 drive, 1 = external 4 drive decode	*/
371	unsigned reserved2 : 1;	    /* RAZ					*/
372    }	by_field;
373} SMC37c669_CR05;
374
375/*
376** CR06 - default value 0xFF
377*/
378typedef union _SMC37c669_CR06 {
379    unsigned char as_uchar;
380    struct {
381    	unsigned floppy_a : 2;	    /* Type of floppy drive A	    */
382	unsigned floppy_b : 2;	    /* Type of floppy drive B	    */
383	unsigned floppy_c : 2;	    /* Type of floppy drive C	    */
384	unsigned floppy_d : 2;	    /* Type of floppy drive D	    */
385    }	by_field;
386} SMC37c669_CR06;
387
388/*
389** CR07 - default value 0x00
390**
391**  Auto Power Management CR07<7:4>:
392**	0 - Auto Powerdown disabled (default)
393**	1 - Auto Powerdown enabled
394**
395**	This bit is reset to the default state by POR or
396**	a hardware reset.
397**
398*/
399typedef union _SMC37c669_CR07 {
400    unsigned char as_uchar;
401    struct {
402    	unsigned floppy_boot : 2;   /* 0 = A:, 1 = B:		    */
403	unsigned reserved1 : 2;	    /* RAZ			    */
404	unsigned ppt_en : 1;	    /* See note above		    */
405	unsigned uart1_en : 1;	    /* See note above		    */
406	unsigned uart2_en : 1;	    /* See note above		    */
407	unsigned fdc_en : 1;	    /* See note above		    */
408    }	by_field;
409} SMC37c669_CR07;
410
411/*
412** CR08 - default value 0x00
413*/
414typedef union _SMC37c669_CR08 {
415    unsigned char as_uchar;
416    struct {
417    	unsigned zero : 4;	    /* 0			    */
418	unsigned addrx7_4 : 4;	    /* ADR<7:3> for ADRx decode	    */
419    }	by_field;
420} SMC37c669_CR08;
421
422/*
423** CR09 - default value 0x00
424**
425**  ADRx_CONFIG:
426**	00 - ADRx disabled
427**	01 - 1 byte decode A<3:0> = 0000b
428**	10 - 8 byte block decode A<3:0> = 0XXXb
429**	11 - 16 byte block decode A<3:0> = XXXXb
430**
431*/
432typedef union _SMC37c669_CR09 {
433    unsigned char as_uchar;
434    struct {
435    	unsigned adra8 : 3;	    /* ADR<10:8> for ADRx decode    */
436	unsigned reserved1 : 3;
437	unsigned adrx_config : 2;   /* See note above		    */
438    }	by_field;
439} SMC37c669_CR09;
440
441/*
442** CR0A - default value 0x00
443*/
444typedef union _SMC37c669_CR0A {
445    unsigned char as_uchar;
446    struct {
447    	unsigned ecp_fifo_threshold : 4;
448	unsigned reserved1 : 4;
449    }	by_field;
450} SMC37c669_CR0A;
451
452/*
453** CR0B - default value 0x00
454*/
455typedef union _SMC37c669_CR0B {
456    unsigned char as_uchar;
457    struct {
458    	unsigned fdd0_drtx : 2;	    /* FDD0 Data Rate Table	    */
459	unsigned fdd1_drtx : 2;	    /* FDD1 Data Rate Table	    */
460	unsigned fdd2_drtx : 2;	    /* FDD2 Data Rate Table	    */
461	unsigned fdd3_drtx : 2;	    /* FDD3 Data Rate Table	    */
462    }	by_field;
463} SMC37c669_CR0B;
464
465/*
466** CR0C - default value 0x00
467**
468**  UART2_MODE:
469**	000 - Standard (default)
470**	001 - IrDA (HPSIR)
471**	010 - Amplitude Shift Keyed IR @500 KHz
472**	011 - Reserved
473**	1xx - Reserved
474**
475*/
476typedef union _SMC37c669_CR0C {
477    unsigned char as_uchar;
478    struct {
479    	unsigned uart2_rcv_polarity : 1;    /* 1 = invert RX		*/
480	unsigned uart2_xmit_polarity : 1;   /* 1 = invert TX		*/
481	unsigned uart2_duplex : 1;	    /* 1 = full, 0 = half	*/
482	unsigned uart2_mode : 3;	    /* See note above		*/
483	unsigned uart1_speed : 1;	    /* 1 = high speed enabled	*/
484	unsigned uart2_speed : 1;	    /* 1 = high speed enabled	*/
485    }	by_field;
486} SMC37c669_CR0C;
487
488/*
489** CR0D - default value 0x03
490**
491**  Device ID Register - read only
492*/
493typedef union _SMC37c669_CR0D {
494    unsigned char as_uchar;
495    struct {
496    	unsigned device_id : 8;	    /* Returns 0x3 in this field    */
497    }	by_field;
498} SMC37c669_CR0D;
499
500/*
501** CR0E - default value 0x02
502**
503**  Device Revision Register - read only
504*/
505typedef union _SMC37c669_CR0E {
506    unsigned char as_uchar;
507    struct {
508    	unsigned device_rev : 8;    /* Returns 0x2 in this field    */
509    }	by_field;
510} SMC37c669_CR0E;
511
512/*
513** CR0F - default value 0x00
514*/
515typedef union _SMC37c669_CR0F {
516    unsigned char as_uchar;
517    struct {
518    	unsigned test0 : 1;	    /* Reserved - set to 0	    */
519	unsigned test1 : 1;	    /* Reserved - set to 0	    */
520	unsigned test2 : 1;	    /* Reserved - set to 0	    */
521	unsigned test3 : 1;	    /* Reserved - set t0 0	    */
522	unsigned test4 : 1;	    /* Reserved - set to 0	    */
523	unsigned test5 : 1;	    /* Reserved - set t0 0	    */
524	unsigned test6 : 1;	    /* Reserved - set t0 0	    */
525	unsigned test7 : 1;	    /* Reserved - set to 0	    */
526    }	by_field;
527} SMC37c669_CR0F;
528
529/*
530** CR10 - default value 0x00
531*/
532typedef union _SMC37c669_CR10 {
533    unsigned char as_uchar;
534    struct {
535    	unsigned reserved1 : 3;	     /* RAZ			    */
536	unsigned pll_gain : 1;	     /* 1 = 3V, 2 = 5V operation    */
537	unsigned pll_stop : 1;	     /* 1 = stop PLLs		    */
538	unsigned ace_stop : 1;	     /* 1 = stop UART clocks	    */
539	unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz  */
540	unsigned ir_test : 1;	     /* Enable IR test mode	    */
541    }	by_field;
542} SMC37c669_CR10;
543
544/*
545** CR11 - default value 0x00
546*/
547typedef union _SMC37c669_CR11 {
548    unsigned char as_uchar;
549    struct {
550    	unsigned ir_loopback : 1;   /* Internal IR loop back		    */
551	unsigned test_10ms : 1;	    /* Test 10ms autopowerdown FDC timeout  */
552	unsigned reserved1 : 6;	    /* RAZ				    */
553    }	by_field;
554} SMC37c669_CR11;
555
556/*
557** CR12 - CR1D are reserved registers
558*/
559
560/*
561** CR1E - default value 0x80
562**
563**  GAMECS:
564**	00 - GAMECS disabled
565**	01 - 1 byte decode ADR<3:0> = 0001b
566**	10 - 8 byte block decode ADR<3:0> = 0XXXb
567**	11 - 16 byte block decode ADR<3:0> = XXXXb
568**
569*/
570typedef union _SMC37c66_CR1E {
571    unsigned char as_uchar;
572    struct {
573    	unsigned gamecs_config: 2;   /* See note above		    */
574	unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4>	    */
575    }	by_field;
576} SMC37c669_CR1E;
577
578/*
579** CR1F - default value 0x00
580**
581**  DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
582**  --- --- ------- ------- ----------
583**   0   0  DENSEL  DRATE0  4/2/1 MB 3.5"
584**                          2/1 MB 5.25"
585**                          2/1.6/1 MB 3.5" (3-mode)
586**   0   1  DRATE1  DRATE0
587**   1   0  nDENSEL DRATE0  PS/2
588**   1   1  DRATE0  DRATE1
589**
590**  Note: DENSEL, DRATE1, and DRATE0 map onto two output
591**	  pins - DRVDEN0 and DRVDEN1.
592**
593*/
594typedef union _SMC37c669_CR1F {
595    unsigned char as_uchar;
596    struct {
597    	unsigned fdd0_drive_type : 2;	/* FDD0 drive type	    */
598	unsigned fdd1_drive_type : 2;	/* FDD1 drive type	    */
599	unsigned fdd2_drive_type : 2;	/* FDD2 drive type	    */
600	unsigned fdd3_drive_type : 2;	/* FDD3 drive type	    */
601    }	by_field;
602} SMC37c669_CR1F;
603
604/*
605** CR20 - default value 0x3C
606**
607**  FDC Base Address Register
608**	- To disable this decode set Addr<9:8> = 0
609**	- A<10> = 0, A<3:0> = 0XXXb to access.
610**
611*/
612typedef union _SMC37c669_CR20 {
613    unsigned char as_uchar;
614    struct {
615    	unsigned zero : 2;	    /* 0			    */
616	unsigned addr9_4 : 6;	    /* FDC Addr<9:4>		    */
617    }	by_field;
618} SMC37c669_CR20;
619
620/*
621** CR21 - default value 0x3C
622**
623**  IDE Base Address Register
624**	- To disable this decode set Addr<9:8> = 0
625**	- A<10> = 0, A<3:0> = 0XXXb to access.
626**
627*/
628typedef union _SMC37c669_CR21 {
629    unsigned char as_uchar;
630    struct {
631    	unsigned zero : 2;	    /* 0			    */
632	unsigned addr9_4 : 6;	    /* IDE Addr<9:4>		    */
633    }	by_field;
634} SMC37c669_CR21;
635
636/*
637** CR22 - default value 0x3D
638**
639**  IDE Alternate Status Base Address Register
640**	- To disable this decode set Addr<9:8> = 0
641**	- A<10> = 0, A<3:0> = 0110b to access.
642**
643*/
644typedef union _SMC37c669_CR22 {
645    unsigned char as_uchar;
646    struct {
647    	unsigned zero : 2;	    /* 0			    */
648	unsigned addr9_4 : 6;	    /* IDE Alt Status Addr<9:4>	    */
649    }	by_field;
650} SMC37c669_CR22;
651
652/*
653** CR23 - default value 0x00
654**
655**  Parallel Port Base Address Register
656**	- To disable this decode set Addr<9:8> = 0
657**	- A<10> = 0 to access.
658**	- If EPP is enabled, A<2:0> = XXXb to access.
659**	  If EPP is NOT enabled, A<1:0> = XXb to access
660**
661*/
662typedef union _SMC37c669_CR23 {
663    unsigned char as_uchar;
664    struct {
665	unsigned addr9_2 : 8;	    /* Parallel Port Addr<9:2>	    */
666    }	by_field;
667} SMC37c669_CR23;
668
669/*
670** CR24 - default value 0x00
671**
672**  UART1 Base Address Register
673**	- To disable this decode set Addr<9:8> = 0
674**	- A<10> = 0, A<2:0> = XXXb to access.
675**
676*/
677typedef union _SMC37c669_CR24 {
678    unsigned char as_uchar;
679    struct {
680    	unsigned zero : 1;	    /* 0			    */
681	unsigned addr9_3 : 7;	    /* UART1 Addr<9:3>		    */
682    }	by_field;
683} SMC37c669_CR24;
684
685/*
686** CR25 - default value 0x00
687**
688**  UART2 Base Address Register
689**	- To disable this decode set Addr<9:8> = 0
690**	- A<10> = 0, A<2:0> = XXXb to access.
691**
692*/
693typedef union _SMC37c669_CR25 {
694    unsigned char as_uchar;
695    struct {
696    	unsigned zero : 1;	    /* 0			    */
697	unsigned addr9_3 : 7;	    /* UART2 Addr<9:3>		    */
698    }	by_field;
699} SMC37c669_CR25;
700
701/*
702** CR26 - default value 0x00
703**
704**  Parallel Port / FDC DMA Select Register
705**
706**  D3 - D0	  DMA
707**  D7 - D4	Selected
708**  -------	--------
709**   0000	 None
710**   0001	 DMA_A
711**   0010	 DMA_B
712**   0011	 DMA_C
713**
714*/
715typedef union _SMC37c669_CR26 {
716    unsigned char as_uchar;
717    struct {
718    	unsigned ppt_drq : 4;	    /* See note above		    */
719	unsigned fdc_drq : 4;	    /* See note above		    */
720    }	by_field;
721} SMC37c669_CR26;
722
723/*
724** CR27 - default value 0x00
725**
726**  Parallel Port / FDC IRQ Select Register
727**
728**  D3 - D0	  IRQ
729**  D7 - D4	Selected
730**  -------	--------
731**   0000	 None
732**   0001	 IRQ_A
733**   0010	 IRQ_B
734**   0011	 IRQ_C
735**   0100	 IRQ_D
736**   0101	 IRQ_E
737**   0110	 IRQ_F
738**   0111	 Reserved
739**   1000	 IRQ_H
740**
741**  Any unselected IRQ REQ is in tristate
742**
743*/
744typedef union _SMC37c669_CR27 {
745    unsigned char as_uchar;
746    struct {
747    	unsigned ppt_irq : 4;	    /* See note above		    */
748	unsigned fdc_irq : 4;	    /* See note above		    */
749    }	by_field;
750} SMC37c669_CR27;
751
752/*
753** CR28 - default value 0x00
754**
755**  UART IRQ Select Register
756**
757**  D3 - D0	  IRQ
758**  D7 - D4	Selected
759**  -------	--------
760**   0000	 None
761**   0001	 IRQ_A
762**   0010	 IRQ_B
763**   0011	 IRQ_C
764**   0100	 IRQ_D
765**   0101	 IRQ_E
766**   0110	 IRQ_F
767**   0111	 Reserved
768**   1000	 IRQ_H
769**   1111	 share with UART1 (only for UART2)
770**
771**  Any unselected IRQ REQ is in tristate
772**
773**  To share an IRQ between UART1 and UART2, set
774**  UART1 to use the desired IRQ and set UART2 to
775**  0xF to enable sharing mechanism.
776**
777*/
778typedef union _SMC37c669_CR28 {
779    unsigned char as_uchar;
780    struct {
781    	unsigned uart2_irq : 4;	    /* See note above		    */
782	unsigned uart1_irq : 4;	    /* See note above		    */
783    }	by_field;
784} SMC37c669_CR28;
785
786/*
787** CR29 - default value 0x00
788**
789**  IRQIN IRQ Select Register
790**
791**  D3 - D0	  IRQ
792**  D7 - D4	Selected
793**  -------	--------
794**   0000	 None
795**   0001	 IRQ_A
796**   0010	 IRQ_B
797**   0011	 IRQ_C
798**   0100	 IRQ_D
799**   0101	 IRQ_E
800**   0110	 IRQ_F
801**   0111	 Reserved
802**   1000	 IRQ_H
803**
804**  Any unselected IRQ REQ is in tristate
805**
806*/
807typedef union _SMC37c669_CR29 {
808    unsigned char as_uchar;
809    struct {
810    	unsigned irqin_irq : 4;	    /* See note above		    */
811	unsigned reserved1 : 4;	    /* RAZ			    */
812    }	by_field;
813} SMC37c669_CR29;
814
815/*
816** Aliases of Configuration Register formats (should match
817** the set of index aliases).
818**
819** Note that CR24 and CR25 have the same format and are the
820** base address registers for UART1 and UART2.  Because of
821** this we only define 1 alias here - for CR24 - as the serial
822** base address register.
823**
824** Note that CR21 and CR22 have the same format and are the
825** base address and alternate status address registers for
826** the IDE controller.  Because of this we only define 1 alias
827** here - for CR21 - as the IDE address register.
828**
829*/
830typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
831typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
832typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
833typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
834typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
835typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
836typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
837typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
838typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;
839
840/*
841** ISA/Device IRQ Translation Table Entry Definition
842*/
843typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {
844    int device_irq;
845    int isa_irq;
846} SMC37c669_IRQ_TRANSLATION_ENTRY;
847
848/*
849** ISA/Device DMA Translation Table Entry Definition
850*/
851typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {
852    int device_drq;
853    int isa_drq;
854} SMC37c669_DRQ_TRANSLATION_ENTRY;
855
856/*
857** External Interface Function Prototype Declarations
858*/
859
860SMC37c669_CONFIG_REGS *SMC37c669_detect(
861    int
862);
863
864unsigned int SMC37c669_enable_device(
865    unsigned int func
866);
867
868unsigned int SMC37c669_disable_device(
869    unsigned int func
870);
871
872unsigned int SMC37c669_configure_device(
873    unsigned int func,
874    int port,
875    int irq,
876    int drq
877);
878
879void SMC37c669_display_device_info(
880    void
881);
882
883#endif	/* __SMC37c669_H */
884
885/* file:	smcc669.c
886 *
887 * Copyright (C) 1997 by
888 * Digital Equipment Corporation, Maynard, Massachusetts.
889 * All rights reserved.
890 *
891 * This software is furnished under a license and may be used and copied
892 * only  in  accordance  of  the  terms  of  such  license  and with the
893 * inclusion of the above copyright notice. This software or  any  other
894 * copies thereof may not be provided or otherwise made available to any
895 * other person.  No title to and  ownership of the  software is  hereby
896 * transferred.
897 *
898 * The information in this software is  subject to change without notice
899 * and  should  not  be  construed  as a commitment by digital equipment
900 * corporation.
901 *
902 * Digital assumes no responsibility for the use  or  reliability of its
903 * software on equipment which is not supplied by digital.
904 */
905
906/*
907 *++
908 *  FACILITY:
909 *
910 *      Alpha SRM Console Firmware
911 *
912 *  MODULE DESCRIPTION:
913 *
914 *	SMC37c669 Super I/O controller configuration routines.
915 *
916 *  AUTHORS:
917 *
918 *	Eric Rasmussen
919 *
920 *  CREATION DATE:
921 *
922 *	28-Jan-1997
923 *
924 *  MODIFICATION HISTORY:
925 *
926 *	er	01-May-1997	Fixed pointer conversion errors in
927 *				SMC37c669_get_device_config().
928 *      er	28-Jan-1997	Initial version.
929 *
930 *--
931 */
932
933#ifndef TRUE
934#define TRUE 1
935#endif
936#ifndef FALSE
937#define FALSE 0
938#endif
939
940#define wb( _x_, _y_ )	outb( _y_, (unsigned int)((unsigned long)_x_) )
941#define rb( _x_ )	inb( (unsigned int)((unsigned long)_x_) )
942
943/*
944** Local storage for device configuration information.
945**
946** Since the SMC37c669 does not provide an explicit
947** mechanism for enabling/disabling individual device
948** functions, other than unmapping the device, local
949** storage for device configuration information is
950** allocated here for use in implementing our own
951** function enable/disable scheme.
952*/
953static struct DEVICE_CONFIG {
954    unsigned int port1;
955    unsigned int port2;
956    int irq;
957    int drq;
958} local_config [NUM_FUNCS];
959
960/*
961** List of all possible addresses for the Super I/O chip
962*/
963static unsigned long SMC37c669_Addresses[] __initdata =
964    {
965	0x3F0UL,	    /* Primary address	    */
966	0x370UL,	    /* Secondary address    */
967	0UL		    /* End of list	    */
968    };
969
970/*
971** Global Pointer to the Super I/O device
972*/
973static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;
974
975/*
976** IRQ Translation Table
977**
978** The IRQ translation table is a list of SMC37c669 device
979** and standard ISA IRQs.
980**
981*/
982static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata;
983
984/*
985** The following definition is for the default IRQ
986** translation table.
987*/
988static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]
989__initdata =
990    {
991	{ SMC37c669_DEVICE_IRQ_A, -1 },
992	{ SMC37c669_DEVICE_IRQ_B, -1 },
993	{ SMC37c669_DEVICE_IRQ_C, 7 },
994	{ SMC37c669_DEVICE_IRQ_D, 6 },
995	{ SMC37c669_DEVICE_IRQ_E, 4 },
996	{ SMC37c669_DEVICE_IRQ_F, 3 },
997	{ SMC37c669_DEVICE_IRQ_H, -1 },
998	{ -1, -1 } /* End of table */
999    };
1000
1001/*
1002** The following definition is for the MONET (XP1000) IRQ
1003** translation table.
1004*/
1005static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]
1006__initdata =
1007    {
1008	{ SMC37c669_DEVICE_IRQ_A, -1 },
1009	{ SMC37c669_DEVICE_IRQ_B, -1 },
1010	{ SMC37c669_DEVICE_IRQ_C, 6 },
1011	{ SMC37c669_DEVICE_IRQ_D, 7 },
1012	{ SMC37c669_DEVICE_IRQ_E, 4 },
1013	{ SMC37c669_DEVICE_IRQ_F, 3 },
1014	{ SMC37c669_DEVICE_IRQ_H, -1 },
1015	{ -1, -1 } /* End of table */
1016    };
1017
1018static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =
1019    {
1020	SMC37c669_default_irq_table,
1021	SMC37c669_monet_irq_table
1022    };
1023
1024/*
1025** DRQ Translation Table
1026**
1027** The DRQ translation table is a list of SMC37c669 device and
1028** ISA DMA channels.
1029**
1030*/
1031static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata;
1032
1033/*
1034** The following definition is the default DRQ
1035** translation table.
1036*/
1037static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]
1038__initdata =
1039    {
1040	{ SMC37c669_DEVICE_DRQ_A, 2 },
1041	{ SMC37c669_DEVICE_DRQ_B, 3 },
1042	{ SMC37c669_DEVICE_DRQ_C, -1 },
1043	{ -1, -1 } /* End of table */
1044    };
1045
1046/*
1047** Local Function Prototype Declarations
1048*/
1049
1050static unsigned int SMC37c669_is_device_enabled(
1051    unsigned int func
1052);
1053
1054
1055static void SMC37c669_config_mode(
1056    unsigned int enable
1057);
1058
1059static unsigned char SMC37c669_read_config(
1060    unsigned char index
1061);
1062
1063static void SMC37c669_write_config(
1064    unsigned char index,
1065    unsigned char data
1066);
1067
1068static void SMC37c669_init_local_config( void );
1069
1070static struct DEVICE_CONFIG *SMC37c669_get_config(
1071    unsigned int func
1072);
1073
1074static int SMC37c669_xlate_irq(
1075    int irq
1076);
1077
1078static int SMC37c669_xlate_drq(
1079    int drq
1080);
1081
1082static  __cacheline_aligned DEFINE_SPINLOCK(smc_lock);
1083
1084/*
1085**++
1086**  FUNCTIONAL DESCRIPTION:
1087**
1088**      This function detects the presence of an SMC37c669 Super I/O
1089**	controller.
1090**
1091**  FORMAL PARAMETERS:
1092**
1093**	None
1094**
1095**  RETURN VALUE:
1096**
1097**      Returns a pointer to the device if found, otherwise,
1098**	the NULL pointer is returned.
1099**
1100**  SIDE EFFECTS:
1101**
1102**      None
1103**
1104**--
1105*/
1106SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
1107{
1108    int i;
1109    SMC37c669_DEVICE_ID_REGISTER id;
1110
1111    for ( i = 0;  SMC37c669_Addresses[i] != 0;  i++ ) {
1112/*
1113** Initialize the device pointer even though we don't yet know if
1114** the controller is at this address.  The support functions access
1115** the controller through this device pointer so we need to set it
1116** even when we are looking ...
1117*/
1118    	SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
1119/*
1120** Enter configuration mode
1121*/
1122	SMC37c669_config_mode( TRUE );
1123/*
1124** Read the device id
1125*/
1126	id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
1127/*
1128** Exit configuration mode
1129*/
1130	SMC37c669_config_mode( FALSE );
1131/*
1132** Does the device id match?  If so, assume we have found an
1133** SMC37c669 controller at this address.
1134*/
1135	if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
1136/*
1137** Initialize the IRQ and DRQ translation tables.
1138*/
1139    	    SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
1140	    SMC37c669_drq_table = SMC37c669_default_drq_table;
1141/*
1142** erfix
1143**
1144** If the platform can't use the IRQ and DRQ defaults set up in this
1145** file, it should call a platform-specific external routine at this
1146** point to reset the IRQ and DRQ translation table pointers to point
1147** at the appropriate tables for the platform.  If the defaults are
1148** acceptable, then the external routine should do nothing.
1149*/
1150
1151/*
1152** Put the chip back into configuration mode
1153*/
1154	    SMC37c669_config_mode( TRUE );
1155/*
1156** Initialize local storage for configuration information
1157*/
1158	    SMC37c669_init_local_config( );
1159/*
1160** Exit configuration mode
1161*/
1162	    SMC37c669_config_mode( FALSE );
1163/*
1164** SMC37c669 controller found, break out of search loop
1165*/
1166	    break;
1167	}
1168	else {
1169/*
1170** Otherwise, we did not find an SMC37c669 controller at this
1171** address so set the device pointer to NULL.
1172*/
1173	    SMC37c669 = NULL;
1174	}
1175    }
1176    return SMC37c669;
1177}
1178
1179
1180/*
1181**++
1182**  FUNCTIONAL DESCRIPTION:
1183**
1184**      This function enables an SMC37c669 device function.
1185**
1186**  FORMAL PARAMETERS:
1187**
1188**      func:
1189**          Which device function to enable
1190**
1191**  RETURN VALUE:
1192**
1193**      Returns TRUE is the device function was enabled, otherwise, FALSE
1194**
1195**  SIDE EFFECTS:
1196**
1197**      {@description or none@}
1198**
1199**  DESIGN:
1200**
1201**      Enabling a device function in the SMC37c669 controller involves
1202**	setting all of its mappings (port, irq, drq ...).  A local
1203**	"shadow" copy of the device configuration is kept so we can
1204**	just set each mapping to what the local copy says.
1205**
1206**	This function ALWAYS updates the local shadow configuration of
1207**	the device function being enabled, even if the device is always
1208**	enabled.  To avoid replication of code, functions such as
1209**	configure_device set up the local copy and then call this
1210**	function to the update the real device.
1211**
1212**--
1213*/
1214unsigned int __init SMC37c669_enable_device ( unsigned int func )
1215{
1216    unsigned int ret_val = FALSE;
1217/*
1218** Put the device into configuration mode
1219*/
1220    SMC37c669_config_mode( TRUE );
1221    switch ( func ) {
1222    	case SERIAL_0:
1223	    {
1224	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1225		SMC37c669_SERIAL_IRQ_REGISTER irq;
1226/*
1227** Enable the serial 1 IRQ mapping
1228*/
1229	    	irq.as_uchar =
1230		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1231
1232		irq.by_field.uart1_irq =
1233		    SMC37c669_RAW_DEVICE_IRQ(
1234			SMC37c669_xlate_irq( local_config[ func ].irq )
1235		    );
1236
1237		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1238/*
1239** Enable the serial 1 port base address mapping
1240*/
1241		base_addr.as_uchar = 0;
1242		base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1243
1244		SMC37c669_write_config(
1245		    SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1246		    base_addr.as_uchar
1247		);
1248		ret_val = TRUE;
1249		break;
1250	    }
1251	case SERIAL_1:
1252	    {
1253	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1254		SMC37c669_SERIAL_IRQ_REGISTER irq;
1255/*
1256** Enable the serial 2 IRQ mapping
1257*/
1258	    	irq.as_uchar =
1259		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1260
1261		irq.by_field.uart2_irq =
1262		    SMC37c669_RAW_DEVICE_IRQ(
1263			SMC37c669_xlate_irq( local_config[ func ].irq )
1264		    );
1265
1266		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1267/*
1268** Enable the serial 2 port base address mapping
1269*/
1270		base_addr.as_uchar = 0;
1271		base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1272
1273		SMC37c669_write_config(
1274		    SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1275		    base_addr.as_uchar
1276		);
1277		ret_val = TRUE;
1278		break;
1279	    }
1280	case PARALLEL_0:
1281	    {
1282	    	SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1283		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1284		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1285/*
1286** Enable the parallel port DMA channel mapping
1287*/
1288	    	drq.as_uchar =
1289		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1290
1291		drq.by_field.ppt_drq =
1292		    SMC37c669_RAW_DEVICE_DRQ(
1293			SMC37c669_xlate_drq( local_config[ func ].drq )
1294		    );
1295
1296		SMC37c669_write_config(
1297		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1298		    drq.as_uchar
1299		);
1300/*
1301** Enable the parallel port IRQ mapping
1302*/
1303		irq.as_uchar =
1304		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1305
1306		irq.by_field.ppt_irq =
1307		    SMC37c669_RAW_DEVICE_IRQ(
1308			SMC37c669_xlate_irq( local_config[ func ].irq )
1309		    );
1310
1311		SMC37c669_write_config(
1312		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1313		    irq.as_uchar
1314		);
1315/*
1316** Enable the parallel port base address mapping
1317*/
1318		base_addr.as_uchar = 0;
1319		base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;
1320
1321		SMC37c669_write_config(
1322		    SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1323		    base_addr.as_uchar
1324		);
1325		ret_val = TRUE;
1326		break;
1327	    }
1328	case FLOPPY_0:
1329	    {
1330	    	SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1331		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1332		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1333/*
1334** Enable the floppy controller DMA channel mapping
1335*/
1336	    	drq.as_uchar =
1337		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1338
1339		drq.by_field.fdc_drq =
1340		    SMC37c669_RAW_DEVICE_DRQ(
1341			SMC37c669_xlate_drq( local_config[ func ].drq )
1342		    );
1343
1344		SMC37c669_write_config(
1345		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1346		    drq.as_uchar
1347		);
1348/*
1349** Enable the floppy controller IRQ mapping
1350*/
1351		irq.as_uchar =
1352		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1353
1354		irq.by_field.fdc_irq =
1355		    SMC37c669_RAW_DEVICE_IRQ(
1356			SMC37c669_xlate_irq( local_config[ func ].irq )
1357		    );
1358
1359		SMC37c669_write_config(
1360		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1361		    irq.as_uchar
1362		);
1363/*
1364** Enable the floppy controller base address mapping
1365*/
1366		base_addr.as_uchar = 0;
1367		base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1368
1369		SMC37c669_write_config(
1370		    SMC37c669_FDC_BASE_ADDRESS_INDEX,
1371		    base_addr.as_uchar
1372		);
1373		ret_val = TRUE;
1374		break;
1375	    }
1376	case IDE_0:
1377	    {
1378	    	SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1379/*
1380** Enable the IDE alternate status base address mapping
1381*/
1382	    	ide_addr.as_uchar = 0;
1383		ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
1384
1385		SMC37c669_write_config(
1386		    SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1387		    ide_addr.as_uchar
1388		);
1389/*
1390** Enable the IDE controller base address mapping
1391*/
1392		ide_addr.as_uchar = 0;
1393		ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1394
1395		SMC37c669_write_config(
1396		    SMC37c669_IDE_BASE_ADDRESS_INDEX,
1397		    ide_addr.as_uchar
1398		);
1399		ret_val = TRUE;
1400		break;
1401	    }
1402    }
1403/*
1404** Exit configuration mode and return
1405*/
1406    SMC37c669_config_mode( FALSE );
1407
1408    return ret_val;
1409}
1410
1411
1412/*
1413**++
1414**  FUNCTIONAL DESCRIPTION:
1415**
1416**      This function disables a device function within the
1417**	SMC37c669 Super I/O controller.
1418**
1419**  FORMAL PARAMETERS:
1420**
1421**      func:
1422**          Which function to disable
1423**
1424**  RETURN VALUE:
1425**
1426**      Return TRUE if the device function was disabled, otherwise, FALSE
1427**
1428**  SIDE EFFECTS:
1429**
1430**      {@description or none@}
1431**
1432**  DESIGN:
1433**
1434**      Disabling a function in the SMC37c669 device involves
1435**	disabling all the function's mappings (port, irq, drq ...).
1436**	A shadow copy of the device configuration is maintained
1437**	in local storage so we won't worry aboving saving the
1438**	current configuration information.
1439**
1440**--
1441*/
1442unsigned int __init SMC37c669_disable_device ( unsigned int func )
1443{
1444    unsigned int ret_val = FALSE;
1445
1446/*
1447** Put the device into configuration mode
1448*/
1449    SMC37c669_config_mode( TRUE );
1450    switch ( func ) {
1451    	case SERIAL_0:
1452	    {
1453	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1454		SMC37c669_SERIAL_IRQ_REGISTER irq;
1455/*
1456** Disable the serial 1 IRQ mapping
1457*/
1458	    	irq.as_uchar =
1459		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1460
1461		irq.by_field.uart1_irq = 0;
1462
1463		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1464/*
1465** Disable the serial 1 port base address mapping
1466*/
1467		base_addr.as_uchar = 0;
1468		SMC37c669_write_config(
1469		    SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1470		    base_addr.as_uchar
1471		);
1472		ret_val = TRUE;
1473		break;
1474	    }
1475	case SERIAL_1:
1476	    {
1477	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1478		SMC37c669_SERIAL_IRQ_REGISTER irq;
1479/*
1480** Disable the serial 2 IRQ mapping
1481*/
1482	    	irq.as_uchar =
1483		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1484
1485		irq.by_field.uart2_irq = 0;
1486
1487		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1488/*
1489** Disable the serial 2 port base address mapping
1490*/
1491		base_addr.as_uchar = 0;
1492
1493		SMC37c669_write_config(
1494		    SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1495		    base_addr.as_uchar
1496		);
1497		ret_val = TRUE;
1498		break;
1499	    }
1500	case PARALLEL_0:
1501	    {
1502	    	SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1503		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1504		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1505/*
1506** Disable the parallel port DMA channel mapping
1507*/
1508	    	drq.as_uchar =
1509		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1510
1511		drq.by_field.ppt_drq = 0;
1512
1513		SMC37c669_write_config(
1514		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1515		    drq.as_uchar
1516		);
1517/*
1518** Disable the parallel port IRQ mapping
1519*/
1520		irq.as_uchar =
1521		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1522
1523		irq.by_field.ppt_irq = 0;
1524
1525		SMC37c669_write_config(
1526		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1527		    irq.as_uchar
1528		);
1529/*
1530** Disable the parallel port base address mapping
1531*/
1532		base_addr.as_uchar = 0;
1533
1534		SMC37c669_write_config(
1535		    SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1536		    base_addr.as_uchar
1537		);
1538		ret_val = TRUE;
1539		break;
1540	    }
1541	case FLOPPY_0:
1542	    {
1543	    	SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1544		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1545		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1546/*
1547** Disable the floppy controller DMA channel mapping
1548*/
1549	    	drq.as_uchar =
1550		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1551
1552		drq.by_field.fdc_drq = 0;
1553
1554		SMC37c669_write_config(
1555		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1556		    drq.as_uchar
1557		);
1558/*
1559** Disable the floppy controller IRQ mapping
1560*/
1561		irq.as_uchar =
1562		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1563
1564		irq.by_field.fdc_irq = 0;
1565
1566		SMC37c669_write_config(
1567		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1568		    irq.as_uchar
1569		);
1570/*
1571** Disable the floppy controller base address mapping
1572*/
1573		base_addr.as_uchar = 0;
1574
1575		SMC37c669_write_config(
1576		    SMC37c669_FDC_BASE_ADDRESS_INDEX,
1577		    base_addr.as_uchar
1578		);
1579		ret_val = TRUE;
1580		break;
1581	    }
1582	case IDE_0:
1583	    {
1584	    	SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1585/*
1586** Disable the IDE alternate status base address mapping
1587*/
1588	    	ide_addr.as_uchar = 0;
1589
1590		SMC37c669_write_config(
1591		    SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1592		    ide_addr.as_uchar
1593		);
1594/*
1595** Disable the IDE controller base address mapping
1596*/
1597		ide_addr.as_uchar = 0;
1598
1599		SMC37c669_write_config(
1600		    SMC37c669_IDE_BASE_ADDRESS_INDEX,
1601		    ide_addr.as_uchar
1602		);
1603		ret_val = TRUE;
1604		break;
1605	    }
1606    }
1607/*
1608** Exit configuration mode and return
1609*/
1610    SMC37c669_config_mode( FALSE );
1611
1612    return ret_val;
1613}
1614
1615
1616/*
1617**++
1618**  FUNCTIONAL DESCRIPTION:
1619**
1620**      This function configures a device function within the
1621**	SMC37c669 Super I/O controller.
1622**
1623**  FORMAL PARAMETERS:
1624**
1625**      func:
1626**          Which device function
1627**
1628**      port:
1629**          I/O port for the function to use
1630**
1631**      irq:
1632**          IRQ for the device function to use
1633**
1634**      drq:
1635**          DMA channel for the device function to use
1636**
1637**  RETURN VALUE:
1638**
1639**      Returns TRUE if the device function was configured,
1640**	otherwise, FALSE.
1641**
1642**  SIDE EFFECTS:
1643**
1644**      {@description or none@}
1645**
1646**  DESIGN:
1647**
1648**	If this function returns TRUE, the local shadow copy of
1649**	the configuration is also updated.  If the device function
1650**	is currently disabled, only the local shadow copy is
1651**	updated and the actual device function will be updated
1652**	if/when it is enabled.
1653**
1654**--
1655*/
1656unsigned int __init SMC37c669_configure_device (
1657    unsigned int func,
1658    int port,
1659    int irq,
1660    int drq )
1661{
1662    struct DEVICE_CONFIG *cp;
1663
1664/*
1665** Check for a valid configuration
1666*/
1667    if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
1668/*
1669** Configuration is valid, update the local shadow copy
1670*/
1671    	if ( ( drq & ~0xFF ) == 0 ) {
1672	    cp->drq = drq;
1673	}
1674	if ( ( irq & ~0xFF ) == 0 ) {
1675	    cp->irq = irq;
1676	}
1677	if ( ( port & ~0xFFFF ) == 0 ) {
1678	    cp->port1 = port;
1679	}
1680/*
1681** If the device function is enabled, update the actual
1682** device configuration.
1683*/
1684	if ( SMC37c669_is_device_enabled( func ) ) {
1685	    SMC37c669_enable_device( func );
1686	}
1687	return TRUE;
1688    }
1689    return FALSE;
1690}
1691
1692
1693/*
1694**++
1695**  FUNCTIONAL DESCRIPTION:
1696**
1697**      This function determines whether a device function
1698**	within the SMC37c669 controller is enabled.
1699**
1700**  FORMAL PARAMETERS:
1701**
1702**      func:
1703**          Which device function
1704**
1705**  RETURN VALUE:
1706**
1707**      Returns TRUE if the device function is enabled, otherwise, FALSE
1708**
1709**  SIDE EFFECTS:
1710**
1711**      {@description or none@}
1712**
1713**  DESIGN:
1714**
1715**      To check whether a device is enabled we will only look at
1716**	the port base address mapping.  According to the SMC37c669
1717**	specification, all of the port base address mappings are
1718**	disabled if the addr<9:8> (bits <7:6> of the register) are
1719**	zero.
1720**
1721**--
1722*/
1723static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
1724{
1725    unsigned char base_addr = 0;
1726    unsigned int dev_ok = FALSE;
1727    unsigned int ret_val = FALSE;
1728/*
1729** Enter configuration mode
1730*/
1731    SMC37c669_config_mode( TRUE );
1732
1733    switch ( func ) {
1734    	case SERIAL_0:
1735	    base_addr =
1736		SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
1737	    dev_ok = TRUE;
1738	    break;
1739	case SERIAL_1:
1740	    base_addr =
1741		SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
1742	    dev_ok = TRUE;
1743	    break;
1744	case PARALLEL_0:
1745	    base_addr =
1746		SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
1747	    dev_ok = TRUE;
1748	    break;
1749	case FLOPPY_0:
1750	    base_addr =
1751		SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
1752	    dev_ok = TRUE;
1753	    break;
1754	case IDE_0:
1755	    base_addr =
1756		SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
1757	    dev_ok = TRUE;
1758	    break;
1759    }
1760/*
1761** If we have a valid device, check base_addr<7:6> to see if the
1762** device is enabled (mapped).
1763*/
1764    if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
1765/*
1766** The mapping is not disabled, so assume that the function is
1767** enabled.
1768*/
1769    	ret_val = TRUE;
1770    }
1771/*
1772** Exit configuration mode
1773*/
1774    SMC37c669_config_mode( FALSE );
1775
1776    return ret_val;
1777}
1778
1779
1780
1781
1782/*
1783**++
1784**  FUNCTIONAL DESCRIPTION:
1785**
1786**      This function displays the current state of the SMC37c699
1787**	Super I/O controller's device functions.
1788**
1789**  FORMAL PARAMETERS:
1790**
1791**      None
1792**
1793**  RETURN VALUE:
1794**
1795**      None
1796**
1797**  SIDE EFFECTS:
1798**
1799**      None
1800**
1801**--
1802*/
1803void __init SMC37c669_display_device_info ( void )
1804{
1805    if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
1806    	printk( "  Serial 0:    Enabled [ Port 0x%x, IRQ %d ]\n",
1807		 local_config[ SERIAL_0 ].port1,
1808		 local_config[ SERIAL_0 ].irq
1809	);
1810    }
1811    else {
1812    	printk( "  Serial 0:    Disabled\n" );
1813    }
1814
1815    if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
1816    	printk( "  Serial 1:    Enabled [ Port 0x%x, IRQ %d ]\n",
1817		 local_config[ SERIAL_1 ].port1,
1818		 local_config[ SERIAL_1 ].irq
1819	);
1820    }
1821    else {
1822    	printk( "  Serial 1:    Disabled\n" );
1823    }
1824
1825    if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
1826    	printk( "  Parallel:    Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1827		 local_config[ PARALLEL_0 ].port1,
1828		 local_config[ PARALLEL_0 ].irq,
1829		 local_config[ PARALLEL_0 ].drq
1830	);
1831    }
1832    else {
1833    	printk( "  Parallel:    Disabled\n" );
1834    }
1835
1836    if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
1837    	printk( "  Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1838		 local_config[ FLOPPY_0 ].port1,
1839		 local_config[ FLOPPY_0 ].irq,
1840		 local_config[ FLOPPY_0 ].drq
1841	);
1842    }
1843    else {
1844    	printk( "  Floppy Ctrl: Disabled\n" );
1845    }
1846
1847    if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
1848    	printk( "  IDE 0:       Enabled [ Port 0x%x, IRQ %d ]\n",
1849		 local_config[ IDE_0 ].port1,
1850		 local_config[ IDE_0 ].irq
1851	);
1852    }
1853    else {
1854    	printk( "  IDE 0:       Disabled\n" );
1855    }
1856}
1857
1858
1859/*
1860**++
1861**  FUNCTIONAL DESCRIPTION:
1862**
1863**      This function puts the SMC37c669 Super I/O controller into,
1864**	and takes it out of, configuration mode.
1865**
1866**  FORMAL PARAMETERS:
1867**
1868**      enable:
1869**          TRUE to enter configuration mode, FALSE to exit.
1870**
1871**  RETURN VALUE:
1872**
1873**      None
1874**
1875**  SIDE EFFECTS:
1876**
1877**      The SMC37c669 controller may be left in configuration mode.
1878**
1879**--
1880*/
1881static void __init SMC37c669_config_mode(
1882    unsigned int enable )
1883{
1884    if ( enable ) {
1885/*
1886** To enter configuration mode, two writes in succession to the index
1887** port are required.  If a write to another address or port occurs
1888** between these two writes, the chip does not enter configuration
1889** mode.  Therefore, a spinlock is placed around the two writes to
1890** guarantee that they complete uninterrupted.
1891*/
1892	spin_lock(&smc_lock);
1893    	wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1894    	wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1895	spin_unlock(&smc_lock);
1896    }
1897    else {
1898    	wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
1899    }
1900}
1901
1902/*
1903**++
1904**  FUNCTIONAL DESCRIPTION:
1905**
1906**      This function reads an SMC37c669 Super I/O controller
1907**	configuration register.  This function assumes that the
1908**	device is already in configuration mode.
1909**
1910**  FORMAL PARAMETERS:
1911**
1912**      index:
1913**          Index value of configuration register to read
1914**
1915**  RETURN VALUE:
1916**
1917**      Data read from configuration register
1918**
1919**  SIDE EFFECTS:
1920**
1921**      None
1922**
1923**--
1924*/
1925static unsigned char __init SMC37c669_read_config(
1926    unsigned char index )
1927{
1928    unsigned char data;
1929
1930    wb( &SMC37c669->index_port, index );
1931    data = rb( &SMC37c669->data_port );
1932    return data;
1933}
1934
1935/*
1936**++
1937**  FUNCTIONAL DESCRIPTION:
1938**
1939**      This function writes an SMC37c669 Super I/O controller
1940**	configuration register.  This function assumes that the
1941**	device is already in configuration mode.
1942**
1943**  FORMAL PARAMETERS:
1944**
1945**      index:
1946**          Index of configuration register to write
1947**
1948**      data:
1949**          Data to be written
1950**
1951**  RETURN VALUE:
1952**
1953**      None
1954**
1955**  SIDE EFFECTS:
1956**
1957**      None
1958**
1959**--
1960*/
1961static void __init SMC37c669_write_config(
1962    unsigned char index,
1963    unsigned char data )
1964{
1965    wb( &SMC37c669->index_port, index );
1966    wb( &SMC37c669->data_port, data );
1967}
1968
1969
1970/*
1971**++
1972**  FUNCTIONAL DESCRIPTION:
1973**
1974**      This function initializes the local device
1975**	configuration storage.  This function assumes
1976**	that the device is already in configuration
1977**	mode.
1978**
1979**  FORMAL PARAMETERS:
1980**
1981**      None
1982**
1983**  RETURN VALUE:
1984**
1985**      None
1986**
1987**  SIDE EFFECTS:
1988**
1989**      Local storage for device configuration information
1990**	is initialized.
1991**
1992**--
1993*/
1994static void __init SMC37c669_init_local_config ( void )
1995{
1996    SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
1997    SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
1998    SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
1999    SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
2000    SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
2001    SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
2002    SMC37c669_IDE_ADDRESS_REGISTER ide_base;
2003    SMC37c669_IDE_ADDRESS_REGISTER ide_alt;
2004
2005/*
2006** Get serial port 1 base address
2007*/
2008    uart_base.as_uchar =
2009	SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
2010/*
2011** Get IRQs for serial ports 1 & 2
2012*/
2013    uart_irqs.as_uchar =
2014	SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
2015/*
2016** Store local configuration information for serial port 1
2017*/
2018    local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
2019    local_config[SERIAL_0].irq =
2020	SMC37c669_xlate_irq(
2021	    SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq )
2022	);
2023/*
2024** Get serial port 2 base address
2025*/
2026    uart_base.as_uchar =
2027	SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
2028/*
2029** Store local configuration information for serial port 2
2030*/
2031    local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
2032    local_config[SERIAL_1].irq =
2033	SMC37c669_xlate_irq(
2034	    SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq )
2035	);
2036/*
2037** Get parallel port base address
2038*/
2039    ppt_base.as_uchar =
2040	SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
2041/*
2042** Get IRQs for parallel port and floppy controller
2043*/
2044    ppt_fdc_irqs.as_uchar =
2045	SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
2046/*
2047** Get DRQs for parallel port and floppy controller
2048*/
2049    ppt_fdc_drqs.as_uchar =
2050	SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
2051/*
2052** Store local configuration information for parallel port
2053*/
2054    local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
2055    local_config[PARALLEL_0].irq =
2056	SMC37c669_xlate_irq(
2057	    SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
2058	);
2059    local_config[PARALLEL_0].drq =
2060	SMC37c669_xlate_drq(
2061	    SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
2062	);
2063/*
2064** Get floppy controller base address
2065*/
2066    fdc_base.as_uchar =
2067	SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
2068/*
2069** Store local configuration information for floppy controller
2070*/
2071    local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
2072    local_config[FLOPPY_0].irq =
2073	SMC37c669_xlate_irq(
2074	    SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
2075	);
2076    local_config[FLOPPY_0].drq =
2077	SMC37c669_xlate_drq(
2078	    SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
2079	);
2080/*
2081** Get IDE controller base address
2082*/
2083    ide_base.as_uchar =
2084	SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
2085/*
2086** Get IDE alternate status base address
2087*/
2088    ide_alt.as_uchar =
2089	SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
2090/*
2091** Store local configuration information for IDE controller
2092*/
2093    local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
2094    local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
2095    local_config[IDE_0].irq = 14;
2096}
2097
2098
2099/*
2100**++
2101**  FUNCTIONAL DESCRIPTION:
2102**
2103**      This function returns a pointer to the local shadow
2104**	configuration of the requested device function.
2105**
2106**  FORMAL PARAMETERS:
2107**
2108**      func:
2109**          Which device function
2110**
2111**  RETURN VALUE:
2112**
2113**      Returns a pointer to the DEVICE_CONFIG structure for the
2114**	requested function, otherwise, NULL.
2115**
2116**  SIDE EFFECTS:
2117**
2118**      {@description or none@}
2119**
2120**--
2121*/
2122static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
2123{
2124    struct DEVICE_CONFIG *cp = NULL;
2125
2126    switch ( func ) {
2127    	case SERIAL_0:
2128	    cp = &local_config[ SERIAL_0 ];
2129	    break;
2130	case SERIAL_1:
2131	    cp = &local_config[ SERIAL_1 ];
2132	    break;
2133	case PARALLEL_0:
2134	    cp = &local_config[ PARALLEL_0 ];
2135	    break;
2136	case FLOPPY_0:
2137	    cp = &local_config[ FLOPPY_0 ];
2138	    break;
2139	case IDE_0:
2140	    cp = &local_config[ IDE_0 ];
2141	    break;
2142    }
2143    return cp;
2144}
2145
2146/*
2147**++
2148**  FUNCTIONAL DESCRIPTION:
2149**
2150**      This function translates IRQs back and forth between ISA
2151**	IRQs and SMC37c669 device IRQs.
2152**
2153**  FORMAL PARAMETERS:
2154**
2155**      irq:
2156**          The IRQ to translate
2157**
2158**  RETURN VALUE:
2159**
2160**      Returns the translated IRQ, otherwise, returns -1.
2161**
2162**  SIDE EFFECTS:
2163**
2164**      {@description or none@}
2165**
2166**--
2167*/
2168static int __init SMC37c669_xlate_irq ( int irq )
2169{
2170    int i, translated_irq = -1;
2171
2172    if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
2173/*
2174** We are translating a device IRQ to an ISA IRQ
2175*/
2176    	for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
2177	    if ( irq == SMC37c669_irq_table[i].device_irq ) {
2178	    	translated_irq = SMC37c669_irq_table[i].isa_irq;
2179		break;
2180	    }
2181	}
2182    }
2183    else {
2184/*
2185** We are translating an ISA IRQ to a device IRQ
2186*/
2187    	for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
2188	    if ( irq == SMC37c669_irq_table[i].isa_irq ) {
2189	    	translated_irq = SMC37c669_irq_table[i].device_irq;
2190		break;
2191	    }
2192	}
2193    }
2194    return translated_irq;
2195}
2196
2197
2198/*
2199**++
2200**  FUNCTIONAL DESCRIPTION:
2201**
2202**      This function translates DMA channels back and forth between
2203**	ISA DMA channels and SMC37c669 device DMA channels.
2204**
2205**  FORMAL PARAMETERS:
2206**
2207**      drq:
2208**          The DMA channel to translate
2209**
2210**  RETURN VALUE:
2211**
2212**      Returns the translated DMA channel, otherwise, returns -1
2213**
2214**  SIDE EFFECTS:
2215**
2216**      {@description or none@}
2217**
2218**--
2219*/
2220static int __init SMC37c669_xlate_drq ( int drq )
2221{
2222    int i, translated_drq = -1;
2223
2224    if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
2225/*
2226** We are translating a device DMA channel to an ISA DMA channel
2227*/
2228    	for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
2229	    if ( drq == SMC37c669_drq_table[i].device_drq ) {
2230	    	translated_drq = SMC37c669_drq_table[i].isa_drq;
2231		break;
2232	    }
2233	}
2234    }
2235    else {
2236/*
2237** We are translating an ISA DMA channel to a device DMA channel
2238*/
2239    	for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
2240	    if ( drq == SMC37c669_drq_table[i].isa_drq ) {
2241	    	translated_drq = SMC37c669_drq_table[i].device_drq;
2242		break;
2243	    }
2244	}
2245    }
2246    return translated_drq;
2247}
2248
2249
2250void __init
2251SMC37c669_dump_registers(void)
2252{
2253  int i;
2254  for (i = 0; i <= 0x29; i++)
2255    printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
2256}
2257/*+
2258 * ============================================================================
2259 * = SMC_init - SMC37c669 Super I/O controller initialization                 =
2260 * ============================================================================
2261 *
2262 * OVERVIEW:
2263 *
2264 *      This routine configures and enables device functions on the
2265 *      SMC37c669 Super I/O controller.
2266 *
2267 * FORM OF CALL:
2268 *
2269 *      SMC_init( );
2270 *
2271 * RETURNS:
2272 *
2273 *      Nothing
2274 *
2275 * ARGUMENTS:
2276 *
2277 *      None
2278 *
2279 * SIDE EFFECTS:
2280 *
2281 *      None
2282 *
2283 */
2284void __init SMC669_Init ( int index )
2285{
2286    SMC37c669_CONFIG_REGS *SMC_base;
2287    unsigned long flags;
2288
2289    local_irq_save(flags);
2290    if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
2291#if SMC_DEBUG
2292	SMC37c669_config_mode( TRUE );
2293	SMC37c669_dump_registers( );
2294	SMC37c669_config_mode( FALSE );
2295        SMC37c669_display_device_info( );
2296#endif
2297        SMC37c669_disable_device( SERIAL_0 );
2298        SMC37c669_configure_device(
2299            SERIAL_0,
2300            COM1_BASE,
2301            COM1_IRQ,
2302            -1
2303        );
2304        SMC37c669_enable_device( SERIAL_0 );
2305
2306        SMC37c669_disable_device( SERIAL_1 );
2307        SMC37c669_configure_device(
2308            SERIAL_1,
2309            COM2_BASE,
2310            COM2_IRQ,
2311            -1
2312        );
2313        SMC37c669_enable_device( SERIAL_1 );
2314
2315        SMC37c669_disable_device( PARALLEL_0 );
2316        SMC37c669_configure_device(
2317            PARALLEL_0,
2318            PARP_BASE,
2319            PARP_IRQ,
2320            PARP_DRQ
2321        );
2322        SMC37c669_enable_device( PARALLEL_0 );
2323
2324        SMC37c669_disable_device( FLOPPY_0 );
2325        SMC37c669_configure_device(
2326            FLOPPY_0,
2327            FDC_BASE,
2328            FDC_IRQ,
2329            FDC_DRQ
2330        );
2331        SMC37c669_enable_device( FLOPPY_0 );
2332
2333	/* Wake up sometimes forgotten floppy, especially on DP264. */
2334	outb(0xc, 0x3f2);
2335
2336        SMC37c669_disable_device( IDE_0 );
2337
2338#if SMC_DEBUG
2339	SMC37c669_config_mode( TRUE );
2340	SMC37c669_dump_registers( );
2341	SMC37c669_config_mode( FALSE );
2342        SMC37c669_display_device_info( );
2343#endif
2344	local_irq_restore(flags);
2345        printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",
2346		SMC_base );
2347    }
2348    else {
2349	local_irq_restore(flags);
2350#if SMC_DEBUG
2351        printk( "No SMC37c669 Super I/O Controller found\n" );
2352#endif
2353    }
2354}
2355