xref: /openbmc/linux/arch/alpha/kernel/smc37c669.c (revision c67fdc1f)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * SMC 37C669 initialization code
31da177e4SLinus Torvalds  */
41da177e4SLinus Torvalds #include <linux/kernel.h>
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <linux/mm.h>
71da177e4SLinus Torvalds #include <linux/init.h>
81da177e4SLinus Torvalds #include <linux/delay.h>
91da177e4SLinus Torvalds #include <linux/spinlock.h>
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <asm/hwrpb.h>
121da177e4SLinus Torvalds #include <asm/io.h>
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #if 0
151da177e4SLinus Torvalds # define DBG_DEVS(args)         printk args
161da177e4SLinus Torvalds #else
171da177e4SLinus Torvalds # define DBG_DEVS(args)
181da177e4SLinus Torvalds #endif
191da177e4SLinus Torvalds 
201da177e4SLinus Torvalds #define KB              1024
211da177e4SLinus Torvalds #define MB              (1024*KB)
221da177e4SLinus Torvalds #define GB              (1024*MB)
231da177e4SLinus Torvalds 
241da177e4SLinus Torvalds #define SMC_DEBUG   0
251da177e4SLinus Torvalds 
261da177e4SLinus Torvalds /* File:	smcc669_def.h
271da177e4SLinus Torvalds  *
281da177e4SLinus Torvalds  * Copyright (C) 1997 by
291da177e4SLinus Torvalds  * Digital Equipment Corporation, Maynard, Massachusetts.
301da177e4SLinus Torvalds  * All rights reserved.
311da177e4SLinus Torvalds  *
321da177e4SLinus Torvalds  * This software is furnished under a license and may be used and copied
331da177e4SLinus Torvalds  * only  in  accordance  of  the  terms  of  such  license  and with the
341da177e4SLinus Torvalds  * inclusion of the above copyright notice. This software or  any  other
351da177e4SLinus Torvalds  * copies thereof may not be provided or otherwise made available to any
361da177e4SLinus Torvalds  * other person.  No title to and  ownership of the  software is  hereby
371da177e4SLinus Torvalds  * transferred.
381da177e4SLinus Torvalds  *
391da177e4SLinus Torvalds  * The information in this software is  subject to change without notice
401da177e4SLinus Torvalds  * and  should  not  be  construed  as a commitment by Digital Equipment
411da177e4SLinus Torvalds  * Corporation.
421da177e4SLinus Torvalds  *
431da177e4SLinus Torvalds  * Digital assumes no responsibility for the use  or  reliability of its
441da177e4SLinus Torvalds  * software on equipment which is not supplied by Digital.
451da177e4SLinus Torvalds  *
461da177e4SLinus Torvalds  *
471da177e4SLinus Torvalds  * Abstract:
481da177e4SLinus Torvalds  *
491da177e4SLinus Torvalds  *	This file contains header definitions for the SMC37c669
501da177e4SLinus Torvalds  *	Super I/O controller.
511da177e4SLinus Torvalds  *
521da177e4SLinus Torvalds  * Author:
531da177e4SLinus Torvalds  *
541da177e4SLinus Torvalds  *	Eric Rasmussen
551da177e4SLinus Torvalds  *
561da177e4SLinus Torvalds  * Modification History:
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  *	er	28-Jan-1997	Initial Entry
591da177e4SLinus Torvalds  */
601da177e4SLinus Torvalds 
611da177e4SLinus Torvalds #ifndef __SMC37c669_H
621da177e4SLinus Torvalds #define __SMC37c669_H
631da177e4SLinus Torvalds 
641da177e4SLinus Torvalds /*
651da177e4SLinus Torvalds ** Macros for handling device IRQs
661da177e4SLinus Torvalds **
671da177e4SLinus Torvalds ** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)
681da177e4SLinus Torvalds ** to device IRQs (A - H).
691da177e4SLinus Torvalds */
701da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_MASK	0x80000000
711da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ( __i )	\
721da177e4SLinus Torvalds 	((SMC37c669_DEVICE_IRQ_MASK) | (__i))
731da177e4SLinus Torvalds #define SMC37c669_IS_DEVICE_IRQ(__i)	\
741da177e4SLinus Torvalds 	(((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
751da177e4SLinus Torvalds #define SMC37c669_RAW_DEVICE_IRQ(__i)	\
761da177e4SLinus Torvalds 	((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds /*
791da177e4SLinus Torvalds ** Macros for handling device DRQs
801da177e4SLinus Torvalds **
811da177e4SLinus Torvalds ** The mask acts as a flag used in mapping actual ISA DMA
821da177e4SLinus Torvalds ** channels to device DMA channels (A - C).
831da177e4SLinus Torvalds */
841da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_MASK	0x80000000
851da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ(__d)	\
861da177e4SLinus Torvalds 	((SMC37c669_DEVICE_DRQ_MASK) | (__d))
871da177e4SLinus Torvalds #define SMC37c669_IS_DEVICE_DRQ(__d)	\
881da177e4SLinus Torvalds 	(((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
891da177e4SLinus Torvalds #define SMC37c669_RAW_DEVICE_DRQ(__d)	\
901da177e4SLinus Torvalds 	((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds #define SMC37c669_DEVICE_ID	0x3
931da177e4SLinus Torvalds 
941da177e4SLinus Torvalds /*
951da177e4SLinus Torvalds ** SMC37c669 Device Function Definitions
961da177e4SLinus Torvalds */
971da177e4SLinus Torvalds #define SERIAL_0	0
981da177e4SLinus Torvalds #define SERIAL_1	1
991da177e4SLinus Torvalds #define PARALLEL_0	2
1001da177e4SLinus Torvalds #define FLOPPY_0	3
1011da177e4SLinus Torvalds #define IDE_0		4
1021da177e4SLinus Torvalds #define NUM_FUNCS	5
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds /*
1051da177e4SLinus Torvalds ** Default Device Function Mappings
1061da177e4SLinus Torvalds */
1071da177e4SLinus Torvalds #define COM1_BASE	0x3F8
1081da177e4SLinus Torvalds #define COM1_IRQ	4
1091da177e4SLinus Torvalds #define COM2_BASE	0x2F8
1101da177e4SLinus Torvalds #define COM2_IRQ	3
1111da177e4SLinus Torvalds #define PARP_BASE	0x3BC
1121da177e4SLinus Torvalds #define PARP_IRQ	7
1131da177e4SLinus Torvalds #define PARP_DRQ	3
1141da177e4SLinus Torvalds #define FDC_BASE	0x3F0
1151da177e4SLinus Torvalds #define FDC_IRQ		6
1161da177e4SLinus Torvalds #define FDC_DRQ		2
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds /*
1191da177e4SLinus Torvalds ** Configuration On/Off Key Definitions
1201da177e4SLinus Torvalds */
1211da177e4SLinus Torvalds #define SMC37c669_CONFIG_ON_KEY		0x55
1221da177e4SLinus Torvalds #define SMC37c669_CONFIG_OFF_KEY	0xAA
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds /*
1251da177e4SLinus Torvalds ** SMC 37c669 Device IRQs
1261da177e4SLinus Torvalds */
1271da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_A	    ( SMC37c669_DEVICE_IRQ( 0x01 ) )
1281da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_B	    ( SMC37c669_DEVICE_IRQ( 0x02 ) )
1291da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_C	    ( SMC37c669_DEVICE_IRQ( 0x03 ) )
1301da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_D	    ( SMC37c669_DEVICE_IRQ( 0x04 ) )
1311da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_E	    ( SMC37c669_DEVICE_IRQ( 0x05 ) )
1321da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_F	    ( SMC37c669_DEVICE_IRQ( 0x06 ) )
1331da177e4SLinus Torvalds /*      SMC37c669_DEVICE_IRQ_G	    *** RESERVED ***/
1341da177e4SLinus Torvalds #define SMC37c669_DEVICE_IRQ_H	    ( SMC37c669_DEVICE_IRQ( 0x08 ) )
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds /*
1371da177e4SLinus Torvalds ** SMC 37c669 Device DMA Channel Definitions
1381da177e4SLinus Torvalds */
1391da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_A		    ( SMC37c669_DEVICE_DRQ( 0x01 ) )
1401da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_B		    ( SMC37c669_DEVICE_DRQ( 0x02 ) )
1411da177e4SLinus Torvalds #define SMC37c669_DEVICE_DRQ_C		    ( SMC37c669_DEVICE_DRQ( 0x03 ) )
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds /*
1441da177e4SLinus Torvalds ** Configuration Register Index Definitions
1451da177e4SLinus Torvalds */
1461da177e4SLinus Torvalds #define SMC37c669_CR00_INDEX	    0x00
1471da177e4SLinus Torvalds #define SMC37c669_CR01_INDEX	    0x01
1481da177e4SLinus Torvalds #define SMC37c669_CR02_INDEX	    0x02
1491da177e4SLinus Torvalds #define SMC37c669_CR03_INDEX	    0x03
1501da177e4SLinus Torvalds #define SMC37c669_CR04_INDEX	    0x04
1511da177e4SLinus Torvalds #define SMC37c669_CR05_INDEX	    0x05
1521da177e4SLinus Torvalds #define SMC37c669_CR06_INDEX	    0x06
1531da177e4SLinus Torvalds #define SMC37c669_CR07_INDEX	    0x07
1541da177e4SLinus Torvalds #define SMC37c669_CR08_INDEX	    0x08
1551da177e4SLinus Torvalds #define SMC37c669_CR09_INDEX	    0x09
1561da177e4SLinus Torvalds #define SMC37c669_CR0A_INDEX	    0x0A
1571da177e4SLinus Torvalds #define SMC37c669_CR0B_INDEX	    0x0B
1581da177e4SLinus Torvalds #define SMC37c669_CR0C_INDEX	    0x0C
1591da177e4SLinus Torvalds #define SMC37c669_CR0D_INDEX	    0x0D
1601da177e4SLinus Torvalds #define SMC37c669_CR0E_INDEX	    0x0E
1611da177e4SLinus Torvalds #define SMC37c669_CR0F_INDEX	    0x0F
1621da177e4SLinus Torvalds #define SMC37c669_CR10_INDEX	    0x10
1631da177e4SLinus Torvalds #define SMC37c669_CR11_INDEX	    0x11
1641da177e4SLinus Torvalds #define SMC37c669_CR12_INDEX	    0x12
1651da177e4SLinus Torvalds #define SMC37c669_CR13_INDEX	    0x13
1661da177e4SLinus Torvalds #define SMC37c669_CR14_INDEX	    0x14
1671da177e4SLinus Torvalds #define SMC37c669_CR15_INDEX	    0x15
1681da177e4SLinus Torvalds #define SMC37c669_CR16_INDEX	    0x16
1691da177e4SLinus Torvalds #define SMC37c669_CR17_INDEX	    0x17
1701da177e4SLinus Torvalds #define SMC37c669_CR18_INDEX	    0x18
1711da177e4SLinus Torvalds #define SMC37c669_CR19_INDEX	    0x19
1721da177e4SLinus Torvalds #define SMC37c669_CR1A_INDEX	    0x1A
1731da177e4SLinus Torvalds #define SMC37c669_CR1B_INDEX	    0x1B
1741da177e4SLinus Torvalds #define SMC37c669_CR1C_INDEX	    0x1C
1751da177e4SLinus Torvalds #define SMC37c669_CR1D_INDEX	    0x1D
1761da177e4SLinus Torvalds #define SMC37c669_CR1E_INDEX	    0x1E
1771da177e4SLinus Torvalds #define SMC37c669_CR1F_INDEX	    0x1F
1781da177e4SLinus Torvalds #define SMC37c669_CR20_INDEX	    0x20
1791da177e4SLinus Torvalds #define SMC37c669_CR21_INDEX	    0x21
1801da177e4SLinus Torvalds #define SMC37c669_CR22_INDEX	    0x22
1811da177e4SLinus Torvalds #define SMC37c669_CR23_INDEX	    0x23
1821da177e4SLinus Torvalds #define SMC37c669_CR24_INDEX	    0x24
1831da177e4SLinus Torvalds #define SMC37c669_CR25_INDEX	    0x25
1841da177e4SLinus Torvalds #define SMC37c669_CR26_INDEX	    0x26
1851da177e4SLinus Torvalds #define SMC37c669_CR27_INDEX	    0x27
1861da177e4SLinus Torvalds #define SMC37c669_CR28_INDEX	    0x28
1871da177e4SLinus Torvalds #define SMC37c669_CR29_INDEX	    0x29
1881da177e4SLinus Torvalds 
1891da177e4SLinus Torvalds /*
1901da177e4SLinus Torvalds ** Configuration Register Alias Definitions
1911da177e4SLinus Torvalds */
1921da177e4SLinus Torvalds #define SMC37c669_DEVICE_ID_INDEX		    SMC37c669_CR0D_INDEX
1931da177e4SLinus Torvalds #define SMC37c669_DEVICE_REVISION_INDEX		    SMC37c669_CR0E_INDEX
1941da177e4SLinus Torvalds #define SMC37c669_FDC_BASE_ADDRESS_INDEX	    SMC37c669_CR20_INDEX
1951da177e4SLinus Torvalds #define SMC37c669_IDE_BASE_ADDRESS_INDEX	    SMC37c669_CR21_INDEX
1961da177e4SLinus Torvalds #define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX	    SMC37c669_CR22_INDEX
1971da177e4SLinus Torvalds #define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX	    SMC37c669_CR23_INDEX
1981da177e4SLinus Torvalds #define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX	    SMC37c669_CR24_INDEX
1991da177e4SLinus Torvalds #define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX	    SMC37c669_CR25_INDEX
2001da177e4SLinus Torvalds #define SMC37c669_PARALLEL_FDC_DRQ_INDEX	    SMC37c669_CR26_INDEX
2011da177e4SLinus Torvalds #define SMC37c669_PARALLEL_FDC_IRQ_INDEX	    SMC37c669_CR27_INDEX
2021da177e4SLinus Torvalds #define SMC37c669_SERIAL_IRQ_INDEX		    SMC37c669_CR28_INDEX
2031da177e4SLinus Torvalds 
2041da177e4SLinus Torvalds /*
2051da177e4SLinus Torvalds ** Configuration Register Definitions
2061da177e4SLinus Torvalds **
2071da177e4SLinus Torvalds ** The INDEX (write only) and DATA (read/write) ports are effective
2081da177e4SLinus Torvalds ** only when the chip is in the Configuration State.
2091da177e4SLinus Torvalds */
2101da177e4SLinus Torvalds typedef struct _SMC37c669_CONFIG_REGS {
2111da177e4SLinus Torvalds     unsigned char index_port;
2121da177e4SLinus Torvalds     unsigned char data_port;
2131da177e4SLinus Torvalds } SMC37c669_CONFIG_REGS;
2141da177e4SLinus Torvalds 
2151da177e4SLinus Torvalds /*
2161da177e4SLinus Torvalds ** CR00 - default value 0x28
2171da177e4SLinus Torvalds **
2181da177e4SLinus Torvalds **  IDE_EN (CR00<1:0>):
2191da177e4SLinus Torvalds **	0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
2201da177e4SLinus Torvalds **	11 - IRQ_H available as IRQ output,
2211da177e4SLinus Torvalds **	     IRRX2, IRTX2 available as alternate IR pins
2221da177e4SLinus Torvalds **	10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
2231da177e4SLinus Torvalds **
2241da177e4SLinus Torvalds **  VALID (CR00<7>):
2251da177e4SLinus Torvalds **	A high level on this software controlled bit can
2261da177e4SLinus Torvalds **	be used to indicate that a valid configuration
2271da177e4SLinus Torvalds **	cycle has occurred.  The control software must
2281da177e4SLinus Torvalds **	take care to set this bit at the appropriate times.
2291da177e4SLinus Torvalds **	Set to zero after power up.  This bit has no
2301da177e4SLinus Torvalds **	effect on any other hardware in the chip.
2311da177e4SLinus Torvalds **
2321da177e4SLinus Torvalds */
2331da177e4SLinus Torvalds typedef union _SMC37c669_CR00 {
2341da177e4SLinus Torvalds     unsigned char as_uchar;
2351da177e4SLinus Torvalds     struct {
2361da177e4SLinus Torvalds     	unsigned ide_en : 2;	    /* See note above		*/
2371da177e4SLinus Torvalds 	unsigned reserved1 : 1;	    /* RAZ			*/
2381da177e4SLinus Torvalds 	unsigned fdc_pwr : 1;	    /* 1 = supply power to FDC  */
2391da177e4SLinus Torvalds 	unsigned reserved2 : 3;	    /* Read as 010b		*/
2401da177e4SLinus Torvalds 	unsigned valid : 1;	    /* See note above		*/
2411da177e4SLinus Torvalds     }	by_field;
2421da177e4SLinus Torvalds } SMC37c669_CR00;
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds /*
2451da177e4SLinus Torvalds ** CR01 - default value 0x9C
2461da177e4SLinus Torvalds */
2471da177e4SLinus Torvalds typedef union _SMC37c669_CR01 {
2481da177e4SLinus Torvalds     unsigned char as_uchar;
2491da177e4SLinus Torvalds     struct {
2501da177e4SLinus Torvalds     	unsigned reserved1 : 2;	    /* RAZ			    */
2511da177e4SLinus Torvalds 	unsigned ppt_pwr : 1;	    /* 1 = supply power to PPT	    */
2521da177e4SLinus Torvalds 	unsigned ppt_mode : 1;	    /* 1 = Printer mode, 0 = EPP    */
2531da177e4SLinus Torvalds 	unsigned reserved2 : 1;	    /* Read as 1		    */
2541da177e4SLinus Torvalds 	unsigned reserved3 : 2;	    /* RAZ			    */
2551da177e4SLinus Torvalds 	unsigned lock_crx: 1;	    /* Lock CR00 - CR18		    */
2561da177e4SLinus Torvalds     }	by_field;
2571da177e4SLinus Torvalds } SMC37c669_CR01;
2581da177e4SLinus Torvalds 
2591da177e4SLinus Torvalds /*
2601da177e4SLinus Torvalds ** CR02 - default value 0x88
2611da177e4SLinus Torvalds */
2621da177e4SLinus Torvalds typedef union _SMC37c669_CR02 {
2631da177e4SLinus Torvalds     unsigned char as_uchar;
2641da177e4SLinus Torvalds     struct {
2651da177e4SLinus Torvalds     	unsigned reserved1 : 3;	    /* RAZ			    */
2661da177e4SLinus Torvalds 	unsigned uart1_pwr : 1;	    /* 1 = supply power to UART1    */
2671da177e4SLinus Torvalds 	unsigned reserved2 : 3;	    /* RAZ			    */
2681da177e4SLinus Torvalds 	unsigned uart2_pwr : 1;	    /* 1 = supply power to UART2    */
2691da177e4SLinus Torvalds     }	by_field;
2701da177e4SLinus Torvalds } SMC37c669_CR02;
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds /*
2731da177e4SLinus Torvalds ** CR03 - default value 0x78
2741da177e4SLinus Torvalds **
2751da177e4SLinus Torvalds **  CR03<7>	CR03<2>	    Pin 94
2761da177e4SLinus Torvalds **  -------	-------	    ------
2771da177e4SLinus Torvalds **     0	   X	    DRV2 (input)
2781da177e4SLinus Torvalds **     1	   0	    ADRX
2791da177e4SLinus Torvalds **     1	   1	    IRQ_B
2801da177e4SLinus Torvalds **
2811da177e4SLinus Torvalds **  CR03<6>	CR03<5>	    Op Mode
2821da177e4SLinus Torvalds **  -------	-------	    -------
2831da177e4SLinus Torvalds **     0	   0	    Model 30
2841da177e4SLinus Torvalds **     0	   1	    PS/2
2851da177e4SLinus Torvalds **     1	   0	    Reserved
2861da177e4SLinus Torvalds **     1	   1	    AT Mode
2871da177e4SLinus Torvalds */
2881da177e4SLinus Torvalds typedef union _SMC37c669_CR03 {
2891da177e4SLinus Torvalds     unsigned char as_uchar;
2901da177e4SLinus Torvalds     struct {
2911da177e4SLinus Torvalds     	unsigned pwrgd_gamecs : 1;  /* 1 = PWRGD, 0 = GAMECS	    */
2921da177e4SLinus Torvalds 	unsigned fdc_mode2 : 1;	    /* 1 = Enhanced Mode 2	    */
2931da177e4SLinus Torvalds 	unsigned pin94_0 : 1;	    /* See note above		    */
2941da177e4SLinus Torvalds 	unsigned reserved1 : 1;	    /* RAZ			    */
2951da177e4SLinus Torvalds 	unsigned drvden : 1;	    /* 1 = high, 0 - output	    */
2961da177e4SLinus Torvalds 	unsigned op_mode : 2;	    /* See note above		    */
2971da177e4SLinus Torvalds 	unsigned pin94_1 : 1;	    /* See note above		    */
2981da177e4SLinus Torvalds     }	by_field;
2991da177e4SLinus Torvalds } SMC37c669_CR03;
3001da177e4SLinus Torvalds 
3011da177e4SLinus Torvalds /*
3021da177e4SLinus Torvalds ** CR04 - default value 0x00
3031da177e4SLinus Torvalds **
3041da177e4SLinus Torvalds **  PP_EXT_MODE:
3051da177e4SLinus Torvalds **	If CR01<PP_MODE> = 0 and PP_EXT_MODE =
3061da177e4SLinus Torvalds **	    00 - Standard and Bidirectional
3071da177e4SLinus Torvalds **	    01 - EPP mode and SPP
3081da177e4SLinus Torvalds **	    10 - ECP mode
3091da177e4SLinus Torvalds **		 In this mode, 2 drives can be supported
3101da177e4SLinus Torvalds **		 directly, 3 or 4 drives must use external
3111da177e4SLinus Torvalds **		 4 drive support.  SPP can be selected
3121da177e4SLinus Torvalds **		 through the ECR register of ECP as mode 000.
3131da177e4SLinus Torvalds **	    11 - ECP mode and EPP mode
3141da177e4SLinus Torvalds **		 In this mode, 2 drives can be supported
3151da177e4SLinus Torvalds **		 directly, 3 or 4 drives must use external
3161da177e4SLinus Torvalds **		 4 drive support.  SPP can be selected
3171da177e4SLinus Torvalds **		 through the ECR register of ECP as mode 000.
3181da177e4SLinus Torvalds **		 In this mode, EPP can be selected through
3191da177e4SLinus Torvalds **		 the ECR register of ECP as mode 100.
3201da177e4SLinus Torvalds **
3211da177e4SLinus Torvalds **  PP_FDC:
3221da177e4SLinus Torvalds **	00 - Normal
3231da177e4SLinus Torvalds **	01 - PPFD1
3241da177e4SLinus Torvalds **	10 - PPFD2
3251da177e4SLinus Torvalds **	11 - Reserved
3261da177e4SLinus Torvalds **
3271da177e4SLinus Torvalds **  MIDI1:
3281da177e4SLinus Torvalds **	Serial Clock Select:
3291da177e4SLinus Torvalds **	    A low level on this bit disables MIDI support,
3301da177e4SLinus Torvalds **	    clock = divide by 13.  A high level on this
3311da177e4SLinus Torvalds **	    bit enables MIDI support, clock = divide by 12.
3321da177e4SLinus Torvalds **
3331da177e4SLinus Torvalds **	MIDI operates at 31.25 Kbps which can be derived
3341da177e4SLinus Torvalds **	from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
3351da177e4SLinus Torvalds **
3361da177e4SLinus Torvalds **  ALT_IO:
3371da177e4SLinus Torvalds **	0 - Use pins IRRX, IRTX
3381da177e4SLinus Torvalds **	1 - Use pins IRRX2, IRTX2
3391da177e4SLinus Torvalds **
3401da177e4SLinus Torvalds **	If this bit is set, the IR receive and transmit
3411da177e4SLinus Torvalds **	functions will not be available on pins 25 and 26
3421da177e4SLinus Torvalds **	unless CR00<IDE_EN> = 11.
3431da177e4SLinus Torvalds */
3441da177e4SLinus Torvalds typedef union _SMC37c669_CR04 {
3451da177e4SLinus Torvalds     unsigned char as_uchar;
3461da177e4SLinus Torvalds     struct {
3471da177e4SLinus Torvalds     	unsigned ppt_ext_mode : 2;  /* See note above		    */
3481da177e4SLinus Torvalds 	unsigned ppt_fdc : 2;	    /* See note above		    */
3491da177e4SLinus Torvalds 	unsigned midi1 : 1;	    /* See note above		    */
3501da177e4SLinus Torvalds 	unsigned midi2 : 1;	    /* See note above		    */
3511da177e4SLinus Torvalds 	unsigned epp_type : 1;	    /* 0 = EPP 1.9, 1 = EPP 1.7	    */
3521da177e4SLinus Torvalds 	unsigned alt_io : 1;	    /* See note above		    */
3531da177e4SLinus Torvalds     }	by_field;
3541da177e4SLinus Torvalds } SMC37c669_CR04;
3551da177e4SLinus Torvalds 
3561da177e4SLinus Torvalds /*
3571da177e4SLinus Torvalds ** CR05 - default value 0x00
3581da177e4SLinus Torvalds **
3591da177e4SLinus Torvalds **  DEN_SEL:
3601da177e4SLinus Torvalds **	00 - Densel output normal
3611da177e4SLinus Torvalds **	01 - Reserved
3621da177e4SLinus Torvalds **	10 - Densel output 1
3631da177e4SLinus Torvalds **	11 - Densel output 0
3641da177e4SLinus Torvalds **
3651da177e4SLinus Torvalds */
3661da177e4SLinus Torvalds typedef union _SMC37c669_CR05 {
3671da177e4SLinus Torvalds     unsigned char as_uchar;
3681da177e4SLinus Torvalds     struct {
3691da177e4SLinus Torvalds     	unsigned reserved1 : 2;	    /* RAZ					*/
3701da177e4SLinus Torvalds 	unsigned fdc_dma_mode : 1;  /* 0 = burst, 1 = non-burst			*/
3711da177e4SLinus Torvalds 	unsigned den_sel : 2;	    /* See note above				*/
3721da177e4SLinus Torvalds 	unsigned swap_drv : 1;	    /* Swap the FDC motor selects		*/
3731da177e4SLinus Torvalds 	unsigned extx4 : 1;	    /* 0 = 2 drive, 1 = external 4 drive decode	*/
3741da177e4SLinus Torvalds 	unsigned reserved2 : 1;	    /* RAZ					*/
3751da177e4SLinus Torvalds     }	by_field;
3761da177e4SLinus Torvalds } SMC37c669_CR05;
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds /*
3791da177e4SLinus Torvalds ** CR06 - default value 0xFF
3801da177e4SLinus Torvalds */
3811da177e4SLinus Torvalds typedef union _SMC37c669_CR06 {
3821da177e4SLinus Torvalds     unsigned char as_uchar;
3831da177e4SLinus Torvalds     struct {
3841da177e4SLinus Torvalds     	unsigned floppy_a : 2;	    /* Type of floppy drive A	    */
3851da177e4SLinus Torvalds 	unsigned floppy_b : 2;	    /* Type of floppy drive B	    */
3861da177e4SLinus Torvalds 	unsigned floppy_c : 2;	    /* Type of floppy drive C	    */
3871da177e4SLinus Torvalds 	unsigned floppy_d : 2;	    /* Type of floppy drive D	    */
3881da177e4SLinus Torvalds     }	by_field;
3891da177e4SLinus Torvalds } SMC37c669_CR06;
3901da177e4SLinus Torvalds 
3911da177e4SLinus Torvalds /*
3921da177e4SLinus Torvalds ** CR07 - default value 0x00
3931da177e4SLinus Torvalds **
3941da177e4SLinus Torvalds **  Auto Power Management CR07<7:4>:
3951da177e4SLinus Torvalds **	0 - Auto Powerdown disabled (default)
3961da177e4SLinus Torvalds **	1 - Auto Powerdown enabled
3971da177e4SLinus Torvalds **
3981da177e4SLinus Torvalds **	This bit is reset to the default state by POR or
3991da177e4SLinus Torvalds **	a hardware reset.
4001da177e4SLinus Torvalds **
4011da177e4SLinus Torvalds */
4021da177e4SLinus Torvalds typedef union _SMC37c669_CR07 {
4031da177e4SLinus Torvalds     unsigned char as_uchar;
4041da177e4SLinus Torvalds     struct {
4051da177e4SLinus Torvalds     	unsigned floppy_boot : 2;   /* 0 = A:, 1 = B:		    */
4061da177e4SLinus Torvalds 	unsigned reserved1 : 2;	    /* RAZ			    */
4071da177e4SLinus Torvalds 	unsigned ppt_en : 1;	    /* See note above		    */
4081da177e4SLinus Torvalds 	unsigned uart1_en : 1;	    /* See note above		    */
4091da177e4SLinus Torvalds 	unsigned uart2_en : 1;	    /* See note above		    */
4101da177e4SLinus Torvalds 	unsigned fdc_en : 1;	    /* See note above		    */
4111da177e4SLinus Torvalds     }	by_field;
4121da177e4SLinus Torvalds } SMC37c669_CR07;
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds /*
4151da177e4SLinus Torvalds ** CR08 - default value 0x00
4161da177e4SLinus Torvalds */
4171da177e4SLinus Torvalds typedef union _SMC37c669_CR08 {
4181da177e4SLinus Torvalds     unsigned char as_uchar;
4191da177e4SLinus Torvalds     struct {
4201da177e4SLinus Torvalds     	unsigned zero : 4;	    /* 0			    */
4211da177e4SLinus Torvalds 	unsigned addrx7_4 : 4;	    /* ADR<7:3> for ADRx decode	    */
4221da177e4SLinus Torvalds     }	by_field;
4231da177e4SLinus Torvalds } SMC37c669_CR08;
4241da177e4SLinus Torvalds 
4251da177e4SLinus Torvalds /*
4261da177e4SLinus Torvalds ** CR09 - default value 0x00
4271da177e4SLinus Torvalds **
4281da177e4SLinus Torvalds **  ADRx_CONFIG:
4291da177e4SLinus Torvalds **	00 - ADRx disabled
4301da177e4SLinus Torvalds **	01 - 1 byte decode A<3:0> = 0000b
4311da177e4SLinus Torvalds **	10 - 8 byte block decode A<3:0> = 0XXXb
4321da177e4SLinus Torvalds **	11 - 16 byte block decode A<3:0> = XXXXb
4331da177e4SLinus Torvalds **
4341da177e4SLinus Torvalds */
4351da177e4SLinus Torvalds typedef union _SMC37c669_CR09 {
4361da177e4SLinus Torvalds     unsigned char as_uchar;
4371da177e4SLinus Torvalds     struct {
4381da177e4SLinus Torvalds     	unsigned adra8 : 3;	    /* ADR<10:8> for ADRx decode    */
4391da177e4SLinus Torvalds 	unsigned reserved1 : 3;
4401da177e4SLinus Torvalds 	unsigned adrx_config : 2;   /* See note above		    */
4411da177e4SLinus Torvalds     }	by_field;
4421da177e4SLinus Torvalds } SMC37c669_CR09;
4431da177e4SLinus Torvalds 
4441da177e4SLinus Torvalds /*
4451da177e4SLinus Torvalds ** CR0A - default value 0x00
4461da177e4SLinus Torvalds */
4471da177e4SLinus Torvalds typedef union _SMC37c669_CR0A {
4481da177e4SLinus Torvalds     unsigned char as_uchar;
4491da177e4SLinus Torvalds     struct {
4501da177e4SLinus Torvalds     	unsigned ecp_fifo_threshold : 4;
4511da177e4SLinus Torvalds 	unsigned reserved1 : 4;
4521da177e4SLinus Torvalds     }	by_field;
4531da177e4SLinus Torvalds } SMC37c669_CR0A;
4541da177e4SLinus Torvalds 
4551da177e4SLinus Torvalds /*
4561da177e4SLinus Torvalds ** CR0B - default value 0x00
4571da177e4SLinus Torvalds */
4581da177e4SLinus Torvalds typedef union _SMC37c669_CR0B {
4591da177e4SLinus Torvalds     unsigned char as_uchar;
4601da177e4SLinus Torvalds     struct {
4611da177e4SLinus Torvalds     	unsigned fdd0_drtx : 2;	    /* FDD0 Data Rate Table	    */
4621da177e4SLinus Torvalds 	unsigned fdd1_drtx : 2;	    /* FDD1 Data Rate Table	    */
4631da177e4SLinus Torvalds 	unsigned fdd2_drtx : 2;	    /* FDD2 Data Rate Table	    */
4641da177e4SLinus Torvalds 	unsigned fdd3_drtx : 2;	    /* FDD3 Data Rate Table	    */
4651da177e4SLinus Torvalds     }	by_field;
4661da177e4SLinus Torvalds } SMC37c669_CR0B;
4671da177e4SLinus Torvalds 
4681da177e4SLinus Torvalds /*
4691da177e4SLinus Torvalds ** CR0C - default value 0x00
4701da177e4SLinus Torvalds **
4711da177e4SLinus Torvalds **  UART2_MODE:
4721da177e4SLinus Torvalds **	000 - Standard (default)
4731da177e4SLinus Torvalds **	001 - IrDA (HPSIR)
4741da177e4SLinus Torvalds **	010 - Amplitude Shift Keyed IR @500 KHz
4751da177e4SLinus Torvalds **	011 - Reserved
4761da177e4SLinus Torvalds **	1xx - Reserved
4771da177e4SLinus Torvalds **
4781da177e4SLinus Torvalds */
4791da177e4SLinus Torvalds typedef union _SMC37c669_CR0C {
4801da177e4SLinus Torvalds     unsigned char as_uchar;
4811da177e4SLinus Torvalds     struct {
4821da177e4SLinus Torvalds     	unsigned uart2_rcv_polarity : 1;    /* 1 = invert RX		*/
4831da177e4SLinus Torvalds 	unsigned uart2_xmit_polarity : 1;   /* 1 = invert TX		*/
4841da177e4SLinus Torvalds 	unsigned uart2_duplex : 1;	    /* 1 = full, 0 = half	*/
4851da177e4SLinus Torvalds 	unsigned uart2_mode : 3;	    /* See note above		*/
4861da177e4SLinus Torvalds 	unsigned uart1_speed : 1;	    /* 1 = high speed enabled	*/
4871da177e4SLinus Torvalds 	unsigned uart2_speed : 1;	    /* 1 = high speed enabled	*/
4881da177e4SLinus Torvalds     }	by_field;
4891da177e4SLinus Torvalds } SMC37c669_CR0C;
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds /*
4921da177e4SLinus Torvalds ** CR0D - default value 0x03
4931da177e4SLinus Torvalds **
4941da177e4SLinus Torvalds **  Device ID Register - read only
4951da177e4SLinus Torvalds */
4961da177e4SLinus Torvalds typedef union _SMC37c669_CR0D {
4971da177e4SLinus Torvalds     unsigned char as_uchar;
4981da177e4SLinus Torvalds     struct {
4991da177e4SLinus Torvalds     	unsigned device_id : 8;	    /* Returns 0x3 in this field    */
5001da177e4SLinus Torvalds     }	by_field;
5011da177e4SLinus Torvalds } SMC37c669_CR0D;
5021da177e4SLinus Torvalds 
5031da177e4SLinus Torvalds /*
5041da177e4SLinus Torvalds ** CR0E - default value 0x02
5051da177e4SLinus Torvalds **
5061da177e4SLinus Torvalds **  Device Revision Register - read only
5071da177e4SLinus Torvalds */
5081da177e4SLinus Torvalds typedef union _SMC37c669_CR0E {
5091da177e4SLinus Torvalds     unsigned char as_uchar;
5101da177e4SLinus Torvalds     struct {
5111da177e4SLinus Torvalds     	unsigned device_rev : 8;    /* Returns 0x2 in this field    */
5121da177e4SLinus Torvalds     }	by_field;
5131da177e4SLinus Torvalds } SMC37c669_CR0E;
5141da177e4SLinus Torvalds 
5151da177e4SLinus Torvalds /*
5161da177e4SLinus Torvalds ** CR0F - default value 0x00
5171da177e4SLinus Torvalds */
5181da177e4SLinus Torvalds typedef union _SMC37c669_CR0F {
5191da177e4SLinus Torvalds     unsigned char as_uchar;
5201da177e4SLinus Torvalds     struct {
5211da177e4SLinus Torvalds     	unsigned test0 : 1;	    /* Reserved - set to 0	    */
5221da177e4SLinus Torvalds 	unsigned test1 : 1;	    /* Reserved - set to 0	    */
5231da177e4SLinus Torvalds 	unsigned test2 : 1;	    /* Reserved - set to 0	    */
5241da177e4SLinus Torvalds 	unsigned test3 : 1;	    /* Reserved - set t0 0	    */
5251da177e4SLinus Torvalds 	unsigned test4 : 1;	    /* Reserved - set to 0	    */
5261da177e4SLinus Torvalds 	unsigned test5 : 1;	    /* Reserved - set t0 0	    */
5271da177e4SLinus Torvalds 	unsigned test6 : 1;	    /* Reserved - set t0 0	    */
5281da177e4SLinus Torvalds 	unsigned test7 : 1;	    /* Reserved - set to 0	    */
5291da177e4SLinus Torvalds     }	by_field;
5301da177e4SLinus Torvalds } SMC37c669_CR0F;
5311da177e4SLinus Torvalds 
5321da177e4SLinus Torvalds /*
5331da177e4SLinus Torvalds ** CR10 - default value 0x00
5341da177e4SLinus Torvalds */
5351da177e4SLinus Torvalds typedef union _SMC37c669_CR10 {
5361da177e4SLinus Torvalds     unsigned char as_uchar;
5371da177e4SLinus Torvalds     struct {
5381da177e4SLinus Torvalds     	unsigned reserved1 : 3;	     /* RAZ			    */
5391da177e4SLinus Torvalds 	unsigned pll_gain : 1;	     /* 1 = 3V, 2 = 5V operation    */
5401da177e4SLinus Torvalds 	unsigned pll_stop : 1;	     /* 1 = stop PLLs		    */
5411da177e4SLinus Torvalds 	unsigned ace_stop : 1;	     /* 1 = stop UART clocks	    */
5421da177e4SLinus Torvalds 	unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz  */
5431da177e4SLinus Torvalds 	unsigned ir_test : 1;	     /* Enable IR test mode	    */
5441da177e4SLinus Torvalds     }	by_field;
5451da177e4SLinus Torvalds } SMC37c669_CR10;
5461da177e4SLinus Torvalds 
5471da177e4SLinus Torvalds /*
5481da177e4SLinus Torvalds ** CR11 - default value 0x00
5491da177e4SLinus Torvalds */
5501da177e4SLinus Torvalds typedef union _SMC37c669_CR11 {
5511da177e4SLinus Torvalds     unsigned char as_uchar;
5521da177e4SLinus Torvalds     struct {
5531da177e4SLinus Torvalds     	unsigned ir_loopback : 1;   /* Internal IR loop back		    */
5541da177e4SLinus Torvalds 	unsigned test_10ms : 1;	    /* Test 10ms autopowerdown FDC timeout  */
5551da177e4SLinus Torvalds 	unsigned reserved1 : 6;	    /* RAZ				    */
5561da177e4SLinus Torvalds     }	by_field;
5571da177e4SLinus Torvalds } SMC37c669_CR11;
5581da177e4SLinus Torvalds 
5591da177e4SLinus Torvalds /*
5601da177e4SLinus Torvalds ** CR12 - CR1D are reserved registers
5611da177e4SLinus Torvalds */
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds /*
5641da177e4SLinus Torvalds ** CR1E - default value 0x80
5651da177e4SLinus Torvalds **
5661da177e4SLinus Torvalds **  GAMECS:
5671da177e4SLinus Torvalds **	00 - GAMECS disabled
5681da177e4SLinus Torvalds **	01 - 1 byte decode ADR<3:0> = 0001b
5691da177e4SLinus Torvalds **	10 - 8 byte block decode ADR<3:0> = 0XXXb
5701da177e4SLinus Torvalds **	11 - 16 byte block decode ADR<3:0> = XXXXb
5711da177e4SLinus Torvalds **
5721da177e4SLinus Torvalds */
5731da177e4SLinus Torvalds typedef union _SMC37c66_CR1E {
5741da177e4SLinus Torvalds     unsigned char as_uchar;
5751da177e4SLinus Torvalds     struct {
5761da177e4SLinus Torvalds     	unsigned gamecs_config: 2;   /* See note above		    */
5771da177e4SLinus Torvalds 	unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4>	    */
5781da177e4SLinus Torvalds     }	by_field;
5791da177e4SLinus Torvalds } SMC37c669_CR1E;
5801da177e4SLinus Torvalds 
5811da177e4SLinus Torvalds /*
5821da177e4SLinus Torvalds ** CR1F - default value 0x00
5831da177e4SLinus Torvalds **
5841da177e4SLinus Torvalds **  DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
5851da177e4SLinus Torvalds **  --- --- ------- ------- ----------
5861da177e4SLinus Torvalds **   0   0  DENSEL  DRATE0  4/2/1 MB 3.5"
5871da177e4SLinus Torvalds **                          2/1 MB 5.25"
5881da177e4SLinus Torvalds **                          2/1.6/1 MB 3.5" (3-mode)
5891da177e4SLinus Torvalds **   0   1  DRATE1  DRATE0
5901da177e4SLinus Torvalds **   1   0  nDENSEL DRATE0  PS/2
5911da177e4SLinus Torvalds **   1   1  DRATE0  DRATE1
5921da177e4SLinus Torvalds **
5931da177e4SLinus Torvalds **  Note: DENSEL, DRATE1, and DRATE0 map onto two output
5941da177e4SLinus Torvalds **	  pins - DRVDEN0 and DRVDEN1.
5951da177e4SLinus Torvalds **
5961da177e4SLinus Torvalds */
5971da177e4SLinus Torvalds typedef union _SMC37c669_CR1F {
5981da177e4SLinus Torvalds     unsigned char as_uchar;
5991da177e4SLinus Torvalds     struct {
6001da177e4SLinus Torvalds     	unsigned fdd0_drive_type : 2;	/* FDD0 drive type	    */
6011da177e4SLinus Torvalds 	unsigned fdd1_drive_type : 2;	/* FDD1 drive type	    */
6021da177e4SLinus Torvalds 	unsigned fdd2_drive_type : 2;	/* FDD2 drive type	    */
6031da177e4SLinus Torvalds 	unsigned fdd3_drive_type : 2;	/* FDD3 drive type	    */
6041da177e4SLinus Torvalds     }	by_field;
6051da177e4SLinus Torvalds } SMC37c669_CR1F;
6061da177e4SLinus Torvalds 
6071da177e4SLinus Torvalds /*
6081da177e4SLinus Torvalds ** CR20 - default value 0x3C
6091da177e4SLinus Torvalds **
6101da177e4SLinus Torvalds **  FDC Base Address Register
6111da177e4SLinus Torvalds **	- To disable this decode set Addr<9:8> = 0
6121da177e4SLinus Torvalds **	- A<10> = 0, A<3:0> = 0XXXb to access.
6131da177e4SLinus Torvalds **
6141da177e4SLinus Torvalds */
6151da177e4SLinus Torvalds typedef union _SMC37c669_CR20 {
6161da177e4SLinus Torvalds     unsigned char as_uchar;
6171da177e4SLinus Torvalds     struct {
6181da177e4SLinus Torvalds     	unsigned zero : 2;	    /* 0			    */
6191da177e4SLinus Torvalds 	unsigned addr9_4 : 6;	    /* FDC Addr<9:4>		    */
6201da177e4SLinus Torvalds     }	by_field;
6211da177e4SLinus Torvalds } SMC37c669_CR20;
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds /*
6241da177e4SLinus Torvalds ** CR21 - default value 0x3C
6251da177e4SLinus Torvalds **
6261da177e4SLinus Torvalds **  IDE Base Address Register
6271da177e4SLinus Torvalds **	- To disable this decode set Addr<9:8> = 0
6281da177e4SLinus Torvalds **	- A<10> = 0, A<3:0> = 0XXXb to access.
6291da177e4SLinus Torvalds **
6301da177e4SLinus Torvalds */
6311da177e4SLinus Torvalds typedef union _SMC37c669_CR21 {
6321da177e4SLinus Torvalds     unsigned char as_uchar;
6331da177e4SLinus Torvalds     struct {
6341da177e4SLinus Torvalds     	unsigned zero : 2;	    /* 0			    */
6351da177e4SLinus Torvalds 	unsigned addr9_4 : 6;	    /* IDE Addr<9:4>		    */
6361da177e4SLinus Torvalds     }	by_field;
6371da177e4SLinus Torvalds } SMC37c669_CR21;
6381da177e4SLinus Torvalds 
6391da177e4SLinus Torvalds /*
6401da177e4SLinus Torvalds ** CR22 - default value 0x3D
6411da177e4SLinus Torvalds **
6421da177e4SLinus Torvalds **  IDE Alternate Status Base Address Register
6431da177e4SLinus Torvalds **	- To disable this decode set Addr<9:8> = 0
6441da177e4SLinus Torvalds **	- A<10> = 0, A<3:0> = 0110b to access.
6451da177e4SLinus Torvalds **
6461da177e4SLinus Torvalds */
6471da177e4SLinus Torvalds typedef union _SMC37c669_CR22 {
6481da177e4SLinus Torvalds     unsigned char as_uchar;
6491da177e4SLinus Torvalds     struct {
6501da177e4SLinus Torvalds     	unsigned zero : 2;	    /* 0			    */
6511da177e4SLinus Torvalds 	unsigned addr9_4 : 6;	    /* IDE Alt Status Addr<9:4>	    */
6521da177e4SLinus Torvalds     }	by_field;
6531da177e4SLinus Torvalds } SMC37c669_CR22;
6541da177e4SLinus Torvalds 
6551da177e4SLinus Torvalds /*
6561da177e4SLinus Torvalds ** CR23 - default value 0x00
6571da177e4SLinus Torvalds **
6581da177e4SLinus Torvalds **  Parallel Port Base Address Register
6591da177e4SLinus Torvalds **	- To disable this decode set Addr<9:8> = 0
6601da177e4SLinus Torvalds **	- A<10> = 0 to access.
6611da177e4SLinus Torvalds **	- If EPP is enabled, A<2:0> = XXXb to access.
6621da177e4SLinus Torvalds **	  If EPP is NOT enabled, A<1:0> = XXb to access
6631da177e4SLinus Torvalds **
6641da177e4SLinus Torvalds */
6651da177e4SLinus Torvalds typedef union _SMC37c669_CR23 {
6661da177e4SLinus Torvalds     unsigned char as_uchar;
6671da177e4SLinus Torvalds     struct {
6681da177e4SLinus Torvalds 	unsigned addr9_2 : 8;	    /* Parallel Port Addr<9:2>	    */
6691da177e4SLinus Torvalds     }	by_field;
6701da177e4SLinus Torvalds } SMC37c669_CR23;
6711da177e4SLinus Torvalds 
6721da177e4SLinus Torvalds /*
6731da177e4SLinus Torvalds ** CR24 - default value 0x00
6741da177e4SLinus Torvalds **
6751da177e4SLinus Torvalds **  UART1 Base Address Register
6761da177e4SLinus Torvalds **	- To disable this decode set Addr<9:8> = 0
6771da177e4SLinus Torvalds **	- A<10> = 0, A<2:0> = XXXb to access.
6781da177e4SLinus Torvalds **
6791da177e4SLinus Torvalds */
6801da177e4SLinus Torvalds typedef union _SMC37c669_CR24 {
6811da177e4SLinus Torvalds     unsigned char as_uchar;
6821da177e4SLinus Torvalds     struct {
6831da177e4SLinus Torvalds     	unsigned zero : 1;	    /* 0			    */
6841da177e4SLinus Torvalds 	unsigned addr9_3 : 7;	    /* UART1 Addr<9:3>		    */
6851da177e4SLinus Torvalds     }	by_field;
6861da177e4SLinus Torvalds } SMC37c669_CR24;
6871da177e4SLinus Torvalds 
6881da177e4SLinus Torvalds /*
6891da177e4SLinus Torvalds ** CR25 - default value 0x00
6901da177e4SLinus Torvalds **
6911da177e4SLinus Torvalds **  UART2 Base Address Register
6921da177e4SLinus Torvalds **	- To disable this decode set Addr<9:8> = 0
6931da177e4SLinus Torvalds **	- A<10> = 0, A<2:0> = XXXb to access.
6941da177e4SLinus Torvalds **
6951da177e4SLinus Torvalds */
6961da177e4SLinus Torvalds typedef union _SMC37c669_CR25 {
6971da177e4SLinus Torvalds     unsigned char as_uchar;
6981da177e4SLinus Torvalds     struct {
6991da177e4SLinus Torvalds     	unsigned zero : 1;	    /* 0			    */
7001da177e4SLinus Torvalds 	unsigned addr9_3 : 7;	    /* UART2 Addr<9:3>		    */
7011da177e4SLinus Torvalds     }	by_field;
7021da177e4SLinus Torvalds } SMC37c669_CR25;
7031da177e4SLinus Torvalds 
7041da177e4SLinus Torvalds /*
7051da177e4SLinus Torvalds ** CR26 - default value 0x00
7061da177e4SLinus Torvalds **
7071da177e4SLinus Torvalds **  Parallel Port / FDC DMA Select Register
7081da177e4SLinus Torvalds **
7091da177e4SLinus Torvalds **  D3 - D0	  DMA
7101da177e4SLinus Torvalds **  D7 - D4	Selected
7111da177e4SLinus Torvalds **  -------	--------
7121da177e4SLinus Torvalds **   0000	 None
7131da177e4SLinus Torvalds **   0001	 DMA_A
7141da177e4SLinus Torvalds **   0010	 DMA_B
7151da177e4SLinus Torvalds **   0011	 DMA_C
7161da177e4SLinus Torvalds **
7171da177e4SLinus Torvalds */
7181da177e4SLinus Torvalds typedef union _SMC37c669_CR26 {
7191da177e4SLinus Torvalds     unsigned char as_uchar;
7201da177e4SLinus Torvalds     struct {
7211da177e4SLinus Torvalds     	unsigned ppt_drq : 4;	    /* See note above		    */
7221da177e4SLinus Torvalds 	unsigned fdc_drq : 4;	    /* See note above		    */
7231da177e4SLinus Torvalds     }	by_field;
7241da177e4SLinus Torvalds } SMC37c669_CR26;
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds /*
7271da177e4SLinus Torvalds ** CR27 - default value 0x00
7281da177e4SLinus Torvalds **
7291da177e4SLinus Torvalds **  Parallel Port / FDC IRQ Select Register
7301da177e4SLinus Torvalds **
7311da177e4SLinus Torvalds **  D3 - D0	  IRQ
7321da177e4SLinus Torvalds **  D7 - D4	Selected
7331da177e4SLinus Torvalds **  -------	--------
7341da177e4SLinus Torvalds **   0000	 None
7351da177e4SLinus Torvalds **   0001	 IRQ_A
7361da177e4SLinus Torvalds **   0010	 IRQ_B
7371da177e4SLinus Torvalds **   0011	 IRQ_C
7381da177e4SLinus Torvalds **   0100	 IRQ_D
7391da177e4SLinus Torvalds **   0101	 IRQ_E
7401da177e4SLinus Torvalds **   0110	 IRQ_F
7411da177e4SLinus Torvalds **   0111	 Reserved
7421da177e4SLinus Torvalds **   1000	 IRQ_H
7431da177e4SLinus Torvalds **
7441da177e4SLinus Torvalds **  Any unselected IRQ REQ is in tristate
7451da177e4SLinus Torvalds **
7461da177e4SLinus Torvalds */
7471da177e4SLinus Torvalds typedef union _SMC37c669_CR27 {
7481da177e4SLinus Torvalds     unsigned char as_uchar;
7491da177e4SLinus Torvalds     struct {
7501da177e4SLinus Torvalds     	unsigned ppt_irq : 4;	    /* See note above		    */
7511da177e4SLinus Torvalds 	unsigned fdc_irq : 4;	    /* See note above		    */
7521da177e4SLinus Torvalds     }	by_field;
7531da177e4SLinus Torvalds } SMC37c669_CR27;
7541da177e4SLinus Torvalds 
7551da177e4SLinus Torvalds /*
7561da177e4SLinus Torvalds ** CR28 - default value 0x00
7571da177e4SLinus Torvalds **
7581da177e4SLinus Torvalds **  UART IRQ Select Register
7591da177e4SLinus Torvalds **
7601da177e4SLinus Torvalds **  D3 - D0	  IRQ
7611da177e4SLinus Torvalds **  D7 - D4	Selected
7621da177e4SLinus Torvalds **  -------	--------
7631da177e4SLinus Torvalds **   0000	 None
7641da177e4SLinus Torvalds **   0001	 IRQ_A
7651da177e4SLinus Torvalds **   0010	 IRQ_B
7661da177e4SLinus Torvalds **   0011	 IRQ_C
7671da177e4SLinus Torvalds **   0100	 IRQ_D
7681da177e4SLinus Torvalds **   0101	 IRQ_E
7691da177e4SLinus Torvalds **   0110	 IRQ_F
7701da177e4SLinus Torvalds **   0111	 Reserved
7711da177e4SLinus Torvalds **   1000	 IRQ_H
7721da177e4SLinus Torvalds **   1111	 share with UART1 (only for UART2)
7731da177e4SLinus Torvalds **
7741da177e4SLinus Torvalds **  Any unselected IRQ REQ is in tristate
7751da177e4SLinus Torvalds **
7761da177e4SLinus Torvalds **  To share an IRQ between UART1 and UART2, set
7771da177e4SLinus Torvalds **  UART1 to use the desired IRQ and set UART2 to
7781da177e4SLinus Torvalds **  0xF to enable sharing mechanism.
7791da177e4SLinus Torvalds **
7801da177e4SLinus Torvalds */
7811da177e4SLinus Torvalds typedef union _SMC37c669_CR28 {
7821da177e4SLinus Torvalds     unsigned char as_uchar;
7831da177e4SLinus Torvalds     struct {
7841da177e4SLinus Torvalds     	unsigned uart2_irq : 4;	    /* See note above		    */
7851da177e4SLinus Torvalds 	unsigned uart1_irq : 4;	    /* See note above		    */
7861da177e4SLinus Torvalds     }	by_field;
7871da177e4SLinus Torvalds } SMC37c669_CR28;
7881da177e4SLinus Torvalds 
7891da177e4SLinus Torvalds /*
7901da177e4SLinus Torvalds ** CR29 - default value 0x00
7911da177e4SLinus Torvalds **
7921da177e4SLinus Torvalds **  IRQIN IRQ Select Register
7931da177e4SLinus Torvalds **
7941da177e4SLinus Torvalds **  D3 - D0	  IRQ
7951da177e4SLinus Torvalds **  D7 - D4	Selected
7961da177e4SLinus Torvalds **  -------	--------
7971da177e4SLinus Torvalds **   0000	 None
7981da177e4SLinus Torvalds **   0001	 IRQ_A
7991da177e4SLinus Torvalds **   0010	 IRQ_B
8001da177e4SLinus Torvalds **   0011	 IRQ_C
8011da177e4SLinus Torvalds **   0100	 IRQ_D
8021da177e4SLinus Torvalds **   0101	 IRQ_E
8031da177e4SLinus Torvalds **   0110	 IRQ_F
8041da177e4SLinus Torvalds **   0111	 Reserved
8051da177e4SLinus Torvalds **   1000	 IRQ_H
8061da177e4SLinus Torvalds **
8071da177e4SLinus Torvalds **  Any unselected IRQ REQ is in tristate
8081da177e4SLinus Torvalds **
8091da177e4SLinus Torvalds */
8101da177e4SLinus Torvalds typedef union _SMC37c669_CR29 {
8111da177e4SLinus Torvalds     unsigned char as_uchar;
8121da177e4SLinus Torvalds     struct {
8131da177e4SLinus Torvalds     	unsigned irqin_irq : 4;	    /* See note above		    */
8141da177e4SLinus Torvalds 	unsigned reserved1 : 4;	    /* RAZ			    */
8151da177e4SLinus Torvalds     }	by_field;
8161da177e4SLinus Torvalds } SMC37c669_CR29;
8171da177e4SLinus Torvalds 
8181da177e4SLinus Torvalds /*
8191da177e4SLinus Torvalds ** Aliases of Configuration Register formats (should match
8201da177e4SLinus Torvalds ** the set of index aliases).
8211da177e4SLinus Torvalds **
8221da177e4SLinus Torvalds ** Note that CR24 and CR25 have the same format and are the
8231da177e4SLinus Torvalds ** base address registers for UART1 and UART2.  Because of
8241da177e4SLinus Torvalds ** this we only define 1 alias here - for CR24 - as the serial
8251da177e4SLinus Torvalds ** base address register.
8261da177e4SLinus Torvalds **
8271da177e4SLinus Torvalds ** Note that CR21 and CR22 have the same format and are the
8281da177e4SLinus Torvalds ** base address and alternate status address registers for
8291da177e4SLinus Torvalds ** the IDE controller.  Because of this we only define 1 alias
8301da177e4SLinus Torvalds ** here - for CR21 - as the IDE address register.
8311da177e4SLinus Torvalds **
8321da177e4SLinus Torvalds */
8331da177e4SLinus Torvalds typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
8341da177e4SLinus Torvalds typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
8351da177e4SLinus Torvalds typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
8361da177e4SLinus Torvalds typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
8371da177e4SLinus Torvalds typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
8381da177e4SLinus Torvalds typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
8391da177e4SLinus Torvalds typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
8401da177e4SLinus Torvalds typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
8411da177e4SLinus Torvalds typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;
8421da177e4SLinus Torvalds 
8431da177e4SLinus Torvalds /*
8441da177e4SLinus Torvalds ** ISA/Device IRQ Translation Table Entry Definition
8451da177e4SLinus Torvalds */
8461da177e4SLinus Torvalds typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {
8471da177e4SLinus Torvalds     int device_irq;
8481da177e4SLinus Torvalds     int isa_irq;
8491da177e4SLinus Torvalds } SMC37c669_IRQ_TRANSLATION_ENTRY;
8501da177e4SLinus Torvalds 
8511da177e4SLinus Torvalds /*
8521da177e4SLinus Torvalds ** ISA/Device DMA Translation Table Entry Definition
8531da177e4SLinus Torvalds */
8541da177e4SLinus Torvalds typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {
8551da177e4SLinus Torvalds     int device_drq;
8561da177e4SLinus Torvalds     int isa_drq;
8571da177e4SLinus Torvalds } SMC37c669_DRQ_TRANSLATION_ENTRY;
8581da177e4SLinus Torvalds 
8591da177e4SLinus Torvalds /*
8601da177e4SLinus Torvalds ** External Interface Function Prototype Declarations
8611da177e4SLinus Torvalds */
8621da177e4SLinus Torvalds 
8631da177e4SLinus Torvalds SMC37c669_CONFIG_REGS *SMC37c669_detect(
8641da177e4SLinus Torvalds     int
8651da177e4SLinus Torvalds );
8661da177e4SLinus Torvalds 
8671da177e4SLinus Torvalds unsigned int SMC37c669_enable_device(
8681da177e4SLinus Torvalds     unsigned int func
8691da177e4SLinus Torvalds );
8701da177e4SLinus Torvalds 
8711da177e4SLinus Torvalds unsigned int SMC37c669_disable_device(
8721da177e4SLinus Torvalds     unsigned int func
8731da177e4SLinus Torvalds );
8741da177e4SLinus Torvalds 
8751da177e4SLinus Torvalds unsigned int SMC37c669_configure_device(
8761da177e4SLinus Torvalds     unsigned int func,
8771da177e4SLinus Torvalds     int port,
8781da177e4SLinus Torvalds     int irq,
8791da177e4SLinus Torvalds     int drq
8801da177e4SLinus Torvalds );
8811da177e4SLinus Torvalds 
8821da177e4SLinus Torvalds void SMC37c669_display_device_info(
8831da177e4SLinus Torvalds     void
8841da177e4SLinus Torvalds );
8851da177e4SLinus Torvalds 
8861da177e4SLinus Torvalds #endif	/* __SMC37c669_H */
8871da177e4SLinus Torvalds 
8881da177e4SLinus Torvalds /* file:	smcc669.c
8891da177e4SLinus Torvalds  *
8901da177e4SLinus Torvalds  * Copyright (C) 1997 by
8911da177e4SLinus Torvalds  * Digital Equipment Corporation, Maynard, Massachusetts.
8921da177e4SLinus Torvalds  * All rights reserved.
8931da177e4SLinus Torvalds  *
8941da177e4SLinus Torvalds  * This software is furnished under a license and may be used and copied
8951da177e4SLinus Torvalds  * only  in  accordance  of  the  terms  of  such  license  and with the
8961da177e4SLinus Torvalds  * inclusion of the above copyright notice. This software or  any  other
8971da177e4SLinus Torvalds  * copies thereof may not be provided or otherwise made available to any
8981da177e4SLinus Torvalds  * other person.  No title to and  ownership of the  software is  hereby
8991da177e4SLinus Torvalds  * transferred.
9001da177e4SLinus Torvalds  *
9011da177e4SLinus Torvalds  * The information in this software is  subject to change without notice
9021da177e4SLinus Torvalds  * and  should  not  be  construed  as a commitment by digital equipment
9031da177e4SLinus Torvalds  * corporation.
9041da177e4SLinus Torvalds  *
9051da177e4SLinus Torvalds  * Digital assumes no responsibility for the use  or  reliability of its
9061da177e4SLinus Torvalds  * software on equipment which is not supplied by digital.
9071da177e4SLinus Torvalds  */
9081da177e4SLinus Torvalds 
9091da177e4SLinus Torvalds /*
9101da177e4SLinus Torvalds  *++
9111da177e4SLinus Torvalds  *  FACILITY:
9121da177e4SLinus Torvalds  *
9131da177e4SLinus Torvalds  *      Alpha SRM Console Firmware
9141da177e4SLinus Torvalds  *
9151da177e4SLinus Torvalds  *  MODULE DESCRIPTION:
9161da177e4SLinus Torvalds  *
9171da177e4SLinus Torvalds  *	SMC37c669 Super I/O controller configuration routines.
9181da177e4SLinus Torvalds  *
9191da177e4SLinus Torvalds  *  AUTHORS:
9201da177e4SLinus Torvalds  *
9211da177e4SLinus Torvalds  *	Eric Rasmussen
9221da177e4SLinus Torvalds  *
9231da177e4SLinus Torvalds  *  CREATION DATE:
9241da177e4SLinus Torvalds  *
9251da177e4SLinus Torvalds  *	28-Jan-1997
9261da177e4SLinus Torvalds  *
9271da177e4SLinus Torvalds  *  MODIFICATION HISTORY:
9281da177e4SLinus Torvalds  *
9291da177e4SLinus Torvalds  *	er	01-May-1997	Fixed pointer conversion errors in
9301da177e4SLinus Torvalds  *				SMC37c669_get_device_config().
9311da177e4SLinus Torvalds  *      er	28-Jan-1997	Initial version.
9321da177e4SLinus Torvalds  *
9331da177e4SLinus Torvalds  *--
9341da177e4SLinus Torvalds  */
9351da177e4SLinus Torvalds 
9361da177e4SLinus Torvalds #ifndef TRUE
9371da177e4SLinus Torvalds #define TRUE 1
9381da177e4SLinus Torvalds #endif
9391da177e4SLinus Torvalds #ifndef FALSE
9401da177e4SLinus Torvalds #define FALSE 0
9411da177e4SLinus Torvalds #endif
9421da177e4SLinus Torvalds 
9431da177e4SLinus Torvalds #define wb( _x_, _y_ )	outb( _y_, (unsigned int)((unsigned long)_x_) )
9441da177e4SLinus Torvalds #define rb( _x_ )	inb( (unsigned int)((unsigned long)_x_) )
9451da177e4SLinus Torvalds 
9461da177e4SLinus Torvalds /*
9471da177e4SLinus Torvalds ** Local storage for device configuration information.
9481da177e4SLinus Torvalds **
9491da177e4SLinus Torvalds ** Since the SMC37c669 does not provide an explicit
9501da177e4SLinus Torvalds ** mechanism for enabling/disabling individual device
9511da177e4SLinus Torvalds ** functions, other than unmapping the device, local
9521da177e4SLinus Torvalds ** storage for device configuration information is
9531da177e4SLinus Torvalds ** allocated here for use in implementing our own
9541da177e4SLinus Torvalds ** function enable/disable scheme.
9551da177e4SLinus Torvalds */
9561da177e4SLinus Torvalds static struct DEVICE_CONFIG {
9571da177e4SLinus Torvalds     unsigned int port1;
9581da177e4SLinus Torvalds     unsigned int port2;
9591da177e4SLinus Torvalds     int irq;
9601da177e4SLinus Torvalds     int drq;
9611da177e4SLinus Torvalds } local_config [NUM_FUNCS];
9621da177e4SLinus Torvalds 
9631da177e4SLinus Torvalds /*
9641da177e4SLinus Torvalds ** List of all possible addresses for the Super I/O chip
9651da177e4SLinus Torvalds */
9661da177e4SLinus Torvalds static unsigned long SMC37c669_Addresses[] __initdata =
9671da177e4SLinus Torvalds     {
9681da177e4SLinus Torvalds 	0x3F0UL,	    /* Primary address	    */
9691da177e4SLinus Torvalds 	0x370UL,	    /* Secondary address    */
9701da177e4SLinus Torvalds 	0UL		    /* End of list	    */
9711da177e4SLinus Torvalds     };
9721da177e4SLinus Torvalds 
9731da177e4SLinus Torvalds /*
9741da177e4SLinus Torvalds ** Global Pointer to the Super I/O device
9751da177e4SLinus Torvalds */
9761da177e4SLinus Torvalds static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;
9771da177e4SLinus Torvalds 
9781da177e4SLinus Torvalds /*
9791da177e4SLinus Torvalds ** IRQ Translation Table
9801da177e4SLinus Torvalds **
9811da177e4SLinus Torvalds ** The IRQ translation table is a list of SMC37c669 device
9821da177e4SLinus Torvalds ** and standard ISA IRQs.
9831da177e4SLinus Torvalds **
9841da177e4SLinus Torvalds */
9851da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata;
9861da177e4SLinus Torvalds 
9871da177e4SLinus Torvalds /*
9881da177e4SLinus Torvalds ** The following definition is for the default IRQ
9891da177e4SLinus Torvalds ** translation table.
9901da177e4SLinus Torvalds */
9911da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]
9921da177e4SLinus Torvalds __initdata =
9931da177e4SLinus Torvalds     {
9941da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_A, -1 },
9951da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_B, -1 },
9961da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_C, 7 },
9971da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_D, 6 },
9981da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_E, 4 },
9991da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_F, 3 },
10001da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_H, -1 },
10011da177e4SLinus Torvalds 	{ -1, -1 } /* End of table */
10021da177e4SLinus Torvalds     };
10031da177e4SLinus Torvalds 
10041da177e4SLinus Torvalds /*
10051da177e4SLinus Torvalds ** The following definition is for the MONET (XP1000) IRQ
10061da177e4SLinus Torvalds ** translation table.
10071da177e4SLinus Torvalds */
10081da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]
10091da177e4SLinus Torvalds __initdata =
10101da177e4SLinus Torvalds     {
10111da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_A, -1 },
10121da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_B, -1 },
10131da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_C, 6 },
10141da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_D, 7 },
10151da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_E, 4 },
10161da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_F, 3 },
10171da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_IRQ_H, -1 },
10181da177e4SLinus Torvalds 	{ -1, -1 } /* End of table */
10191da177e4SLinus Torvalds     };
10201da177e4SLinus Torvalds 
10211da177e4SLinus Torvalds static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =
10221da177e4SLinus Torvalds     {
10231da177e4SLinus Torvalds 	SMC37c669_default_irq_table,
10241da177e4SLinus Torvalds 	SMC37c669_monet_irq_table
10251da177e4SLinus Torvalds     };
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds /*
10281da177e4SLinus Torvalds ** DRQ Translation Table
10291da177e4SLinus Torvalds **
10301da177e4SLinus Torvalds ** The DRQ translation table is a list of SMC37c669 device and
10311da177e4SLinus Torvalds ** ISA DMA channels.
10321da177e4SLinus Torvalds **
10331da177e4SLinus Torvalds */
10341da177e4SLinus Torvalds static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata;
10351da177e4SLinus Torvalds 
10361da177e4SLinus Torvalds /*
10371da177e4SLinus Torvalds ** The following definition is the default DRQ
10381da177e4SLinus Torvalds ** translation table.
10391da177e4SLinus Torvalds */
10401da177e4SLinus Torvalds static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]
10411da177e4SLinus Torvalds __initdata =
10421da177e4SLinus Torvalds     {
10431da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_DRQ_A, 2 },
10441da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_DRQ_B, 3 },
10451da177e4SLinus Torvalds 	{ SMC37c669_DEVICE_DRQ_C, -1 },
10461da177e4SLinus Torvalds 	{ -1, -1 } /* End of table */
10471da177e4SLinus Torvalds     };
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds /*
10501da177e4SLinus Torvalds ** Local Function Prototype Declarations
10511da177e4SLinus Torvalds */
10521da177e4SLinus Torvalds 
10531da177e4SLinus Torvalds static unsigned int SMC37c669_is_device_enabled(
10541da177e4SLinus Torvalds     unsigned int func
10551da177e4SLinus Torvalds );
10561da177e4SLinus Torvalds 
10571da177e4SLinus Torvalds #if 0
10581da177e4SLinus Torvalds static unsigned int SMC37c669_get_device_config(
10591da177e4SLinus Torvalds     unsigned int func,
10601da177e4SLinus Torvalds     int *port,
10611da177e4SLinus Torvalds     int *irq,
10621da177e4SLinus Torvalds     int *drq
10631da177e4SLinus Torvalds );
10641da177e4SLinus Torvalds #endif
10651da177e4SLinus Torvalds 
10661da177e4SLinus Torvalds static void SMC37c669_config_mode(
10671da177e4SLinus Torvalds     unsigned int enable
10681da177e4SLinus Torvalds );
10691da177e4SLinus Torvalds 
10701da177e4SLinus Torvalds static unsigned char SMC37c669_read_config(
10711da177e4SLinus Torvalds     unsigned char index
10721da177e4SLinus Torvalds );
10731da177e4SLinus Torvalds 
10741da177e4SLinus Torvalds static void SMC37c669_write_config(
10751da177e4SLinus Torvalds     unsigned char index,
10761da177e4SLinus Torvalds     unsigned char data
10771da177e4SLinus Torvalds );
10781da177e4SLinus Torvalds 
10791da177e4SLinus Torvalds static void SMC37c669_init_local_config( void );
10801da177e4SLinus Torvalds 
10811da177e4SLinus Torvalds static struct DEVICE_CONFIG *SMC37c669_get_config(
10821da177e4SLinus Torvalds     unsigned int func
10831da177e4SLinus Torvalds );
10841da177e4SLinus Torvalds 
10851da177e4SLinus Torvalds static int SMC37c669_xlate_irq(
10861da177e4SLinus Torvalds     int irq
10871da177e4SLinus Torvalds );
10881da177e4SLinus Torvalds 
10891da177e4SLinus Torvalds static int SMC37c669_xlate_drq(
10901da177e4SLinus Torvalds     int drq
10911da177e4SLinus Torvalds );
10921da177e4SLinus Torvalds 
10931da177e4SLinus Torvalds static  __cacheline_aligned DEFINE_SPINLOCK(smc_lock);
10941da177e4SLinus Torvalds 
10951da177e4SLinus Torvalds /*
10961da177e4SLinus Torvalds **++
10971da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
10981da177e4SLinus Torvalds **
10991da177e4SLinus Torvalds **      This function detects the presence of an SMC37c669 Super I/O
11001da177e4SLinus Torvalds **	controller.
11011da177e4SLinus Torvalds **
11021da177e4SLinus Torvalds **  FORMAL PARAMETERS:
11031da177e4SLinus Torvalds **
11041da177e4SLinus Torvalds **	None
11051da177e4SLinus Torvalds **
11061da177e4SLinus Torvalds **  RETURN VALUE:
11071da177e4SLinus Torvalds **
11081da177e4SLinus Torvalds **      Returns a pointer to the device if found, otherwise,
11091da177e4SLinus Torvalds **	the NULL pointer is returned.
11101da177e4SLinus Torvalds **
11111da177e4SLinus Torvalds **  SIDE EFFECTS:
11121da177e4SLinus Torvalds **
11131da177e4SLinus Torvalds **      None
11141da177e4SLinus Torvalds **
11151da177e4SLinus Torvalds **--
11161da177e4SLinus Torvalds */
SMC37c669_detect(int index)11171da177e4SLinus Torvalds SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
11181da177e4SLinus Torvalds {
11191da177e4SLinus Torvalds     int i;
11201da177e4SLinus Torvalds     SMC37c669_DEVICE_ID_REGISTER id;
11211da177e4SLinus Torvalds 
11221da177e4SLinus Torvalds     for ( i = 0;  SMC37c669_Addresses[i] != 0;  i++ ) {
11231da177e4SLinus Torvalds /*
11241da177e4SLinus Torvalds ** Initialize the device pointer even though we don't yet know if
11251da177e4SLinus Torvalds ** the controller is at this address.  The support functions access
11261da177e4SLinus Torvalds ** the controller through this device pointer so we need to set it
11271da177e4SLinus Torvalds ** even when we are looking ...
11281da177e4SLinus Torvalds */
11291da177e4SLinus Torvalds     	SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
11301da177e4SLinus Torvalds /*
11311da177e4SLinus Torvalds ** Enter configuration mode
11321da177e4SLinus Torvalds */
11331da177e4SLinus Torvalds 	SMC37c669_config_mode( TRUE );
11341da177e4SLinus Torvalds /*
11351da177e4SLinus Torvalds ** Read the device id
11361da177e4SLinus Torvalds */
11371da177e4SLinus Torvalds 	id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
11381da177e4SLinus Torvalds /*
11391da177e4SLinus Torvalds ** Exit configuration mode
11401da177e4SLinus Torvalds */
11411da177e4SLinus Torvalds 	SMC37c669_config_mode( FALSE );
11421da177e4SLinus Torvalds /*
11431da177e4SLinus Torvalds ** Does the device id match?  If so, assume we have found an
11441da177e4SLinus Torvalds ** SMC37c669 controller at this address.
11451da177e4SLinus Torvalds */
11461da177e4SLinus Torvalds 	if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
11471da177e4SLinus Torvalds /*
11481da177e4SLinus Torvalds ** Initialize the IRQ and DRQ translation tables.
11491da177e4SLinus Torvalds */
11501da177e4SLinus Torvalds     	    SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
11511da177e4SLinus Torvalds 	    SMC37c669_drq_table = SMC37c669_default_drq_table;
11521da177e4SLinus Torvalds /*
11531da177e4SLinus Torvalds ** erfix
11541da177e4SLinus Torvalds **
11551da177e4SLinus Torvalds ** If the platform can't use the IRQ and DRQ defaults set up in this
11561da177e4SLinus Torvalds ** file, it should call a platform-specific external routine at this
11571da177e4SLinus Torvalds ** point to reset the IRQ and DRQ translation table pointers to point
11581da177e4SLinus Torvalds ** at the appropriate tables for the platform.  If the defaults are
11591da177e4SLinus Torvalds ** acceptable, then the external routine should do nothing.
11601da177e4SLinus Torvalds */
11611da177e4SLinus Torvalds 
11621da177e4SLinus Torvalds /*
11631da177e4SLinus Torvalds ** Put the chip back into configuration mode
11641da177e4SLinus Torvalds */
11651da177e4SLinus Torvalds 	    SMC37c669_config_mode( TRUE );
11661da177e4SLinus Torvalds /*
11671da177e4SLinus Torvalds ** Initialize local storage for configuration information
11681da177e4SLinus Torvalds */
11691da177e4SLinus Torvalds 	    SMC37c669_init_local_config( );
11701da177e4SLinus Torvalds /*
11711da177e4SLinus Torvalds ** Exit configuration mode
11721da177e4SLinus Torvalds */
11731da177e4SLinus Torvalds 	    SMC37c669_config_mode( FALSE );
11741da177e4SLinus Torvalds /*
11751da177e4SLinus Torvalds ** SMC37c669 controller found, break out of search loop
11761da177e4SLinus Torvalds */
11771da177e4SLinus Torvalds 	    break;
11781da177e4SLinus Torvalds 	}
11791da177e4SLinus Torvalds 	else {
11801da177e4SLinus Torvalds /*
11811da177e4SLinus Torvalds ** Otherwise, we did not find an SMC37c669 controller at this
11821da177e4SLinus Torvalds ** address so set the device pointer to NULL.
11831da177e4SLinus Torvalds */
11841da177e4SLinus Torvalds 	    SMC37c669 = NULL;
11851da177e4SLinus Torvalds 	}
11861da177e4SLinus Torvalds     }
11871da177e4SLinus Torvalds     return SMC37c669;
11881da177e4SLinus Torvalds }
11891da177e4SLinus Torvalds 
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds /*
11921da177e4SLinus Torvalds **++
11931da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
11941da177e4SLinus Torvalds **
11951da177e4SLinus Torvalds **      This function enables an SMC37c669 device function.
11961da177e4SLinus Torvalds **
11971da177e4SLinus Torvalds **  FORMAL PARAMETERS:
11981da177e4SLinus Torvalds **
11991da177e4SLinus Torvalds **      func:
12001da177e4SLinus Torvalds **          Which device function to enable
12011da177e4SLinus Torvalds **
12021da177e4SLinus Torvalds **  RETURN VALUE:
12031da177e4SLinus Torvalds **
12041da177e4SLinus Torvalds **      Returns TRUE is the device function was enabled, otherwise, FALSE
12051da177e4SLinus Torvalds **
12061da177e4SLinus Torvalds **  SIDE EFFECTS:
12071da177e4SLinus Torvalds **
12081da177e4SLinus Torvalds **      {@description or none@}
12091da177e4SLinus Torvalds **
12101da177e4SLinus Torvalds **  DESIGN:
12111da177e4SLinus Torvalds **
12121da177e4SLinus Torvalds **      Enabling a device function in the SMC37c669 controller involves
12131da177e4SLinus Torvalds **	setting all of its mappings (port, irq, drq ...).  A local
12141da177e4SLinus Torvalds **	"shadow" copy of the device configuration is kept so we can
12151da177e4SLinus Torvalds **	just set each mapping to what the local copy says.
12161da177e4SLinus Torvalds **
12171da177e4SLinus Torvalds **	This function ALWAYS updates the local shadow configuration of
12181da177e4SLinus Torvalds **	the device function being enabled, even if the device is always
12191da177e4SLinus Torvalds **	enabled.  To avoid replication of code, functions such as
12201da177e4SLinus Torvalds **	configure_device set up the local copy and then call this
12211da177e4SLinus Torvalds **	function to the update the real device.
12221da177e4SLinus Torvalds **
12231da177e4SLinus Torvalds **--
12241da177e4SLinus Torvalds */
SMC37c669_enable_device(unsigned int func)12251da177e4SLinus Torvalds unsigned int __init SMC37c669_enable_device ( unsigned int func )
12261da177e4SLinus Torvalds {
12271da177e4SLinus Torvalds     unsigned int ret_val = FALSE;
12281da177e4SLinus Torvalds /*
12291da177e4SLinus Torvalds ** Put the device into configuration mode
12301da177e4SLinus Torvalds */
12311da177e4SLinus Torvalds     SMC37c669_config_mode( TRUE );
12321da177e4SLinus Torvalds     switch ( func ) {
12331da177e4SLinus Torvalds     	case SERIAL_0:
12341da177e4SLinus Torvalds 	    {
12351da177e4SLinus Torvalds 	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
12361da177e4SLinus Torvalds 		SMC37c669_SERIAL_IRQ_REGISTER irq;
12371da177e4SLinus Torvalds /*
12381da177e4SLinus Torvalds ** Enable the serial 1 IRQ mapping
12391da177e4SLinus Torvalds */
12401da177e4SLinus Torvalds 	    	irq.as_uchar =
12411da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
12421da177e4SLinus Torvalds 
12431da177e4SLinus Torvalds 		irq.by_field.uart1_irq =
12441da177e4SLinus Torvalds 		    SMC37c669_RAW_DEVICE_IRQ(
12451da177e4SLinus Torvalds 			SMC37c669_xlate_irq( local_config[ func ].irq )
12461da177e4SLinus Torvalds 		    );
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds 		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
12491da177e4SLinus Torvalds /*
12501da177e4SLinus Torvalds ** Enable the serial 1 port base address mapping
12511da177e4SLinus Torvalds */
12521da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
12531da177e4SLinus Torvalds 		base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 		SMC37c669_write_config(
12561da177e4SLinus Torvalds 		    SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
12571da177e4SLinus Torvalds 		    base_addr.as_uchar
12581da177e4SLinus Torvalds 		);
12591da177e4SLinus Torvalds 		ret_val = TRUE;
12601da177e4SLinus Torvalds 		break;
12611da177e4SLinus Torvalds 	    }
12621da177e4SLinus Torvalds 	case SERIAL_1:
12631da177e4SLinus Torvalds 	    {
12641da177e4SLinus Torvalds 	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
12651da177e4SLinus Torvalds 		SMC37c669_SERIAL_IRQ_REGISTER irq;
12661da177e4SLinus Torvalds /*
12671da177e4SLinus Torvalds ** Enable the serial 2 IRQ mapping
12681da177e4SLinus Torvalds */
12691da177e4SLinus Torvalds 	    	irq.as_uchar =
12701da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
12711da177e4SLinus Torvalds 
12721da177e4SLinus Torvalds 		irq.by_field.uart2_irq =
12731da177e4SLinus Torvalds 		    SMC37c669_RAW_DEVICE_IRQ(
12741da177e4SLinus Torvalds 			SMC37c669_xlate_irq( local_config[ func ].irq )
12751da177e4SLinus Torvalds 		    );
12761da177e4SLinus Torvalds 
12771da177e4SLinus Torvalds 		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
12781da177e4SLinus Torvalds /*
12791da177e4SLinus Torvalds ** Enable the serial 2 port base address mapping
12801da177e4SLinus Torvalds */
12811da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
12821da177e4SLinus Torvalds 		base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
12831da177e4SLinus Torvalds 
12841da177e4SLinus Torvalds 		SMC37c669_write_config(
12851da177e4SLinus Torvalds 		    SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
12861da177e4SLinus Torvalds 		    base_addr.as_uchar
12871da177e4SLinus Torvalds 		);
12881da177e4SLinus Torvalds 		ret_val = TRUE;
12891da177e4SLinus Torvalds 		break;
12901da177e4SLinus Torvalds 	    }
12911da177e4SLinus Torvalds 	case PARALLEL_0:
12921da177e4SLinus Torvalds 	    {
12931da177e4SLinus Torvalds 	    	SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
12941da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
12951da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
12961da177e4SLinus Torvalds /*
12971da177e4SLinus Torvalds ** Enable the parallel port DMA channel mapping
12981da177e4SLinus Torvalds */
12991da177e4SLinus Torvalds 	    	drq.as_uchar =
13001da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
13011da177e4SLinus Torvalds 
13021da177e4SLinus Torvalds 		drq.by_field.ppt_drq =
13031da177e4SLinus Torvalds 		    SMC37c669_RAW_DEVICE_DRQ(
13041da177e4SLinus Torvalds 			SMC37c669_xlate_drq( local_config[ func ].drq )
13051da177e4SLinus Torvalds 		    );
13061da177e4SLinus Torvalds 
13071da177e4SLinus Torvalds 		SMC37c669_write_config(
13081da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
13091da177e4SLinus Torvalds 		    drq.as_uchar
13101da177e4SLinus Torvalds 		);
13111da177e4SLinus Torvalds /*
13121da177e4SLinus Torvalds ** Enable the parallel port IRQ mapping
13131da177e4SLinus Torvalds */
13141da177e4SLinus Torvalds 		irq.as_uchar =
13151da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds 		irq.by_field.ppt_irq =
13181da177e4SLinus Torvalds 		    SMC37c669_RAW_DEVICE_IRQ(
13191da177e4SLinus Torvalds 			SMC37c669_xlate_irq( local_config[ func ].irq )
13201da177e4SLinus Torvalds 		    );
13211da177e4SLinus Torvalds 
13221da177e4SLinus Torvalds 		SMC37c669_write_config(
13231da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
13241da177e4SLinus Torvalds 		    irq.as_uchar
13251da177e4SLinus Torvalds 		);
13261da177e4SLinus Torvalds /*
13271da177e4SLinus Torvalds ** Enable the parallel port base address mapping
13281da177e4SLinus Torvalds */
13291da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
13301da177e4SLinus Torvalds 		base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;
13311da177e4SLinus Torvalds 
13321da177e4SLinus Torvalds 		SMC37c669_write_config(
13331da177e4SLinus Torvalds 		    SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
13341da177e4SLinus Torvalds 		    base_addr.as_uchar
13351da177e4SLinus Torvalds 		);
13361da177e4SLinus Torvalds 		ret_val = TRUE;
13371da177e4SLinus Torvalds 		break;
13381da177e4SLinus Torvalds 	    }
13391da177e4SLinus Torvalds 	case FLOPPY_0:
13401da177e4SLinus Torvalds 	    {
13411da177e4SLinus Torvalds 	    	SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
13421da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
13431da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
13441da177e4SLinus Torvalds /*
13451da177e4SLinus Torvalds ** Enable the floppy controller DMA channel mapping
13461da177e4SLinus Torvalds */
13471da177e4SLinus Torvalds 	    	drq.as_uchar =
13481da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
13491da177e4SLinus Torvalds 
13501da177e4SLinus Torvalds 		drq.by_field.fdc_drq =
13511da177e4SLinus Torvalds 		    SMC37c669_RAW_DEVICE_DRQ(
13521da177e4SLinus Torvalds 			SMC37c669_xlate_drq( local_config[ func ].drq )
13531da177e4SLinus Torvalds 		    );
13541da177e4SLinus Torvalds 
13551da177e4SLinus Torvalds 		SMC37c669_write_config(
13561da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
13571da177e4SLinus Torvalds 		    drq.as_uchar
13581da177e4SLinus Torvalds 		);
13591da177e4SLinus Torvalds /*
13601da177e4SLinus Torvalds ** Enable the floppy controller IRQ mapping
13611da177e4SLinus Torvalds */
13621da177e4SLinus Torvalds 		irq.as_uchar =
13631da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
13641da177e4SLinus Torvalds 
13651da177e4SLinus Torvalds 		irq.by_field.fdc_irq =
13661da177e4SLinus Torvalds 		    SMC37c669_RAW_DEVICE_IRQ(
13671da177e4SLinus Torvalds 			SMC37c669_xlate_irq( local_config[ func ].irq )
13681da177e4SLinus Torvalds 		    );
13691da177e4SLinus Torvalds 
13701da177e4SLinus Torvalds 		SMC37c669_write_config(
13711da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
13721da177e4SLinus Torvalds 		    irq.as_uchar
13731da177e4SLinus Torvalds 		);
13741da177e4SLinus Torvalds /*
13751da177e4SLinus Torvalds ** Enable the floppy controller base address mapping
13761da177e4SLinus Torvalds */
13771da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
13781da177e4SLinus Torvalds 		base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
13791da177e4SLinus Torvalds 
13801da177e4SLinus Torvalds 		SMC37c669_write_config(
13811da177e4SLinus Torvalds 		    SMC37c669_FDC_BASE_ADDRESS_INDEX,
13821da177e4SLinus Torvalds 		    base_addr.as_uchar
13831da177e4SLinus Torvalds 		);
13841da177e4SLinus Torvalds 		ret_val = TRUE;
13851da177e4SLinus Torvalds 		break;
13861da177e4SLinus Torvalds 	    }
13871da177e4SLinus Torvalds 	case IDE_0:
13881da177e4SLinus Torvalds 	    {
13891da177e4SLinus Torvalds 	    	SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
13901da177e4SLinus Torvalds /*
13911da177e4SLinus Torvalds ** Enable the IDE alternate status base address mapping
13921da177e4SLinus Torvalds */
13931da177e4SLinus Torvalds 	    	ide_addr.as_uchar = 0;
13941da177e4SLinus Torvalds 		ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
13951da177e4SLinus Torvalds 
13961da177e4SLinus Torvalds 		SMC37c669_write_config(
13971da177e4SLinus Torvalds 		    SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
13981da177e4SLinus Torvalds 		    ide_addr.as_uchar
13991da177e4SLinus Torvalds 		);
14001da177e4SLinus Torvalds /*
14011da177e4SLinus Torvalds ** Enable the IDE controller base address mapping
14021da177e4SLinus Torvalds */
14031da177e4SLinus Torvalds 		ide_addr.as_uchar = 0;
14041da177e4SLinus Torvalds 		ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
14051da177e4SLinus Torvalds 
14061da177e4SLinus Torvalds 		SMC37c669_write_config(
14071da177e4SLinus Torvalds 		    SMC37c669_IDE_BASE_ADDRESS_INDEX,
14081da177e4SLinus Torvalds 		    ide_addr.as_uchar
14091da177e4SLinus Torvalds 		);
14101da177e4SLinus Torvalds 		ret_val = TRUE;
14111da177e4SLinus Torvalds 		break;
14121da177e4SLinus Torvalds 	    }
14131da177e4SLinus Torvalds     }
14141da177e4SLinus Torvalds /*
14151da177e4SLinus Torvalds ** Exit configuration mode and return
14161da177e4SLinus Torvalds */
14171da177e4SLinus Torvalds     SMC37c669_config_mode( FALSE );
14181da177e4SLinus Torvalds 
14191da177e4SLinus Torvalds     return ret_val;
14201da177e4SLinus Torvalds }
14211da177e4SLinus Torvalds 
14221da177e4SLinus Torvalds 
14231da177e4SLinus Torvalds /*
14241da177e4SLinus Torvalds **++
14251da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
14261da177e4SLinus Torvalds **
14271da177e4SLinus Torvalds **      This function disables a device function within the
14281da177e4SLinus Torvalds **	SMC37c669 Super I/O controller.
14291da177e4SLinus Torvalds **
14301da177e4SLinus Torvalds **  FORMAL PARAMETERS:
14311da177e4SLinus Torvalds **
14321da177e4SLinus Torvalds **      func:
14331da177e4SLinus Torvalds **          Which function to disable
14341da177e4SLinus Torvalds **
14351da177e4SLinus Torvalds **  RETURN VALUE:
14361da177e4SLinus Torvalds **
14371da177e4SLinus Torvalds **      Return TRUE if the device function was disabled, otherwise, FALSE
14381da177e4SLinus Torvalds **
14391da177e4SLinus Torvalds **  SIDE EFFECTS:
14401da177e4SLinus Torvalds **
14411da177e4SLinus Torvalds **      {@description or none@}
14421da177e4SLinus Torvalds **
14431da177e4SLinus Torvalds **  DESIGN:
14441da177e4SLinus Torvalds **
14451da177e4SLinus Torvalds **      Disabling a function in the SMC37c669 device involves
14461da177e4SLinus Torvalds **	disabling all the function's mappings (port, irq, drq ...).
14471da177e4SLinus Torvalds **	A shadow copy of the device configuration is maintained
14481da177e4SLinus Torvalds **	in local storage so we won't worry aboving saving the
14491da177e4SLinus Torvalds **	current configuration information.
14501da177e4SLinus Torvalds **
14511da177e4SLinus Torvalds **--
14521da177e4SLinus Torvalds */
SMC37c669_disable_device(unsigned int func)14531da177e4SLinus Torvalds unsigned int __init SMC37c669_disable_device ( unsigned int func )
14541da177e4SLinus Torvalds {
14551da177e4SLinus Torvalds     unsigned int ret_val = FALSE;
14561da177e4SLinus Torvalds 
14571da177e4SLinus Torvalds /*
14581da177e4SLinus Torvalds ** Put the device into configuration mode
14591da177e4SLinus Torvalds */
14601da177e4SLinus Torvalds     SMC37c669_config_mode( TRUE );
14611da177e4SLinus Torvalds     switch ( func ) {
14621da177e4SLinus Torvalds     	case SERIAL_0:
14631da177e4SLinus Torvalds 	    {
14641da177e4SLinus Torvalds 	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
14651da177e4SLinus Torvalds 		SMC37c669_SERIAL_IRQ_REGISTER irq;
14661da177e4SLinus Torvalds /*
14671da177e4SLinus Torvalds ** Disable the serial 1 IRQ mapping
14681da177e4SLinus Torvalds */
14691da177e4SLinus Torvalds 	    	irq.as_uchar =
14701da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
14711da177e4SLinus Torvalds 
14721da177e4SLinus Torvalds 		irq.by_field.uart1_irq = 0;
14731da177e4SLinus Torvalds 
14741da177e4SLinus Torvalds 		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
14751da177e4SLinus Torvalds /*
14761da177e4SLinus Torvalds ** Disable the serial 1 port base address mapping
14771da177e4SLinus Torvalds */
14781da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
14791da177e4SLinus Torvalds 		SMC37c669_write_config(
14801da177e4SLinus Torvalds 		    SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
14811da177e4SLinus Torvalds 		    base_addr.as_uchar
14821da177e4SLinus Torvalds 		);
14831da177e4SLinus Torvalds 		ret_val = TRUE;
14841da177e4SLinus Torvalds 		break;
14851da177e4SLinus Torvalds 	    }
14861da177e4SLinus Torvalds 	case SERIAL_1:
14871da177e4SLinus Torvalds 	    {
14881da177e4SLinus Torvalds 	    	SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
14891da177e4SLinus Torvalds 		SMC37c669_SERIAL_IRQ_REGISTER irq;
14901da177e4SLinus Torvalds /*
14911da177e4SLinus Torvalds ** Disable the serial 2 IRQ mapping
14921da177e4SLinus Torvalds */
14931da177e4SLinus Torvalds 	    	irq.as_uchar =
14941da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
14951da177e4SLinus Torvalds 
14961da177e4SLinus Torvalds 		irq.by_field.uart2_irq = 0;
14971da177e4SLinus Torvalds 
14981da177e4SLinus Torvalds 		SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
14991da177e4SLinus Torvalds /*
15001da177e4SLinus Torvalds ** Disable the serial 2 port base address mapping
15011da177e4SLinus Torvalds */
15021da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
15031da177e4SLinus Torvalds 
15041da177e4SLinus Torvalds 		SMC37c669_write_config(
15051da177e4SLinus Torvalds 		    SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
15061da177e4SLinus Torvalds 		    base_addr.as_uchar
15071da177e4SLinus Torvalds 		);
15081da177e4SLinus Torvalds 		ret_val = TRUE;
15091da177e4SLinus Torvalds 		break;
15101da177e4SLinus Torvalds 	    }
15111da177e4SLinus Torvalds 	case PARALLEL_0:
15121da177e4SLinus Torvalds 	    {
15131da177e4SLinus Torvalds 	    	SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
15141da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
15151da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
15161da177e4SLinus Torvalds /*
15171da177e4SLinus Torvalds ** Disable the parallel port DMA channel mapping
15181da177e4SLinus Torvalds */
15191da177e4SLinus Torvalds 	    	drq.as_uchar =
15201da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
15211da177e4SLinus Torvalds 
15221da177e4SLinus Torvalds 		drq.by_field.ppt_drq = 0;
15231da177e4SLinus Torvalds 
15241da177e4SLinus Torvalds 		SMC37c669_write_config(
15251da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
15261da177e4SLinus Torvalds 		    drq.as_uchar
15271da177e4SLinus Torvalds 		);
15281da177e4SLinus Torvalds /*
15291da177e4SLinus Torvalds ** Disable the parallel port IRQ mapping
15301da177e4SLinus Torvalds */
15311da177e4SLinus Torvalds 		irq.as_uchar =
15321da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
15331da177e4SLinus Torvalds 
15341da177e4SLinus Torvalds 		irq.by_field.ppt_irq = 0;
15351da177e4SLinus Torvalds 
15361da177e4SLinus Torvalds 		SMC37c669_write_config(
15371da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
15381da177e4SLinus Torvalds 		    irq.as_uchar
15391da177e4SLinus Torvalds 		);
15401da177e4SLinus Torvalds /*
15411da177e4SLinus Torvalds ** Disable the parallel port base address mapping
15421da177e4SLinus Torvalds */
15431da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds 		SMC37c669_write_config(
15461da177e4SLinus Torvalds 		    SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
15471da177e4SLinus Torvalds 		    base_addr.as_uchar
15481da177e4SLinus Torvalds 		);
15491da177e4SLinus Torvalds 		ret_val = TRUE;
15501da177e4SLinus Torvalds 		break;
15511da177e4SLinus Torvalds 	    }
15521da177e4SLinus Torvalds 	case FLOPPY_0:
15531da177e4SLinus Torvalds 	    {
15541da177e4SLinus Torvalds 	    	SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
15551da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
15561da177e4SLinus Torvalds 		SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
15571da177e4SLinus Torvalds /*
15581da177e4SLinus Torvalds ** Disable the floppy controller DMA channel mapping
15591da177e4SLinus Torvalds */
15601da177e4SLinus Torvalds 	    	drq.as_uchar =
15611da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
15621da177e4SLinus Torvalds 
15631da177e4SLinus Torvalds 		drq.by_field.fdc_drq = 0;
15641da177e4SLinus Torvalds 
15651da177e4SLinus Torvalds 		SMC37c669_write_config(
15661da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_DRQ_INDEX,
15671da177e4SLinus Torvalds 		    drq.as_uchar
15681da177e4SLinus Torvalds 		);
15691da177e4SLinus Torvalds /*
15701da177e4SLinus Torvalds ** Disable the floppy controller IRQ mapping
15711da177e4SLinus Torvalds */
15721da177e4SLinus Torvalds 		irq.as_uchar =
15731da177e4SLinus Torvalds 		    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
15741da177e4SLinus Torvalds 
15751da177e4SLinus Torvalds 		irq.by_field.fdc_irq = 0;
15761da177e4SLinus Torvalds 
15771da177e4SLinus Torvalds 		SMC37c669_write_config(
15781da177e4SLinus Torvalds 		    SMC37c669_PARALLEL_FDC_IRQ_INDEX,
15791da177e4SLinus Torvalds 		    irq.as_uchar
15801da177e4SLinus Torvalds 		);
15811da177e4SLinus Torvalds /*
15821da177e4SLinus Torvalds ** Disable the floppy controller base address mapping
15831da177e4SLinus Torvalds */
15841da177e4SLinus Torvalds 		base_addr.as_uchar = 0;
15851da177e4SLinus Torvalds 
15861da177e4SLinus Torvalds 		SMC37c669_write_config(
15871da177e4SLinus Torvalds 		    SMC37c669_FDC_BASE_ADDRESS_INDEX,
15881da177e4SLinus Torvalds 		    base_addr.as_uchar
15891da177e4SLinus Torvalds 		);
15901da177e4SLinus Torvalds 		ret_val = TRUE;
15911da177e4SLinus Torvalds 		break;
15921da177e4SLinus Torvalds 	    }
15931da177e4SLinus Torvalds 	case IDE_0:
15941da177e4SLinus Torvalds 	    {
15951da177e4SLinus Torvalds 	    	SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
15961da177e4SLinus Torvalds /*
15971da177e4SLinus Torvalds ** Disable the IDE alternate status base address mapping
15981da177e4SLinus Torvalds */
15991da177e4SLinus Torvalds 	    	ide_addr.as_uchar = 0;
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds 		SMC37c669_write_config(
16021da177e4SLinus Torvalds 		    SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
16031da177e4SLinus Torvalds 		    ide_addr.as_uchar
16041da177e4SLinus Torvalds 		);
16051da177e4SLinus Torvalds /*
16061da177e4SLinus Torvalds ** Disable the IDE controller base address mapping
16071da177e4SLinus Torvalds */
16081da177e4SLinus Torvalds 		ide_addr.as_uchar = 0;
16091da177e4SLinus Torvalds 
16101da177e4SLinus Torvalds 		SMC37c669_write_config(
16111da177e4SLinus Torvalds 		    SMC37c669_IDE_BASE_ADDRESS_INDEX,
16121da177e4SLinus Torvalds 		    ide_addr.as_uchar
16131da177e4SLinus Torvalds 		);
16141da177e4SLinus Torvalds 		ret_val = TRUE;
16151da177e4SLinus Torvalds 		break;
16161da177e4SLinus Torvalds 	    }
16171da177e4SLinus Torvalds     }
16181da177e4SLinus Torvalds /*
16191da177e4SLinus Torvalds ** Exit configuration mode and return
16201da177e4SLinus Torvalds */
16211da177e4SLinus Torvalds     SMC37c669_config_mode( FALSE );
16221da177e4SLinus Torvalds 
16231da177e4SLinus Torvalds     return ret_val;
16241da177e4SLinus Torvalds }
16251da177e4SLinus Torvalds 
16261da177e4SLinus Torvalds 
16271da177e4SLinus Torvalds /*
16281da177e4SLinus Torvalds **++
16291da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
16301da177e4SLinus Torvalds **
16311da177e4SLinus Torvalds **      This function configures a device function within the
16321da177e4SLinus Torvalds **	SMC37c669 Super I/O controller.
16331da177e4SLinus Torvalds **
16341da177e4SLinus Torvalds **  FORMAL PARAMETERS:
16351da177e4SLinus Torvalds **
16361da177e4SLinus Torvalds **      func:
16371da177e4SLinus Torvalds **          Which device function
16381da177e4SLinus Torvalds **
16391da177e4SLinus Torvalds **      port:
16401da177e4SLinus Torvalds **          I/O port for the function to use
16411da177e4SLinus Torvalds **
16421da177e4SLinus Torvalds **      irq:
16431da177e4SLinus Torvalds **          IRQ for the device function to use
16441da177e4SLinus Torvalds **
16451da177e4SLinus Torvalds **      drq:
16461da177e4SLinus Torvalds **          DMA channel for the device function to use
16471da177e4SLinus Torvalds **
16481da177e4SLinus Torvalds **  RETURN VALUE:
16491da177e4SLinus Torvalds **
16501da177e4SLinus Torvalds **      Returns TRUE if the device function was configured,
16511da177e4SLinus Torvalds **	otherwise, FALSE.
16521da177e4SLinus Torvalds **
16531da177e4SLinus Torvalds **  SIDE EFFECTS:
16541da177e4SLinus Torvalds **
16551da177e4SLinus Torvalds **      {@description or none@}
16561da177e4SLinus Torvalds **
16571da177e4SLinus Torvalds **  DESIGN:
16581da177e4SLinus Torvalds **
16591da177e4SLinus Torvalds **	If this function returns TRUE, the local shadow copy of
16601da177e4SLinus Torvalds **	the configuration is also updated.  If the device function
16611da177e4SLinus Torvalds **	is currently disabled, only the local shadow copy is
16621da177e4SLinus Torvalds **	updated and the actual device function will be updated
16631da177e4SLinus Torvalds **	if/when it is enabled.
16641da177e4SLinus Torvalds **
16651da177e4SLinus Torvalds **--
16661da177e4SLinus Torvalds */
SMC37c669_configure_device(unsigned int func,int port,int irq,int drq)16671da177e4SLinus Torvalds unsigned int __init SMC37c669_configure_device (
16681da177e4SLinus Torvalds     unsigned int func,
16691da177e4SLinus Torvalds     int port,
16701da177e4SLinus Torvalds     int irq,
16711da177e4SLinus Torvalds     int drq )
16721da177e4SLinus Torvalds {
16731da177e4SLinus Torvalds     struct DEVICE_CONFIG *cp;
16741da177e4SLinus Torvalds 
16751da177e4SLinus Torvalds /*
16761da177e4SLinus Torvalds ** Check for a valid configuration
16771da177e4SLinus Torvalds */
16781da177e4SLinus Torvalds     if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
16791da177e4SLinus Torvalds /*
16801da177e4SLinus Torvalds ** Configuration is valid, update the local shadow copy
16811da177e4SLinus Torvalds */
16821da177e4SLinus Torvalds     	if ( ( drq & ~0xFF ) == 0 ) {
16831da177e4SLinus Torvalds 	    cp->drq = drq;
16841da177e4SLinus Torvalds 	}
16851da177e4SLinus Torvalds 	if ( ( irq & ~0xFF ) == 0 ) {
16861da177e4SLinus Torvalds 	    cp->irq = irq;
16871da177e4SLinus Torvalds 	}
16881da177e4SLinus Torvalds 	if ( ( port & ~0xFFFF ) == 0 ) {
16891da177e4SLinus Torvalds 	    cp->port1 = port;
16901da177e4SLinus Torvalds 	}
16911da177e4SLinus Torvalds /*
16921da177e4SLinus Torvalds ** If the device function is enabled, update the actual
16931da177e4SLinus Torvalds ** device configuration.
16941da177e4SLinus Torvalds */
16951da177e4SLinus Torvalds 	if ( SMC37c669_is_device_enabled( func ) ) {
16961da177e4SLinus Torvalds 	    SMC37c669_enable_device( func );
16971da177e4SLinus Torvalds 	}
16981da177e4SLinus Torvalds 	return TRUE;
16991da177e4SLinus Torvalds     }
17001da177e4SLinus Torvalds     return FALSE;
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds 
17031da177e4SLinus Torvalds 
17041da177e4SLinus Torvalds /*
17051da177e4SLinus Torvalds **++
17061da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
17071da177e4SLinus Torvalds **
17081da177e4SLinus Torvalds **      This function determines whether a device function
17091da177e4SLinus Torvalds **	within the SMC37c669 controller is enabled.
17101da177e4SLinus Torvalds **
17111da177e4SLinus Torvalds **  FORMAL PARAMETERS:
17121da177e4SLinus Torvalds **
17131da177e4SLinus Torvalds **      func:
17141da177e4SLinus Torvalds **          Which device function
17151da177e4SLinus Torvalds **
17161da177e4SLinus Torvalds **  RETURN VALUE:
17171da177e4SLinus Torvalds **
17181da177e4SLinus Torvalds **      Returns TRUE if the device function is enabled, otherwise, FALSE
17191da177e4SLinus Torvalds **
17201da177e4SLinus Torvalds **  SIDE EFFECTS:
17211da177e4SLinus Torvalds **
17221da177e4SLinus Torvalds **      {@description or none@}
17231da177e4SLinus Torvalds **
17241da177e4SLinus Torvalds **  DESIGN:
17251da177e4SLinus Torvalds **
17261da177e4SLinus Torvalds **      To check whether a device is enabled we will only look at
17271da177e4SLinus Torvalds **	the port base address mapping.  According to the SMC37c669
17281da177e4SLinus Torvalds **	specification, all of the port base address mappings are
17291da177e4SLinus Torvalds **	disabled if the addr<9:8> (bits <7:6> of the register) are
17301da177e4SLinus Torvalds **	zero.
17311da177e4SLinus Torvalds **
17321da177e4SLinus Torvalds **--
17331da177e4SLinus Torvalds */
SMC37c669_is_device_enabled(unsigned int func)17341da177e4SLinus Torvalds static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
17351da177e4SLinus Torvalds {
17361da177e4SLinus Torvalds     unsigned char base_addr = 0;
17371da177e4SLinus Torvalds     unsigned int dev_ok = FALSE;
17381da177e4SLinus Torvalds     unsigned int ret_val = FALSE;
17391da177e4SLinus Torvalds /*
17401da177e4SLinus Torvalds ** Enter configuration mode
17411da177e4SLinus Torvalds */
17421da177e4SLinus Torvalds     SMC37c669_config_mode( TRUE );
17431da177e4SLinus Torvalds 
17441da177e4SLinus Torvalds     switch ( func ) {
17451da177e4SLinus Torvalds     	case SERIAL_0:
17461da177e4SLinus Torvalds 	    base_addr =
17471da177e4SLinus Torvalds 		SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
17481da177e4SLinus Torvalds 	    dev_ok = TRUE;
17491da177e4SLinus Torvalds 	    break;
17501da177e4SLinus Torvalds 	case SERIAL_1:
17511da177e4SLinus Torvalds 	    base_addr =
17521da177e4SLinus Torvalds 		SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
17531da177e4SLinus Torvalds 	    dev_ok = TRUE;
17541da177e4SLinus Torvalds 	    break;
17551da177e4SLinus Torvalds 	case PARALLEL_0:
17561da177e4SLinus Torvalds 	    base_addr =
17571da177e4SLinus Torvalds 		SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
17581da177e4SLinus Torvalds 	    dev_ok = TRUE;
17591da177e4SLinus Torvalds 	    break;
17601da177e4SLinus Torvalds 	case FLOPPY_0:
17611da177e4SLinus Torvalds 	    base_addr =
17621da177e4SLinus Torvalds 		SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
17631da177e4SLinus Torvalds 	    dev_ok = TRUE;
17641da177e4SLinus Torvalds 	    break;
17651da177e4SLinus Torvalds 	case IDE_0:
17661da177e4SLinus Torvalds 	    base_addr =
17671da177e4SLinus Torvalds 		SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
17681da177e4SLinus Torvalds 	    dev_ok = TRUE;
17691da177e4SLinus Torvalds 	    break;
17701da177e4SLinus Torvalds     }
17711da177e4SLinus Torvalds /*
17721da177e4SLinus Torvalds ** If we have a valid device, check base_addr<7:6> to see if the
17731da177e4SLinus Torvalds ** device is enabled (mapped).
17741da177e4SLinus Torvalds */
17751da177e4SLinus Torvalds     if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
17761da177e4SLinus Torvalds /*
17771da177e4SLinus Torvalds ** The mapping is not disabled, so assume that the function is
17781da177e4SLinus Torvalds ** enabled.
17791da177e4SLinus Torvalds */
17801da177e4SLinus Torvalds     	ret_val = TRUE;
17811da177e4SLinus Torvalds     }
17821da177e4SLinus Torvalds /*
17831da177e4SLinus Torvalds ** Exit configuration mode
17841da177e4SLinus Torvalds */
17851da177e4SLinus Torvalds     SMC37c669_config_mode( FALSE );
17861da177e4SLinus Torvalds 
17871da177e4SLinus Torvalds     return ret_val;
17881da177e4SLinus Torvalds }
17891da177e4SLinus Torvalds 
17901da177e4SLinus Torvalds 
17911da177e4SLinus Torvalds #if 0
17921da177e4SLinus Torvalds /*
17931da177e4SLinus Torvalds **++
17941da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
17951da177e4SLinus Torvalds **
17961da177e4SLinus Torvalds **      This function retrieves the configuration information of a
17971da177e4SLinus Torvalds **	device function within the SMC37c699 Super I/O controller.
17981da177e4SLinus Torvalds **
17991da177e4SLinus Torvalds **  FORMAL PARAMETERS:
18001da177e4SLinus Torvalds **
18011da177e4SLinus Torvalds **      func:
18021da177e4SLinus Torvalds **          Which device function
18031da177e4SLinus Torvalds **
18041da177e4SLinus Torvalds **      port:
18051da177e4SLinus Torvalds **          I/O port returned
18061da177e4SLinus Torvalds **
18071da177e4SLinus Torvalds **      irq:
18081da177e4SLinus Torvalds **          IRQ returned
18091da177e4SLinus Torvalds **
18101da177e4SLinus Torvalds **      drq:
18111da177e4SLinus Torvalds **          DMA channel returned
18121da177e4SLinus Torvalds **
18131da177e4SLinus Torvalds **  RETURN VALUE:
18141da177e4SLinus Torvalds **
18151da177e4SLinus Torvalds **      Returns TRUE if the device configuration was successfully
18161da177e4SLinus Torvalds **	retrieved, otherwise, FALSE.
18171da177e4SLinus Torvalds **
18181da177e4SLinus Torvalds **  SIDE EFFECTS:
18191da177e4SLinus Torvalds **
18201da177e4SLinus Torvalds **      The data pointed to by the port, irq, and drq parameters
18211da177e4SLinus Torvalds **	my be modified even if the configuration is not successfully
18221da177e4SLinus Torvalds **	retrieved.
18231da177e4SLinus Torvalds **
18241da177e4SLinus Torvalds **  DESIGN:
18251da177e4SLinus Torvalds **
18261da177e4SLinus Torvalds **      The device configuration is fetched from the local shadow
18271da177e4SLinus Torvalds **	copy.  Any unused parameters will be set to -1.  Any
18281da177e4SLinus Torvalds **	parameter which is not desired can specify the NULL
18291da177e4SLinus Torvalds **	pointer.
18301da177e4SLinus Torvalds **
18311da177e4SLinus Torvalds **--
18321da177e4SLinus Torvalds */
18331da177e4SLinus Torvalds static unsigned int __init SMC37c669_get_device_config (
18341da177e4SLinus Torvalds     unsigned int func,
18351da177e4SLinus Torvalds     int *port,
18361da177e4SLinus Torvalds     int *irq,
18371da177e4SLinus Torvalds     int *drq )
18381da177e4SLinus Torvalds {
18391da177e4SLinus Torvalds     struct DEVICE_CONFIG *cp;
18401da177e4SLinus Torvalds     unsigned int ret_val = FALSE;
18411da177e4SLinus Torvalds /*
18421da177e4SLinus Torvalds ** Check for a valid device configuration
18431da177e4SLinus Torvalds */
18441da177e4SLinus Torvalds     if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {
18451da177e4SLinus Torvalds     	if ( drq != NULL ) {
18461da177e4SLinus Torvalds 	    *drq = cp->drq;
18471da177e4SLinus Torvalds 	    ret_val = TRUE;
18481da177e4SLinus Torvalds 	}
18491da177e4SLinus Torvalds 	if ( irq != NULL ) {
18501da177e4SLinus Torvalds 	    *irq = cp->irq;
18511da177e4SLinus Torvalds 	    ret_val = TRUE;
18521da177e4SLinus Torvalds 	}
18531da177e4SLinus Torvalds 	if ( port != NULL ) {
18541da177e4SLinus Torvalds 	    *port = cp->port1;
18551da177e4SLinus Torvalds 	    ret_val = TRUE;
18561da177e4SLinus Torvalds 	}
18571da177e4SLinus Torvalds     }
18581da177e4SLinus Torvalds     return ret_val;
18591da177e4SLinus Torvalds }
18601da177e4SLinus Torvalds #endif
18611da177e4SLinus Torvalds 
18621da177e4SLinus Torvalds 
18631da177e4SLinus Torvalds /*
18641da177e4SLinus Torvalds **++
18651da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
18661da177e4SLinus Torvalds **
18671da177e4SLinus Torvalds **      This function displays the current state of the SMC37c699
18681da177e4SLinus Torvalds **	Super I/O controller's device functions.
18691da177e4SLinus Torvalds **
18701da177e4SLinus Torvalds **  FORMAL PARAMETERS:
18711da177e4SLinus Torvalds **
18721da177e4SLinus Torvalds **      None
18731da177e4SLinus Torvalds **
18741da177e4SLinus Torvalds **  RETURN VALUE:
18751da177e4SLinus Torvalds **
18761da177e4SLinus Torvalds **      None
18771da177e4SLinus Torvalds **
18781da177e4SLinus Torvalds **  SIDE EFFECTS:
18791da177e4SLinus Torvalds **
18801da177e4SLinus Torvalds **      None
18811da177e4SLinus Torvalds **
18821da177e4SLinus Torvalds **--
18831da177e4SLinus Torvalds */
SMC37c669_display_device_info(void)18841da177e4SLinus Torvalds void __init SMC37c669_display_device_info ( void )
18851da177e4SLinus Torvalds {
18861da177e4SLinus Torvalds     if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
18871da177e4SLinus Torvalds     	printk( "  Serial 0:    Enabled [ Port 0x%x, IRQ %d ]\n",
18881da177e4SLinus Torvalds 		 local_config[ SERIAL_0 ].port1,
18891da177e4SLinus Torvalds 		 local_config[ SERIAL_0 ].irq
18901da177e4SLinus Torvalds 	);
18911da177e4SLinus Torvalds     }
18921da177e4SLinus Torvalds     else {
18931da177e4SLinus Torvalds     	printk( "  Serial 0:    Disabled\n" );
18941da177e4SLinus Torvalds     }
18951da177e4SLinus Torvalds 
18961da177e4SLinus Torvalds     if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
18971da177e4SLinus Torvalds     	printk( "  Serial 1:    Enabled [ Port 0x%x, IRQ %d ]\n",
18981da177e4SLinus Torvalds 		 local_config[ SERIAL_1 ].port1,
18991da177e4SLinus Torvalds 		 local_config[ SERIAL_1 ].irq
19001da177e4SLinus Torvalds 	);
19011da177e4SLinus Torvalds     }
19021da177e4SLinus Torvalds     else {
19031da177e4SLinus Torvalds     	printk( "  Serial 1:    Disabled\n" );
19041da177e4SLinus Torvalds     }
19051da177e4SLinus Torvalds 
19061da177e4SLinus Torvalds     if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
19071da177e4SLinus Torvalds     	printk( "  Parallel:    Enabled [ Port 0x%x, IRQ %d/%d ]\n",
19081da177e4SLinus Torvalds 		 local_config[ PARALLEL_0 ].port1,
19091da177e4SLinus Torvalds 		 local_config[ PARALLEL_0 ].irq,
19101da177e4SLinus Torvalds 		 local_config[ PARALLEL_0 ].drq
19111da177e4SLinus Torvalds 	);
19121da177e4SLinus Torvalds     }
19131da177e4SLinus Torvalds     else {
19141da177e4SLinus Torvalds     	printk( "  Parallel:    Disabled\n" );
19151da177e4SLinus Torvalds     }
19161da177e4SLinus Torvalds 
19171da177e4SLinus Torvalds     if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
19181da177e4SLinus Torvalds     	printk( "  Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
19191da177e4SLinus Torvalds 		 local_config[ FLOPPY_0 ].port1,
19201da177e4SLinus Torvalds 		 local_config[ FLOPPY_0 ].irq,
19211da177e4SLinus Torvalds 		 local_config[ FLOPPY_0 ].drq
19221da177e4SLinus Torvalds 	);
19231da177e4SLinus Torvalds     }
19241da177e4SLinus Torvalds     else {
19251da177e4SLinus Torvalds     	printk( "  Floppy Ctrl: Disabled\n" );
19261da177e4SLinus Torvalds     }
19271da177e4SLinus Torvalds 
19281da177e4SLinus Torvalds     if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
19291da177e4SLinus Torvalds     	printk( "  IDE 0:       Enabled [ Port 0x%x, IRQ %d ]\n",
19301da177e4SLinus Torvalds 		 local_config[ IDE_0 ].port1,
19311da177e4SLinus Torvalds 		 local_config[ IDE_0 ].irq
19321da177e4SLinus Torvalds 	);
19331da177e4SLinus Torvalds     }
19341da177e4SLinus Torvalds     else {
19351da177e4SLinus Torvalds     	printk( "  IDE 0:       Disabled\n" );
19361da177e4SLinus Torvalds     }
19371da177e4SLinus Torvalds }
19381da177e4SLinus Torvalds 
19391da177e4SLinus Torvalds 
19401da177e4SLinus Torvalds /*
19411da177e4SLinus Torvalds **++
19421da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
19431da177e4SLinus Torvalds **
19441da177e4SLinus Torvalds **      This function puts the SMC37c669 Super I/O controller into,
19451da177e4SLinus Torvalds **	and takes it out of, configuration mode.
19461da177e4SLinus Torvalds **
19471da177e4SLinus Torvalds **  FORMAL PARAMETERS:
19481da177e4SLinus Torvalds **
19491da177e4SLinus Torvalds **      enable:
19501da177e4SLinus Torvalds **          TRUE to enter configuration mode, FALSE to exit.
19511da177e4SLinus Torvalds **
19521da177e4SLinus Torvalds **  RETURN VALUE:
19531da177e4SLinus Torvalds **
19541da177e4SLinus Torvalds **      None
19551da177e4SLinus Torvalds **
19561da177e4SLinus Torvalds **  SIDE EFFECTS:
19571da177e4SLinus Torvalds **
19581da177e4SLinus Torvalds **      The SMC37c669 controller may be left in configuration mode.
19591da177e4SLinus Torvalds **
19601da177e4SLinus Torvalds **--
19611da177e4SLinus Torvalds */
SMC37c669_config_mode(unsigned int enable)19621da177e4SLinus Torvalds static void __init SMC37c669_config_mode(
19631da177e4SLinus Torvalds     unsigned int enable )
19641da177e4SLinus Torvalds {
19651da177e4SLinus Torvalds     if ( enable ) {
19661da177e4SLinus Torvalds /*
19671da177e4SLinus Torvalds ** To enter configuration mode, two writes in succession to the index
19681da177e4SLinus Torvalds ** port are required.  If a write to another address or port occurs
19691da177e4SLinus Torvalds ** between these two writes, the chip does not enter configuration
19701da177e4SLinus Torvalds ** mode.  Therefore, a spinlock is placed around the two writes to
19711da177e4SLinus Torvalds ** guarantee that they complete uninterrupted.
19721da177e4SLinus Torvalds */
19731da177e4SLinus Torvalds 	spin_lock(&smc_lock);
19741da177e4SLinus Torvalds     	wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
19751da177e4SLinus Torvalds     	wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
19761da177e4SLinus Torvalds 	spin_unlock(&smc_lock);
19771da177e4SLinus Torvalds     }
19781da177e4SLinus Torvalds     else {
19791da177e4SLinus Torvalds     	wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
19801da177e4SLinus Torvalds     }
19811da177e4SLinus Torvalds }
19821da177e4SLinus Torvalds 
19831da177e4SLinus Torvalds /*
19841da177e4SLinus Torvalds **++
19851da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
19861da177e4SLinus Torvalds **
19871da177e4SLinus Torvalds **      This function reads an SMC37c669 Super I/O controller
19881da177e4SLinus Torvalds **	configuration register.  This function assumes that the
19891da177e4SLinus Torvalds **	device is already in configuration mode.
19901da177e4SLinus Torvalds **
19911da177e4SLinus Torvalds **  FORMAL PARAMETERS:
19921da177e4SLinus Torvalds **
19931da177e4SLinus Torvalds **      index:
19941da177e4SLinus Torvalds **          Index value of configuration register to read
19951da177e4SLinus Torvalds **
19961da177e4SLinus Torvalds **  RETURN VALUE:
19971da177e4SLinus Torvalds **
19981da177e4SLinus Torvalds **      Data read from configuration register
19991da177e4SLinus Torvalds **
20001da177e4SLinus Torvalds **  SIDE EFFECTS:
20011da177e4SLinus Torvalds **
20021da177e4SLinus Torvalds **      None
20031da177e4SLinus Torvalds **
20041da177e4SLinus Torvalds **--
20051da177e4SLinus Torvalds */
SMC37c669_read_config(unsigned char index)20061da177e4SLinus Torvalds static unsigned char __init SMC37c669_read_config(
20071da177e4SLinus Torvalds     unsigned char index )
20081da177e4SLinus Torvalds {
20091da177e4SLinus Torvalds 	wb(&SMC37c669->index_port, index);
2010203308a5SMasahiro Yamada 	return rb(&SMC37c669->data_port);
20111da177e4SLinus Torvalds }
20121da177e4SLinus Torvalds 
20131da177e4SLinus Torvalds /*
20141da177e4SLinus Torvalds **++
20151da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
20161da177e4SLinus Torvalds **
20171da177e4SLinus Torvalds **      This function writes an SMC37c669 Super I/O controller
20181da177e4SLinus Torvalds **	configuration register.  This function assumes that the
20191da177e4SLinus Torvalds **	device is already in configuration mode.
20201da177e4SLinus Torvalds **
20211da177e4SLinus Torvalds **  FORMAL PARAMETERS:
20221da177e4SLinus Torvalds **
20231da177e4SLinus Torvalds **      index:
20241da177e4SLinus Torvalds **          Index of configuration register to write
20251da177e4SLinus Torvalds **
20261da177e4SLinus Torvalds **      data:
20271da177e4SLinus Torvalds **          Data to be written
20281da177e4SLinus Torvalds **
20291da177e4SLinus Torvalds **  RETURN VALUE:
20301da177e4SLinus Torvalds **
20311da177e4SLinus Torvalds **      None
20321da177e4SLinus Torvalds **
20331da177e4SLinus Torvalds **  SIDE EFFECTS:
20341da177e4SLinus Torvalds **
20351da177e4SLinus Torvalds **      None
20361da177e4SLinus Torvalds **
20371da177e4SLinus Torvalds **--
20381da177e4SLinus Torvalds */
SMC37c669_write_config(unsigned char index,unsigned char data)20391da177e4SLinus Torvalds static void __init SMC37c669_write_config(
20401da177e4SLinus Torvalds     unsigned char index,
20411da177e4SLinus Torvalds     unsigned char data )
20421da177e4SLinus Torvalds {
20431da177e4SLinus Torvalds     wb( &SMC37c669->index_port, index );
20441da177e4SLinus Torvalds     wb( &SMC37c669->data_port, data );
20451da177e4SLinus Torvalds }
20461da177e4SLinus Torvalds 
20471da177e4SLinus Torvalds 
20481da177e4SLinus Torvalds /*
20491da177e4SLinus Torvalds **++
20501da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
20511da177e4SLinus Torvalds **
20521da177e4SLinus Torvalds **      This function initializes the local device
20531da177e4SLinus Torvalds **	configuration storage.  This function assumes
20541da177e4SLinus Torvalds **	that the device is already in configuration
20551da177e4SLinus Torvalds **	mode.
20561da177e4SLinus Torvalds **
20571da177e4SLinus Torvalds **  FORMAL PARAMETERS:
20581da177e4SLinus Torvalds **
20591da177e4SLinus Torvalds **      None
20601da177e4SLinus Torvalds **
20611da177e4SLinus Torvalds **  RETURN VALUE:
20621da177e4SLinus Torvalds **
20631da177e4SLinus Torvalds **      None
20641da177e4SLinus Torvalds **
20651da177e4SLinus Torvalds **  SIDE EFFECTS:
20661da177e4SLinus Torvalds **
20671da177e4SLinus Torvalds **      Local storage for device configuration information
20681da177e4SLinus Torvalds **	is initialized.
20691da177e4SLinus Torvalds **
20701da177e4SLinus Torvalds **--
20711da177e4SLinus Torvalds */
SMC37c669_init_local_config(void)20721da177e4SLinus Torvalds static void __init SMC37c669_init_local_config ( void )
20731da177e4SLinus Torvalds {
20741da177e4SLinus Torvalds     SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
20751da177e4SLinus Torvalds     SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
20761da177e4SLinus Torvalds     SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
20771da177e4SLinus Torvalds     SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
20781da177e4SLinus Torvalds     SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
20791da177e4SLinus Torvalds     SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
20801da177e4SLinus Torvalds     SMC37c669_IDE_ADDRESS_REGISTER ide_base;
20811da177e4SLinus Torvalds     SMC37c669_IDE_ADDRESS_REGISTER ide_alt;
20821da177e4SLinus Torvalds 
20831da177e4SLinus Torvalds /*
20841da177e4SLinus Torvalds ** Get serial port 1 base address
20851da177e4SLinus Torvalds */
20861da177e4SLinus Torvalds     uart_base.as_uchar =
20871da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
20881da177e4SLinus Torvalds /*
20891da177e4SLinus Torvalds ** Get IRQs for serial ports 1 & 2
20901da177e4SLinus Torvalds */
20911da177e4SLinus Torvalds     uart_irqs.as_uchar =
20921da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
20931da177e4SLinus Torvalds /*
20941da177e4SLinus Torvalds ** Store local configuration information for serial port 1
20951da177e4SLinus Torvalds */
20961da177e4SLinus Torvalds     local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
20971da177e4SLinus Torvalds     local_config[SERIAL_0].irq =
20981da177e4SLinus Torvalds 	SMC37c669_xlate_irq(
20991da177e4SLinus Torvalds 	    SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq )
21001da177e4SLinus Torvalds 	);
21011da177e4SLinus Torvalds /*
21021da177e4SLinus Torvalds ** Get serial port 2 base address
21031da177e4SLinus Torvalds */
21041da177e4SLinus Torvalds     uart_base.as_uchar =
21051da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
21061da177e4SLinus Torvalds /*
21071da177e4SLinus Torvalds ** Store local configuration information for serial port 2
21081da177e4SLinus Torvalds */
21091da177e4SLinus Torvalds     local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
21101da177e4SLinus Torvalds     local_config[SERIAL_1].irq =
21111da177e4SLinus Torvalds 	SMC37c669_xlate_irq(
21121da177e4SLinus Torvalds 	    SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq )
21131da177e4SLinus Torvalds 	);
21141da177e4SLinus Torvalds /*
21151da177e4SLinus Torvalds ** Get parallel port base address
21161da177e4SLinus Torvalds */
21171da177e4SLinus Torvalds     ppt_base.as_uchar =
21181da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
21191da177e4SLinus Torvalds /*
21201da177e4SLinus Torvalds ** Get IRQs for parallel port and floppy controller
21211da177e4SLinus Torvalds */
21221da177e4SLinus Torvalds     ppt_fdc_irqs.as_uchar =
21231da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
21241da177e4SLinus Torvalds /*
21251da177e4SLinus Torvalds ** Get DRQs for parallel port and floppy controller
21261da177e4SLinus Torvalds */
21271da177e4SLinus Torvalds     ppt_fdc_drqs.as_uchar =
21281da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
21291da177e4SLinus Torvalds /*
21301da177e4SLinus Torvalds ** Store local configuration information for parallel port
21311da177e4SLinus Torvalds */
21321da177e4SLinus Torvalds     local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
21331da177e4SLinus Torvalds     local_config[PARALLEL_0].irq =
21341da177e4SLinus Torvalds 	SMC37c669_xlate_irq(
21351da177e4SLinus Torvalds 	    SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
21361da177e4SLinus Torvalds 	);
21371da177e4SLinus Torvalds     local_config[PARALLEL_0].drq =
21381da177e4SLinus Torvalds 	SMC37c669_xlate_drq(
21391da177e4SLinus Torvalds 	    SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
21401da177e4SLinus Torvalds 	);
21411da177e4SLinus Torvalds /*
21421da177e4SLinus Torvalds ** Get floppy controller base address
21431da177e4SLinus Torvalds */
21441da177e4SLinus Torvalds     fdc_base.as_uchar =
21451da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
21461da177e4SLinus Torvalds /*
21471da177e4SLinus Torvalds ** Store local configuration information for floppy controller
21481da177e4SLinus Torvalds */
21491da177e4SLinus Torvalds     local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
21501da177e4SLinus Torvalds     local_config[FLOPPY_0].irq =
21511da177e4SLinus Torvalds 	SMC37c669_xlate_irq(
21521da177e4SLinus Torvalds 	    SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
21531da177e4SLinus Torvalds 	);
21541da177e4SLinus Torvalds     local_config[FLOPPY_0].drq =
21551da177e4SLinus Torvalds 	SMC37c669_xlate_drq(
21561da177e4SLinus Torvalds 	    SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
21571da177e4SLinus Torvalds 	);
21581da177e4SLinus Torvalds /*
21591da177e4SLinus Torvalds ** Get IDE controller base address
21601da177e4SLinus Torvalds */
21611da177e4SLinus Torvalds     ide_base.as_uchar =
21621da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
21631da177e4SLinus Torvalds /*
21641da177e4SLinus Torvalds ** Get IDE alternate status base address
21651da177e4SLinus Torvalds */
21661da177e4SLinus Torvalds     ide_alt.as_uchar =
21671da177e4SLinus Torvalds 	SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
21681da177e4SLinus Torvalds /*
21691da177e4SLinus Torvalds ** Store local configuration information for IDE controller
21701da177e4SLinus Torvalds */
21711da177e4SLinus Torvalds     local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
21721da177e4SLinus Torvalds     local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
21731da177e4SLinus Torvalds     local_config[IDE_0].irq = 14;
21741da177e4SLinus Torvalds }
21751da177e4SLinus Torvalds 
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds /*
21781da177e4SLinus Torvalds **++
21791da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
21801da177e4SLinus Torvalds **
21811da177e4SLinus Torvalds **      This function returns a pointer to the local shadow
21821da177e4SLinus Torvalds **	configuration of the requested device function.
21831da177e4SLinus Torvalds **
21841da177e4SLinus Torvalds **  FORMAL PARAMETERS:
21851da177e4SLinus Torvalds **
21861da177e4SLinus Torvalds **      func:
21871da177e4SLinus Torvalds **          Which device function
21881da177e4SLinus Torvalds **
21891da177e4SLinus Torvalds **  RETURN VALUE:
21901da177e4SLinus Torvalds **
21911da177e4SLinus Torvalds **      Returns a pointer to the DEVICE_CONFIG structure for the
21921da177e4SLinus Torvalds **	requested function, otherwise, NULL.
21931da177e4SLinus Torvalds **
21941da177e4SLinus Torvalds **  SIDE EFFECTS:
21951da177e4SLinus Torvalds **
21961da177e4SLinus Torvalds **      {@description or none@}
21971da177e4SLinus Torvalds **
21981da177e4SLinus Torvalds **--
21991da177e4SLinus Torvalds */
SMC37c669_get_config(unsigned int func)22001da177e4SLinus Torvalds static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
22011da177e4SLinus Torvalds {
22021da177e4SLinus Torvalds     struct DEVICE_CONFIG *cp = NULL;
22031da177e4SLinus Torvalds 
22041da177e4SLinus Torvalds     switch ( func ) {
22051da177e4SLinus Torvalds     	case SERIAL_0:
22061da177e4SLinus Torvalds 	    cp = &local_config[ SERIAL_0 ];
22071da177e4SLinus Torvalds 	    break;
22081da177e4SLinus Torvalds 	case SERIAL_1:
22091da177e4SLinus Torvalds 	    cp = &local_config[ SERIAL_1 ];
22101da177e4SLinus Torvalds 	    break;
22111da177e4SLinus Torvalds 	case PARALLEL_0:
22121da177e4SLinus Torvalds 	    cp = &local_config[ PARALLEL_0 ];
22131da177e4SLinus Torvalds 	    break;
22141da177e4SLinus Torvalds 	case FLOPPY_0:
22151da177e4SLinus Torvalds 	    cp = &local_config[ FLOPPY_0 ];
22161da177e4SLinus Torvalds 	    break;
22171da177e4SLinus Torvalds 	case IDE_0:
22181da177e4SLinus Torvalds 	    cp = &local_config[ IDE_0 ];
22191da177e4SLinus Torvalds 	    break;
22201da177e4SLinus Torvalds     }
22211da177e4SLinus Torvalds     return cp;
22221da177e4SLinus Torvalds }
22231da177e4SLinus Torvalds 
22241da177e4SLinus Torvalds /*
22251da177e4SLinus Torvalds **++
22261da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
22271da177e4SLinus Torvalds **
22281da177e4SLinus Torvalds **      This function translates IRQs back and forth between ISA
22291da177e4SLinus Torvalds **	IRQs and SMC37c669 device IRQs.
22301da177e4SLinus Torvalds **
22311da177e4SLinus Torvalds **  FORMAL PARAMETERS:
22321da177e4SLinus Torvalds **
22331da177e4SLinus Torvalds **      irq:
22341da177e4SLinus Torvalds **          The IRQ to translate
22351da177e4SLinus Torvalds **
22361da177e4SLinus Torvalds **  RETURN VALUE:
22371da177e4SLinus Torvalds **
22381da177e4SLinus Torvalds **      Returns the translated IRQ, otherwise, returns -1.
22391da177e4SLinus Torvalds **
22401da177e4SLinus Torvalds **  SIDE EFFECTS:
22411da177e4SLinus Torvalds **
22421da177e4SLinus Torvalds **      {@description or none@}
22431da177e4SLinus Torvalds **
22441da177e4SLinus Torvalds **--
22451da177e4SLinus Torvalds */
SMC37c669_xlate_irq(int irq)22461da177e4SLinus Torvalds static int __init SMC37c669_xlate_irq ( int irq )
22471da177e4SLinus Torvalds {
22481da177e4SLinus Torvalds     int i, translated_irq = -1;
22491da177e4SLinus Torvalds 
22501da177e4SLinus Torvalds     if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
22511da177e4SLinus Torvalds /*
22521da177e4SLinus Torvalds ** We are translating a device IRQ to an ISA IRQ
22531da177e4SLinus Torvalds */
22541da177e4SLinus Torvalds     	for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
22551da177e4SLinus Torvalds 	    if ( irq == SMC37c669_irq_table[i].device_irq ) {
22561da177e4SLinus Torvalds 	    	translated_irq = SMC37c669_irq_table[i].isa_irq;
22571da177e4SLinus Torvalds 		break;
22581da177e4SLinus Torvalds 	    }
22591da177e4SLinus Torvalds 	}
22601da177e4SLinus Torvalds     }
22611da177e4SLinus Torvalds     else {
22621da177e4SLinus Torvalds /*
22631da177e4SLinus Torvalds ** We are translating an ISA IRQ to a device IRQ
22641da177e4SLinus Torvalds */
22651da177e4SLinus Torvalds     	for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
22661da177e4SLinus Torvalds 	    if ( irq == SMC37c669_irq_table[i].isa_irq ) {
22671da177e4SLinus Torvalds 	    	translated_irq = SMC37c669_irq_table[i].device_irq;
22681da177e4SLinus Torvalds 		break;
22691da177e4SLinus Torvalds 	    }
22701da177e4SLinus Torvalds 	}
22711da177e4SLinus Torvalds     }
22721da177e4SLinus Torvalds     return translated_irq;
22731da177e4SLinus Torvalds }
22741da177e4SLinus Torvalds 
22751da177e4SLinus Torvalds 
22761da177e4SLinus Torvalds /*
22771da177e4SLinus Torvalds **++
22781da177e4SLinus Torvalds **  FUNCTIONAL DESCRIPTION:
22791da177e4SLinus Torvalds **
22801da177e4SLinus Torvalds **      This function translates DMA channels back and forth between
22811da177e4SLinus Torvalds **	ISA DMA channels and SMC37c669 device DMA channels.
22821da177e4SLinus Torvalds **
22831da177e4SLinus Torvalds **  FORMAL PARAMETERS:
22841da177e4SLinus Torvalds **
22851da177e4SLinus Torvalds **      drq:
22861da177e4SLinus Torvalds **          The DMA channel to translate
22871da177e4SLinus Torvalds **
22881da177e4SLinus Torvalds **  RETURN VALUE:
22891da177e4SLinus Torvalds **
22901da177e4SLinus Torvalds **      Returns the translated DMA channel, otherwise, returns -1
22911da177e4SLinus Torvalds **
22921da177e4SLinus Torvalds **  SIDE EFFECTS:
22931da177e4SLinus Torvalds **
22941da177e4SLinus Torvalds **      {@description or none@}
22951da177e4SLinus Torvalds **
22961da177e4SLinus Torvalds **--
22971da177e4SLinus Torvalds */
SMC37c669_xlate_drq(int drq)22981da177e4SLinus Torvalds static int __init SMC37c669_xlate_drq ( int drq )
22991da177e4SLinus Torvalds {
23001da177e4SLinus Torvalds     int i, translated_drq = -1;
23011da177e4SLinus Torvalds 
23021da177e4SLinus Torvalds     if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
23031da177e4SLinus Torvalds /*
23041da177e4SLinus Torvalds ** We are translating a device DMA channel to an ISA DMA channel
23051da177e4SLinus Torvalds */
23061da177e4SLinus Torvalds     	for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
23071da177e4SLinus Torvalds 	    if ( drq == SMC37c669_drq_table[i].device_drq ) {
23081da177e4SLinus Torvalds 	    	translated_drq = SMC37c669_drq_table[i].isa_drq;
23091da177e4SLinus Torvalds 		break;
23101da177e4SLinus Torvalds 	    }
23111da177e4SLinus Torvalds 	}
23121da177e4SLinus Torvalds     }
23131da177e4SLinus Torvalds     else {
23141da177e4SLinus Torvalds /*
23151da177e4SLinus Torvalds ** We are translating an ISA DMA channel to a device DMA channel
23161da177e4SLinus Torvalds */
23171da177e4SLinus Torvalds     	for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
23181da177e4SLinus Torvalds 	    if ( drq == SMC37c669_drq_table[i].isa_drq ) {
23191da177e4SLinus Torvalds 	    	translated_drq = SMC37c669_drq_table[i].device_drq;
23201da177e4SLinus Torvalds 		break;
23211da177e4SLinus Torvalds 	    }
23221da177e4SLinus Torvalds 	}
23231da177e4SLinus Torvalds     }
23241da177e4SLinus Torvalds     return translated_drq;
23251da177e4SLinus Torvalds }
23261da177e4SLinus Torvalds 
23271da177e4SLinus Torvalds #if 0
23281da177e4SLinus Torvalds int __init smcc669_init ( void )
23291da177e4SLinus Torvalds {
23301da177e4SLinus Torvalds     struct INODE *ip;
23311da177e4SLinus Torvalds 
23321da177e4SLinus Torvalds     allocinode( smc_ddb.name, 1, &ip );
23331da177e4SLinus Torvalds     ip->dva = &smc_ddb;
23341da177e4SLinus Torvalds     ip->attr = ATTR$M_WRITE | ATTR$M_READ;
23351da177e4SLinus Torvalds     ip->len[0] = 0x30;
23361da177e4SLinus Torvalds     ip->misc = 0;
23371da177e4SLinus Torvalds     INODE_UNLOCK( ip );
23381da177e4SLinus Torvalds 
23391da177e4SLinus Torvalds     return msg_success;
23401da177e4SLinus Torvalds }
23411da177e4SLinus Torvalds 
23421da177e4SLinus Torvalds int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )
23431da177e4SLinus Torvalds {
23441da177e4SLinus Torvalds     struct INODE *ip;
23451da177e4SLinus Torvalds /*
23461da177e4SLinus Torvalds ** Allow multiple readers but only one writer.  ip->misc keeps track
23471da177e4SLinus Torvalds ** of the number of writers
23481da177e4SLinus Torvalds */
23491da177e4SLinus Torvalds     ip = fp->ip;
23501da177e4SLinus Torvalds     INODE_LOCK( ip );
23511da177e4SLinus Torvalds     if ( fp->mode & ATTR$M_WRITE ) {
23521da177e4SLinus Torvalds 	if ( ip->misc ) {
23531da177e4SLinus Torvalds 	    INODE_UNLOCK( ip );
23541da177e4SLinus Torvalds 	    return msg_failure;	    /* too many writers */
23551da177e4SLinus Torvalds 	}
23561da177e4SLinus Torvalds 	ip->misc++;
23571da177e4SLinus Torvalds     }
23581da177e4SLinus Torvalds /*
23591da177e4SLinus Torvalds ** Treat the information field as a byte offset
23601da177e4SLinus Torvalds */
23611da177e4SLinus Torvalds     *fp->offset = xtoi( info );
23621da177e4SLinus Torvalds     INODE_UNLOCK( ip );
23631da177e4SLinus Torvalds 
23641da177e4SLinus Torvalds     return msg_success;
23651da177e4SLinus Torvalds }
23661da177e4SLinus Torvalds 
23671da177e4SLinus Torvalds int __init smcc669_close( struct FILE *fp )
23681da177e4SLinus Torvalds {
23691da177e4SLinus Torvalds     struct INODE *ip;
23701da177e4SLinus Torvalds 
23711da177e4SLinus Torvalds     ip = fp->ip;
23721da177e4SLinus Torvalds     if ( fp->mode & ATTR$M_WRITE ) {
23731da177e4SLinus Torvalds 	INODE_LOCK( ip );
23741da177e4SLinus Torvalds 	ip->misc--;
23751da177e4SLinus Torvalds 	INODE_UNLOCK( ip );
23761da177e4SLinus Torvalds     }
23771da177e4SLinus Torvalds     return msg_success;
23781da177e4SLinus Torvalds }
23791da177e4SLinus Torvalds 
23801da177e4SLinus Torvalds int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )
23811da177e4SLinus Torvalds {
23821da177e4SLinus Torvalds     int i;
23831da177e4SLinus Torvalds     int length;
23841da177e4SLinus Torvalds     int nbytes;
23851da177e4SLinus Torvalds     struct INODE *ip;
23861da177e4SLinus Torvalds 
23871da177e4SLinus Torvalds /*
23881da177e4SLinus Torvalds ** Always access a byte at a time
23891da177e4SLinus Torvalds */
23901da177e4SLinus Torvalds     ip = fp->ip;
23911da177e4SLinus Torvalds     length = size * number;
23921da177e4SLinus Torvalds     nbytes = 0;
23931da177e4SLinus Torvalds 
23941da177e4SLinus Torvalds     SMC37c669_config_mode( TRUE );
23951da177e4SLinus Torvalds     for ( i = 0; i < length; i++ ) {
23961da177e4SLinus Torvalds 	if ( !inrange( *fp->offset, 0, ip->len[0] ) )
23971da177e4SLinus Torvalds 	    break;
23981da177e4SLinus Torvalds 	*buf++ = SMC37c669_read_config( *fp->offset );
23991da177e4SLinus Torvalds 	*fp->offset += 1;
24001da177e4SLinus Torvalds 	nbytes++;
24011da177e4SLinus Torvalds     }
24021da177e4SLinus Torvalds     SMC37c669_config_mode( FALSE );
24031da177e4SLinus Torvalds     return nbytes;
24041da177e4SLinus Torvalds }
24051da177e4SLinus Torvalds 
24061da177e4SLinus Torvalds int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )
24071da177e4SLinus Torvalds {
24081da177e4SLinus Torvalds     int i;
24091da177e4SLinus Torvalds     int length;
24101da177e4SLinus Torvalds     int nbytes;
24111da177e4SLinus Torvalds     struct INODE *ip;
24121da177e4SLinus Torvalds /*
24131da177e4SLinus Torvalds ** Always access a byte at a time
24141da177e4SLinus Torvalds */
24151da177e4SLinus Torvalds     ip = fp->ip;
24161da177e4SLinus Torvalds     length = size * number;
24171da177e4SLinus Torvalds     nbytes = 0;
24181da177e4SLinus Torvalds 
24191da177e4SLinus Torvalds     SMC37c669_config_mode( TRUE );
24201da177e4SLinus Torvalds     for ( i = 0; i < length; i++ ) {
24211da177e4SLinus Torvalds 	if ( !inrange( *fp->offset, 0, ip->len[0] ) )
24221da177e4SLinus Torvalds 	    break;
24231da177e4SLinus Torvalds 	SMC37c669_write_config( *fp->offset, *buf );
24241da177e4SLinus Torvalds 	*fp->offset += 1;
24251da177e4SLinus Torvalds 	buf++;
24261da177e4SLinus Torvalds 	nbytes++;
24271da177e4SLinus Torvalds     }
24281da177e4SLinus Torvalds     SMC37c669_config_mode( FALSE );
24291da177e4SLinus Torvalds     return nbytes;
24301da177e4SLinus Torvalds }
24311da177e4SLinus Torvalds #endif
24321da177e4SLinus Torvalds 
24331da177e4SLinus Torvalds void __init
SMC37c669_dump_registers(void)24341da177e4SLinus Torvalds SMC37c669_dump_registers(void)
24351da177e4SLinus Torvalds {
24361da177e4SLinus Torvalds   int i;
24371da177e4SLinus Torvalds   for (i = 0; i <= 0x29; i++)
24381da177e4SLinus Torvalds     printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
24391da177e4SLinus Torvalds }
24401da177e4SLinus Torvalds /*+
24411da177e4SLinus Torvalds  * ============================================================================
24421da177e4SLinus Torvalds  * = SMC_init - SMC37c669 Super I/O controller initialization                 =
24431da177e4SLinus Torvalds  * ============================================================================
24441da177e4SLinus Torvalds  *
24451da177e4SLinus Torvalds  * OVERVIEW:
24461da177e4SLinus Torvalds  *
24471da177e4SLinus Torvalds  *      This routine configures and enables device functions on the
24481da177e4SLinus Torvalds  *      SMC37c669 Super I/O controller.
24491da177e4SLinus Torvalds  *
24501da177e4SLinus Torvalds  * FORM OF CALL:
24511da177e4SLinus Torvalds  *
24521da177e4SLinus Torvalds  *      SMC_init( );
24531da177e4SLinus Torvalds  *
24541da177e4SLinus Torvalds  * RETURNS:
24551da177e4SLinus Torvalds  *
24561da177e4SLinus Torvalds  *      Nothing
24571da177e4SLinus Torvalds  *
24581da177e4SLinus Torvalds  * ARGUMENTS:
24591da177e4SLinus Torvalds  *
24601da177e4SLinus Torvalds  *      None
24611da177e4SLinus Torvalds  *
24621da177e4SLinus Torvalds  * SIDE EFFECTS:
24631da177e4SLinus Torvalds  *
24641da177e4SLinus Torvalds  *      None
24651da177e4SLinus Torvalds  *
24661da177e4SLinus Torvalds  */
SMC669_Init(int index)24671da177e4SLinus Torvalds void __init SMC669_Init ( int index )
24681da177e4SLinus Torvalds {
24691da177e4SLinus Torvalds     SMC37c669_CONFIG_REGS *SMC_base;
24701da177e4SLinus Torvalds     unsigned long flags;
24711da177e4SLinus Torvalds 
24721da177e4SLinus Torvalds     local_irq_save(flags);
24731da177e4SLinus Torvalds     if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
24741da177e4SLinus Torvalds #if SMC_DEBUG
24751da177e4SLinus Torvalds 	SMC37c669_config_mode( TRUE );
24761da177e4SLinus Torvalds 	SMC37c669_dump_registers( );
24771da177e4SLinus Torvalds 	SMC37c669_config_mode( FALSE );
24781da177e4SLinus Torvalds         SMC37c669_display_device_info( );
24791da177e4SLinus Torvalds #endif
24801da177e4SLinus Torvalds         SMC37c669_disable_device( SERIAL_0 );
24811da177e4SLinus Torvalds         SMC37c669_configure_device(
24821da177e4SLinus Torvalds             SERIAL_0,
24831da177e4SLinus Torvalds             COM1_BASE,
24841da177e4SLinus Torvalds             COM1_IRQ,
24851da177e4SLinus Torvalds             -1
24861da177e4SLinus Torvalds         );
24871da177e4SLinus Torvalds         SMC37c669_enable_device( SERIAL_0 );
24881da177e4SLinus Torvalds 
24891da177e4SLinus Torvalds         SMC37c669_disable_device( SERIAL_1 );
24901da177e4SLinus Torvalds         SMC37c669_configure_device(
24911da177e4SLinus Torvalds             SERIAL_1,
24921da177e4SLinus Torvalds             COM2_BASE,
24931da177e4SLinus Torvalds             COM2_IRQ,
24941da177e4SLinus Torvalds             -1
24951da177e4SLinus Torvalds         );
24961da177e4SLinus Torvalds         SMC37c669_enable_device( SERIAL_1 );
24971da177e4SLinus Torvalds 
24981da177e4SLinus Torvalds         SMC37c669_disable_device( PARALLEL_0 );
24991da177e4SLinus Torvalds         SMC37c669_configure_device(
25001da177e4SLinus Torvalds             PARALLEL_0,
25011da177e4SLinus Torvalds             PARP_BASE,
25021da177e4SLinus Torvalds             PARP_IRQ,
25031da177e4SLinus Torvalds             PARP_DRQ
25041da177e4SLinus Torvalds         );
25051da177e4SLinus Torvalds         SMC37c669_enable_device( PARALLEL_0 );
25061da177e4SLinus Torvalds 
25071da177e4SLinus Torvalds         SMC37c669_disable_device( FLOPPY_0 );
25081da177e4SLinus Torvalds         SMC37c669_configure_device(
25091da177e4SLinus Torvalds             FLOPPY_0,
25101da177e4SLinus Torvalds             FDC_BASE,
25111da177e4SLinus Torvalds             FDC_IRQ,
25121da177e4SLinus Torvalds             FDC_DRQ
25131da177e4SLinus Torvalds         );
25141da177e4SLinus Torvalds         SMC37c669_enable_device( FLOPPY_0 );
25151da177e4SLinus Torvalds 
25161da177e4SLinus Torvalds 	/* Wake up sometimes forgotten floppy, especially on DP264. */
25171da177e4SLinus Torvalds 	outb(0xc, 0x3f2);
25181da177e4SLinus Torvalds 
25191da177e4SLinus Torvalds         SMC37c669_disable_device( IDE_0 );
25201da177e4SLinus Torvalds 
25211da177e4SLinus Torvalds #if SMC_DEBUG
25221da177e4SLinus Torvalds 	SMC37c669_config_mode( TRUE );
25231da177e4SLinus Torvalds 	SMC37c669_dump_registers( );
25241da177e4SLinus Torvalds 	SMC37c669_config_mode( FALSE );
25251da177e4SLinus Torvalds         SMC37c669_display_device_info( );
25261da177e4SLinus Torvalds #endif
25271da177e4SLinus Torvalds 	local_irq_restore(flags);
25285f0e3da6SRandy Dunlap         printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",
25295f0e3da6SRandy Dunlap 		SMC_base );
25301da177e4SLinus Torvalds     }
25311da177e4SLinus Torvalds     else {
25321da177e4SLinus Torvalds 	local_irq_restore(flags);
25331da177e4SLinus Torvalds #if SMC_DEBUG
25341da177e4SLinus Torvalds         printk( "No SMC37c669 Super I/O Controller found\n" );
25351da177e4SLinus Torvalds #endif
25361da177e4SLinus Torvalds     }
25371da177e4SLinus Torvalds }
2538