cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

smc37c669.c (61276B)


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