!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/arch/alpha/kernel/   drwxr-xr-x
Free 318.37 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     smc37c669.c (61.71 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * SMC 37C669 initialization code
 */
#include <linux/kernel.h>

#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>

#include <asm/hwrpb.h>
#include <asm/io.h>
#include <asm/segment.h>

#if 0
# define DBG_DEVS(args)         printk args
#else
# define DBG_DEVS(args)
#endif

#define KB              1024
#define MB              (1024*KB)
#define GB              (1024*MB)

#define SMC_DEBUG   0

/* File:    smcc669_def.h
 *
 * Copyright (C) 1997 by
 * Digital Equipment Corporation, Maynard, Massachusetts.
 * All rights reserved.
 *
 * This software is furnished under a license and may be used and copied
 * only  in  accordance  of  the  terms  of  such  license  and with the
 * inclusion of the above copyright notice. This software or  any  other
 * copies thereof may not be provided or otherwise made available to any
 * other person.  No title to and  ownership of the  software is  hereby
 * transferred.
 *
 * The information in this software is  subject to change without notice
 * and  should  not  be  construed  as a commitment by Digital Equipment
 * Corporation.
 *
 * Digital assumes no responsibility for the use  or  reliability of its
 * software on equipment which is not supplied by Digital.
 *
 *
 * Abstract:    
 *
 *    This file contains header definitions for the SMC37c669 
 *    Super I/O controller. 
 *
 * Author:    
 *
 *    Eric Rasmussen
 *
 * Modification History:
 *
 *    er    28-Jan-1997    Initial Entry
 */

#ifndef __SMC37c669_H
#define __SMC37c669_H

/*
** Macros for handling device IRQs
**
** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15) 
** to device IRQs (A - H).
*/
#define SMC37c669_DEVICE_IRQ_MASK    0x80000000
#define SMC37c669_DEVICE_IRQ( __i )    \
    ((SMC37c669_DEVICE_IRQ_MASK) | (__i))
#define SMC37c669_IS_DEVICE_IRQ(__i)    \
    (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
#define SMC37c669_RAW_DEVICE_IRQ(__i)    \
    ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))

/*
** Macros for handling device DRQs
**
** The mask acts as a flag used in mapping actual ISA DMA
** channels to device DMA channels (A - C).
*/
#define SMC37c669_DEVICE_DRQ_MASK    0x80000000
#define SMC37c669_DEVICE_DRQ(__d)    \
    ((SMC37c669_DEVICE_DRQ_MASK) | (__d))
#define SMC37c669_IS_DEVICE_DRQ(__d)    \
    (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
#define SMC37c669_RAW_DEVICE_DRQ(__d)    \
    ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))

#define SMC37c669_DEVICE_ID    0x3

/*
** SMC37c669 Device Function Definitions
*/
#define SERIAL_0    0
#define SERIAL_1    1
#define PARALLEL_0    2
#define FLOPPY_0    3
#define IDE_0        4
#define NUM_FUNCS    5

/*
** Default Device Function Mappings
*/
#define COM1_BASE    0x3F8
#define COM1_IRQ    4
#define COM2_BASE    0x2F8
#define COM2_IRQ    3
#define PARP_BASE    0x3BC
#define PARP_IRQ    7
#define PARP_DRQ    3
#define FDC_BASE    0x3F0
#define FDC_IRQ        6
#define FDC_DRQ        2

/*
** Configuration On/Off Key Definitions
*/
#define SMC37c669_CONFIG_ON_KEY        0x55
#define SMC37c669_CONFIG_OFF_KEY    0xAA

/*
** SMC 37c669 Device IRQs
*/
#define SMC37c669_DEVICE_IRQ_A        ( SMC37c669_DEVICE_IRQ( 0x01 ) )
#define SMC37c669_DEVICE_IRQ_B        ( SMC37c669_DEVICE_IRQ( 0x02 ) )
#define SMC37c669_DEVICE_IRQ_C        ( SMC37c669_DEVICE_IRQ( 0x03 ) )
#define SMC37c669_DEVICE_IRQ_D        ( SMC37c669_DEVICE_IRQ( 0x04 ) )
#define SMC37c669_DEVICE_IRQ_E        ( SMC37c669_DEVICE_IRQ( 0x05 ) )
#define SMC37c669_DEVICE_IRQ_F        ( SMC37c669_DEVICE_IRQ( 0x06 ) )
/*      SMC37c669_DEVICE_IRQ_G        *** RESERVED ***/
#define SMC37c669_DEVICE_IRQ_H        ( SMC37c669_DEVICE_IRQ( 0x08 ) )

/*
** SMC 37c669 Device DMA Channel Definitions
*/
#define SMC37c669_DEVICE_DRQ_A            ( SMC37c669_DEVICE_DRQ( 0x01 ) )
#define SMC37c669_DEVICE_DRQ_B            ( SMC37c669_DEVICE_DRQ( 0x02 ) )
#define SMC37c669_DEVICE_DRQ_C            ( SMC37c669_DEVICE_DRQ( 0x03 ) )

/*
** Configuration Register Index Definitions
*/
#define SMC37c669_CR00_INDEX        0x00
#define SMC37c669_CR01_INDEX        0x01
#define SMC37c669_CR02_INDEX        0x02
#define SMC37c669_CR03_INDEX        0x03
#define SMC37c669_CR04_INDEX        0x04
#define SMC37c669_CR05_INDEX        0x05
#define SMC37c669_CR06_INDEX        0x06
#define SMC37c669_CR07_INDEX        0x07
#define SMC37c669_CR08_INDEX        0x08
#define SMC37c669_CR09_INDEX        0x09
#define SMC37c669_CR0A_INDEX        0x0A
#define SMC37c669_CR0B_INDEX        0x0B
#define SMC37c669_CR0C_INDEX        0x0C
#define SMC37c669_CR0D_INDEX        0x0D
#define SMC37c669_CR0E_INDEX        0x0E
#define SMC37c669_CR0F_INDEX        0x0F
#define SMC37c669_CR10_INDEX        0x10
#define SMC37c669_CR11_INDEX        0x11
#define SMC37c669_CR12_INDEX        0x12
#define SMC37c669_CR13_INDEX        0x13
#define SMC37c669_CR14_INDEX        0x14
#define SMC37c669_CR15_INDEX        0x15
#define SMC37c669_CR16_INDEX        0x16
#define SMC37c669_CR17_INDEX        0x17
#define SMC37c669_CR18_INDEX        0x18
#define SMC37c669_CR19_INDEX        0x19
#define SMC37c669_CR1A_INDEX        0x1A
#define SMC37c669_CR1B_INDEX        0x1B
#define SMC37c669_CR1C_INDEX        0x1C
#define SMC37c669_CR1D_INDEX        0x1D
#define SMC37c669_CR1E_INDEX        0x1E
#define SMC37c669_CR1F_INDEX        0x1F
#define SMC37c669_CR20_INDEX        0x20
#define SMC37c669_CR21_INDEX        0x21
#define SMC37c669_CR22_INDEX        0x22
#define SMC37c669_CR23_INDEX        0x23
#define SMC37c669_CR24_INDEX        0x24
#define SMC37c669_CR25_INDEX        0x25
#define SMC37c669_CR26_INDEX        0x26
#define SMC37c669_CR27_INDEX        0x27
#define SMC37c669_CR28_INDEX        0x28
#define SMC37c669_CR29_INDEX        0x29

/*
** Configuration Register Alias Definitions
*/
#define SMC37c669_DEVICE_ID_INDEX            SMC37c669_CR0D_INDEX
#define SMC37c669_DEVICE_REVISION_INDEX            SMC37c669_CR0E_INDEX
#define SMC37c669_FDC_BASE_ADDRESS_INDEX        SMC37c669_CR20_INDEX
#define SMC37c669_IDE_BASE_ADDRESS_INDEX        SMC37c669_CR21_INDEX
#define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX        SMC37c669_CR22_INDEX
#define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX        SMC37c669_CR23_INDEX
#define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX        SMC37c669_CR24_INDEX
#define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX        SMC37c669_CR25_INDEX
#define SMC37c669_PARALLEL_FDC_DRQ_INDEX        SMC37c669_CR26_INDEX
#define SMC37c669_PARALLEL_FDC_IRQ_INDEX        SMC37c669_CR27_INDEX
#define SMC37c669_SERIAL_IRQ_INDEX            SMC37c669_CR28_INDEX

/*
** Configuration Register Definitions
**
** The INDEX (write only) and DATA (read/write) ports are effective 
** only when the chip is in the Configuration State.
*/
typedef struct _SMC37c669_CONFIG_REGS {
    unsigned char index_port;
    unsigned char data_port;
} SMC37c669_CONFIG_REGS;

/*
** CR00 - default value 0x28
**
**  IDE_EN (CR00<1:0>):
**    0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
**    11 - IRQ_H available as IRQ output,
**         IRRX2, IRTX2 available as alternate IR pins
**    10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
**
**  VALID (CR00<7>):
**    A high level on this software controlled bit can
**    be used to indicate that a valid configuration
**    cycle has occurred.  The control software must
**    take care to set this bit at the appropriate times.
**    Set to zero after power up.  This bit has no
**    effect on any other hardware in the chip.
**
*/
typedef union _SMC37c669_CR00 {
    unsigned char as_uchar;
    struct {
        unsigned ide_en : 2;        /* See note above        */
    unsigned reserved1 : 1;        /* RAZ            */
    unsigned fdc_pwr : 1;        /* 1 = supply power to FDC  */
    unsigned reserved2 : 3;        /* Read as 010b        */
    unsigned valid : 1;        /* See note above        */
    }    by_field;
} SMC37c669_CR00;

/*
** CR01 - default value 0x9C
*/
typedef union _SMC37c669_CR01 {
    unsigned char as_uchar;
    struct {
        unsigned reserved1 : 2;        /* RAZ                */
    unsigned ppt_pwr : 1;        /* 1 = supply power to PPT        */
    unsigned ppt_mode : 1;        /* 1 = Printer mode, 0 = EPP    */
    unsigned reserved2 : 1;        /* Read as 1            */
    unsigned reserved3 : 2;        /* RAZ                */
    unsigned lock_crx: 1;        /* Lock CR00 - CR18            */
    }    by_field;
} SMC37c669_CR01;

/*
** CR02 - default value 0x88
*/
typedef union _SMC37c669_CR02 {
    unsigned char as_uchar;
    struct {
        unsigned reserved1 : 3;        /* RAZ                */
    unsigned uart1_pwr : 1;        /* 1 = supply power to UART1    */
    unsigned reserved2 : 3;        /* RAZ                */
    unsigned uart2_pwr : 1;        /* 1 = supply power to UART2    */
    }    by_field;
} SMC37c669_CR02;

/*
** CR03 - default value 0x78
**
**  CR03<7>    CR03<2>        Pin 94
**  -------    -------        ------
**     0       X        DRV2 (input)
**     1       0        ADRX
**     1       1        IRQ_B
**
**  CR03<6>    CR03<5>        Op Mode
**  -------    -------        -------
**     0       0        Model 30
**     0       1        PS/2
**     1       0        Reserved
**     1       1        AT Mode
*/
typedef union _SMC37c669_CR03 {
    unsigned char as_uchar;
    struct {
        unsigned pwrgd_gamecs : 1;  /* 1 = PWRGD, 0 = GAMECS        */
    unsigned fdc_mode2 : 1;        /* 1 = Enhanced Mode 2        */
    unsigned pin94_0 : 1;        /* See note above            */
    unsigned reserved1 : 1;        /* RAZ                */
    unsigned drvden : 1;        /* 1 = high, 0 - output        */
    unsigned op_mode : 2;        /* See note above            */
    unsigned pin94_1 : 1;        /* See note above            */
    }    by_field;
} SMC37c669_CR03;

/*
** CR04 - default value 0x00
**
**  PP_EXT_MODE:
**    If CR01<PP_MODE> = 0 and PP_EXT_MODE =
**        00 - Standard and Bidirectional
**        01 - EPP mode and SPP
**        10 - ECP mode
**         In this mode, 2 drives can be supported
**         directly, 3 or 4 drives must use external
**         4 drive support.  SPP can be selected
**         through the ECR register of ECP as mode 000.
**        11 - ECP mode and EPP mode
**         In this mode, 2 drives can be supported
**         directly, 3 or 4 drives must use external
**         4 drive support.  SPP can be selected
**         through the ECR register of ECP as mode 000.
**         In this mode, EPP can be selected through
**         the ECR register of ECP as mode 100.
**
**  PP_FDC:
**    00 - Normal
**    01 - PPFD1
**    10 - PPFD2
**    11 - Reserved
**
**  MIDI1:
**    Serial Clock Select: 
**        A low level on this bit disables MIDI support,
**        clock = divide by 13.  A high level on this 
**        bit enables MIDI support, clock = divide by 12.
**
**    MIDI operates at 31.25 Kbps which can be derived 
**    from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
**
**  ALT_IO:
**    0 - Use pins IRRX, IRTX
**    1 - Use pins IRRX2, IRTX2
**
**    If this bit is set, the IR receive and transmit
**    functions will not be available on pins 25 and 26
**    unless CR00<IDE_EN> = 11.
*/
typedef union _SMC37c669_CR04 {
    unsigned char as_uchar;
    struct {
        unsigned ppt_ext_mode : 2;  /* See note above            */
    unsigned ppt_fdc : 2;        /* See note above            */
    unsigned midi1 : 1;        /* See note above            */
    unsigned midi2 : 1;        /* See note above            */
    unsigned epp_type : 1;        /* 0 = EPP 1.9, 1 = EPP 1.7        */
    unsigned alt_io : 1;        /* See note above            */
    }    by_field;
} SMC37c669_CR04;

/*
** CR05 - default value 0x00
**
**  DEN_SEL:
**    00 - Densel output normal
**    01 - Reserved
**    10 - Densel output 1
**    11 - Densel output 0
**
*/
typedef union _SMC37c669_CR05 {
    unsigned char as_uchar;
    struct {
        unsigned reserved1 : 2;        /* RAZ                    */
    unsigned fdc_dma_mode : 1;  /* 0 = burst, 1 = non-burst            */
    unsigned den_sel : 2;        /* See note above                */
    unsigned swap_drv : 1;        /* Swap the FDC motor selects        */
    unsigned extx4 : 1;        /* 0 = 2 drive, 1 = external 4 drive decode    */
    unsigned reserved2 : 1;        /* RAZ                    */
    }    by_field;
} SMC37c669_CR05;

/*
** CR06 - default value 0xFF
*/
typedef union _SMC37c669_CR06 {
    unsigned char as_uchar;
    struct {
        unsigned floppy_a : 2;        /* Type of floppy drive A        */
    unsigned floppy_b : 2;        /* Type of floppy drive B        */
    unsigned floppy_c : 2;        /* Type of floppy drive C        */
    unsigned floppy_d : 2;        /* Type of floppy drive D        */
    }    by_field;
} SMC37c669_CR06;

/*
** CR07 - default value 0x00
**
**  Auto Power Management CR07<7:4>:
**    0 - Auto Powerdown disabled (default)
**    1 - Auto Powerdown enabled
**
**    This bit is reset to the default state by POR or
**    a hardware reset.
**
*/
typedef union _SMC37c669_CR07 {
    unsigned char as_uchar;
    struct {
        unsigned floppy_boot : 2;   /* 0 = A:, 1 = B:            */
    unsigned reserved1 : 2;        /* RAZ                */
    unsigned ppt_en : 1;        /* See note above            */
    unsigned uart1_en : 1;        /* See note above            */
    unsigned uart2_en : 1;        /* See note above            */
    unsigned fdc_en : 1;        /* See note above            */
    }    by_field;
} SMC37c669_CR07;

/*
** CR08 - default value 0x00
*/
typedef union _SMC37c669_CR08 {
    unsigned char as_uchar;
    struct {
        unsigned zero : 4;        /* 0                */
    unsigned addrx7_4 : 4;        /* ADR<7:3> for ADRx decode        */
    }    by_field;
} SMC37c669_CR08;

/*
** CR09 - default value 0x00
**
**  ADRx_CONFIG:
**    00 - ADRx disabled
**    01 - 1 byte decode A<3:0> = 0000b
**    10 - 8 byte block decode A<3:0> = 0XXXb
**    11 - 16 byte block decode A<3:0> = XXXXb
**
*/
typedef union _SMC37c669_CR09 {
    unsigned char as_uchar;
    struct {
        unsigned adra8 : 3;        /* ADR<10:8> for ADRx decode    */
    unsigned reserved1 : 3;
    unsigned adrx_config : 2;   /* See note above            */
    }    by_field;
} SMC37c669_CR09;

/*
** CR0A - default value 0x00
*/
typedef union _SMC37c669_CR0A {
    unsigned char as_uchar;
    struct {
        unsigned ecp_fifo_threshold : 4;
    unsigned reserved1 : 4;
    }    by_field;
} SMC37c669_CR0A;

/*
** CR0B - default value 0x00
*/
typedef union _SMC37c669_CR0B {
    unsigned char as_uchar;
    struct {
        unsigned fdd0_drtx : 2;        /* FDD0 Data Rate Table        */
    unsigned fdd1_drtx : 2;        /* FDD1 Data Rate Table        */
    unsigned fdd2_drtx : 2;        /* FDD2 Data Rate Table        */
    unsigned fdd3_drtx : 2;        /* FDD3 Data Rate Table        */
    }    by_field;
} SMC37c669_CR0B;

/*
** CR0C - default value 0x00
**
**  UART2_MODE:
**    000 - Standard (default)
**    001 - IrDA (HPSIR)
**    010 - Amplitude Shift Keyed IR @500 KHz
**    011 - Reserved
**    1xx - Reserved
**
*/
typedef union _SMC37c669_CR0C {
    unsigned char as_uchar;
    struct {
        unsigned uart2_rcv_polarity : 1;    /* 1 = invert RX        */
    unsigned uart2_xmit_polarity : 1;   /* 1 = invert TX        */
    unsigned uart2_duplex : 1;        /* 1 = full, 0 = half    */
    unsigned uart2_mode : 3;        /* See note above        */
    unsigned uart1_speed : 1;        /* 1 = high speed enabled    */
    unsigned uart2_speed : 1;        /* 1 = high speed enabled    */
    }    by_field;
} SMC37c669_CR0C;

/*
** CR0D - default value 0x03
**
**  Device ID Register - read only
*/
typedef union _SMC37c669_CR0D {
    unsigned char as_uchar;
    struct {
        unsigned device_id : 8;        /* Returns 0x3 in this field    */
    }    by_field;
} SMC37c669_CR0D;

/*
** CR0E - default value 0x02
**
**  Device Revision Register - read only
*/
typedef union _SMC37c669_CR0E {
    unsigned char as_uchar;
    struct {
        unsigned device_rev : 8;    /* Returns 0x2 in this field    */
    }    by_field;
} SMC37c669_CR0E;

/*
** CR0F - default value 0x00
*/
typedef union _SMC37c669_CR0F {
    unsigned char as_uchar;
    struct {
        unsigned test0 : 1;        /* Reserved - set to 0        */
    unsigned test1 : 1;        /* Reserved - set to 0        */
    unsigned test2 : 1;        /* Reserved - set to 0        */
    unsigned test3 : 1;        /* Reserved - set t0 0        */
    unsigned test4 : 1;        /* Reserved - set to 0        */
    unsigned test5 : 1;        /* Reserved - set t0 0        */
    unsigned test6 : 1;        /* Reserved - set t0 0        */
    unsigned test7 : 1;        /* Reserved - set to 0        */
    }    by_field;
} SMC37c669_CR0F;

/*
** CR10 - default value 0x00
*/
typedef union _SMC37c669_CR10 {
    unsigned char as_uchar;
    struct {
        unsigned reserved1 : 3;         /* RAZ                */
    unsigned pll_gain : 1;         /* 1 = 3V, 2 = 5V operation    */
    unsigned pll_stop : 1;         /* 1 = stop PLLs            */
    unsigned ace_stop : 1;         /* 1 = stop UART clocks        */
    unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz  */
    unsigned ir_test : 1;         /* Enable IR test mode        */
    }    by_field;
} SMC37c669_CR10;

/*
** CR11 - default value 0x00
*/
typedef union _SMC37c669_CR11 {
    unsigned char as_uchar;
    struct {
        unsigned ir_loopback : 1;   /* Internal IR loop back            */
    unsigned test_10ms : 1;        /* Test 10ms autopowerdown FDC timeout  */
    unsigned reserved1 : 6;        /* RAZ                    */
    }    by_field;
} SMC37c669_CR11;

/*
** CR12 - CR1D are reserved registers
*/

/*
** CR1E - default value 0x80
**
**  GAMECS:
**    00 - GAMECS disabled
**    01 - 1 byte decode ADR<3:0> = 0001b
**    10 - 8 byte block decode ADR<3:0> = 0XXXb
**    11 - 16 byte block decode ADR<3:0> = XXXXb
**
*/
typedef union _SMC37c66_CR1E {
    unsigned char as_uchar;
    struct {
        unsigned gamecs_config: 2;   /* See note above            */
    unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4>        */
    }    by_field;
} SMC37c669_CR1E;

/*
** CR1F - default value 0x00
**
**  DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
**  --- --- ------- ------- ----------
**   0   0  DENSEL  DRATE0  4/2/1 MB 3.5"
**                          2/1 MB 5.25"
**                          2/1.6/1 MB 3.5" (3-mode)
**   0   1  DRATE1  DRATE0
**   1   0  nDENSEL DRATE0  PS/2
**   1   1  DRATE0  DRATE1
**
**  Note: DENSEL, DRATE1, and DRATE0 map onto two output
**      pins - DRVDEN0 and DRVDEN1.
**
*/
typedef union _SMC37c669_CR1F {
    unsigned char as_uchar;
    struct {
        unsigned fdd0_drive_type : 2;    /* FDD0 drive type        */
    unsigned fdd1_drive_type : 2;    /* FDD1 drive type        */
    unsigned fdd2_drive_type : 2;    /* FDD2 drive type        */
    unsigned fdd3_drive_type : 2;    /* FDD3 drive type        */
    }    by_field;
} SMC37c669_CR1F;

/*
** CR20 - default value 0x3C
**
**  FDC Base Address Register
**    - To disable this decode set Addr<9:8> = 0
**    - A<10> = 0, A<3:0> = 0XXXb to access.
**
*/
typedef union _SMC37c669_CR20 {
    unsigned char as_uchar;
    struct {
        unsigned zero : 2;        /* 0                */
    unsigned addr9_4 : 6;        /* FDC Addr<9:4>            */
    }    by_field;
} SMC37c669_CR20;

/*
** CR21 - default value 0x3C
**
**  IDE Base Address Register
**    - To disable this decode set Addr<9:8> = 0
**    - A<10> = 0, A<3:0> = 0XXXb to access.
**
*/
typedef union _SMC37c669_CR21 {
    unsigned char as_uchar;
    struct {
        unsigned zero : 2;        /* 0                */
    unsigned addr9_4 : 6;        /* IDE Addr<9:4>            */
    }    by_field;
} SMC37c669_CR21;

/*
** CR22 - default value 0x3D
**
**  IDE Alternate Status Base Address Register
**    - To disable this decode set Addr<9:8> = 0
**    - A<10> = 0, A<3:0> = 0110b to access.
**
*/
typedef union _SMC37c669_CR22 {
    unsigned char as_uchar;
    struct {
        unsigned zero : 2;        /* 0                */
    unsigned addr9_4 : 6;        /* IDE Alt Status Addr<9:4>        */
    }    by_field;
} SMC37c669_CR22;

/*
** CR23 - default value 0x00
**
**  Parallel Port Base Address Register
**    - To disable this decode set Addr<9:8> = 0
**    - A<10> = 0 to access.
**    - If EPP is enabled, A<2:0> = XXXb to access.
**      If EPP is NOT enabled, A<1:0> = XXb to access
**
*/
typedef union _SMC37c669_CR23 {
    unsigned char as_uchar;
    struct {
    unsigned addr9_2 : 8;        /* Parallel Port Addr<9:2>        */
    }    by_field;
} SMC37c669_CR23;

/*
** CR24 - default value 0x00
**
**  UART1 Base Address Register
**    - To disable this decode set Addr<9:8> = 0
**    - A<10> = 0, A<2:0> = XXXb to access.
**
*/
typedef union _SMC37c669_CR24 {
    unsigned char as_uchar;
    struct {
        unsigned zero : 1;        /* 0                */
    unsigned addr9_3 : 7;        /* UART1 Addr<9:3>            */
    }    by_field;
} SMC37c669_CR24;

/*
** CR25 - default value 0x00
**
**  UART2 Base Address Register
**    - To disable this decode set Addr<9:8> = 0
**    - A<10> = 0, A<2:0> = XXXb to access.
**
*/
typedef union _SMC37c669_CR25 {
    unsigned char as_uchar;
    struct {
        unsigned zero : 1;        /* 0                */
    unsigned addr9_3 : 7;        /* UART2 Addr<9:3>            */
    }    by_field;
} SMC37c669_CR25;

/*
** CR26 - default value 0x00
**
**  Parallel Port / FDC DMA Select Register
**
**  D3 - D0      DMA
**  D7 - D4    Selected
**  -------    --------
**   0000     None
**   0001     DMA_A
**   0010     DMA_B
**   0011     DMA_C
**
*/
typedef union _SMC37c669_CR26 {
    unsigned char as_uchar;
    struct {
        unsigned ppt_drq : 4;        /* See note above            */
    unsigned fdc_drq : 4;        /* See note above            */
    }    by_field;
} SMC37c669_CR26;

/*
** CR27 - default value 0x00
**
**  Parallel Port / FDC IRQ Select Register
**
**  D3 - D0      IRQ
**  D7 - D4    Selected
**  -------    --------
**   0000     None
**   0001     IRQ_A
**   0010     IRQ_B
**   0011     IRQ_C
**   0100     IRQ_D
**   0101     IRQ_E
**   0110     IRQ_F
**   0111     Reserved
**   1000     IRQ_H
**
**  Any unselected IRQ REQ is in tristate
**
*/
typedef union _SMC37c669_CR27 {
    unsigned char as_uchar;
    struct {
        unsigned ppt_irq : 4;        /* See note above            */
    unsigned fdc_irq : 4;        /* See note above            */
    }    by_field;
} SMC37c669_CR27;

/*
** CR28 - default value 0x00
**
**  UART IRQ Select Register
**
**  D3 - D0      IRQ
**  D7 - D4    Selected
**  -------    --------
**   0000     None
**   0001     IRQ_A
**   0010     IRQ_B
**   0011     IRQ_C
**   0100     IRQ_D
**   0101     IRQ_E
**   0110     IRQ_F
**   0111     Reserved
**   1000     IRQ_H
**   1111     share with UART1 (only for UART2)
**
**  Any unselected IRQ REQ is in tristate
**
**  To share an IRQ between UART1 and UART2, set
**  UART1 to use the desired IRQ and set UART2 to
**  0xF to enable sharing mechanism.
**
*/
typedef union _SMC37c669_CR28 {
    unsigned char as_uchar;
    struct {
        unsigned uart2_irq : 4;        /* See note above            */
    unsigned uart1_irq : 4;        /* See note above            */
    }    by_field;
} SMC37c669_CR28;

/*
** CR29 - default value 0x00
**
**  IRQIN IRQ Select Register
**
**  D3 - D0      IRQ
**  D7 - D4    Selected
**  -------    --------
**   0000     None
**   0001     IRQ_A
**   0010     IRQ_B
**   0011     IRQ_C
**   0100     IRQ_D
**   0101     IRQ_E
**   0110     IRQ_F
**   0111     Reserved
**   1000     IRQ_H
**
**  Any unselected IRQ REQ is in tristate
**
*/
typedef union _SMC37c669_CR29 {
    unsigned char as_uchar;
    struct {
        unsigned irqin_irq : 4;        /* See note above            */
    unsigned reserved1 : 4;        /* RAZ                */
    }    by_field;
} SMC37c669_CR29;

/*
** Aliases of Configuration Register formats (should match
** the set of index aliases).
**
** Note that CR24 and CR25 have the same format and are the
** base address registers for UART1 and UART2.  Because of
** this we only define 1 alias here - for CR24 - as the serial
** base address register.
**
** Note that CR21 and CR22 have the same format and are the
** base address and alternate status address registers for
** the IDE controller.  Because of this we only define 1 alias
** here - for CR21 - as the IDE address register.
**
*/
typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;

/*
** ISA/Device IRQ Translation Table Entry Definition
*/
typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {
    int device_irq;
    int isa_irq;
} SMC37c669_IRQ_TRANSLATION_ENTRY;

/*
** ISA/Device DMA Translation Table Entry Definition
*/
typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {
    int device_drq;
    int isa_drq;
} SMC37c669_DRQ_TRANSLATION_ENTRY;

/*
** External Interface Function Prototype Declarations
*/

SMC37c669_CONFIG_REGS *SMC37c669_detect( 
    int
);

unsigned int SMC37c669_enable_device( 
    unsigned int func 
);

unsigned int SMC37c669_disable_device( 
    unsigned int func 
);

unsigned int SMC37c669_configure_device( 
    unsigned int func, 
    int port, 
    int irq, 
    int drq 
);

void SMC37c669_display_device_info( 
    void 
);

#endif    /* __SMC37c669_H */

/* file:    smcc669.c
 *
 * Copyright (C) 1997 by
 * Digital Equipment Corporation, Maynard, Massachusetts.
 * All rights reserved.
 *
 * This software is furnished under a license and may be used and copied
 * only  in  accordance  of  the  terms  of  such  license  and with the
 * inclusion of the above copyright notice. This software or  any  other
 * copies thereof may not be provided or otherwise made available to any
 * other person.  No title to and  ownership of the  software is  hereby
 * transferred.
 *
 * The information in this software is  subject to change without notice
 * and  should  not  be  construed  as a commitment by digital equipment
 * corporation.
 *
 * Digital assumes no responsibility for the use  or  reliability of its
 * software on equipment which is not supplied by digital.
 */

/*
 *++
 *  FACILITY:
 *
 *      Alpha SRM Console Firmware
 *
 *  MODULE DESCRIPTION:
 *
 *    SMC37c669 Super I/O controller configuration routines.
 *
 *  AUTHORS:
 *
 *    Eric Rasmussen
 *
 *  CREATION DATE:
 *  
 *    28-Jan-1997
 *
 *  MODIFICATION HISTORY:
 *    
 *    er    01-May-1997    Fixed pointer conversion errors in 
 *                SMC37c669_get_device_config().
 *      er    28-Jan-1997    Initial version.
 *
 *--
 */
#if 0
/* $INCLUDE_OPTIONS$ */
#include    "cp$inc:platform_io.h"
/* $INCLUDE_OPTIONS_END$ */
#include    "cp$src:common.h"
#include    "cp$inc:prototypes.h"
#include    "cp$src:kernel_def.h"
#include    "cp$src:msg_def.h"
#include    "cp$src:smcc669_def.h"
/* Platform-specific includes */
#include    "cp$src:platform.h"
#endif

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#define wb( _x_, _y_ )    outb( _y_, (unsigned int)((unsigned long)_x_) )
#define rb( _x_ )    inb( (unsigned int)((unsigned long)_x_) )

/*
** Local storage for device configuration information.
**
** Since the SMC37c669 does not provide an explicit
** mechanism for enabling/disabling individual device 
** functions, other than unmapping the device, local 
** storage for device configuration information is 
** allocated here for use in implementing our own 
** function enable/disable scheme.
*/
static struct DEVICE_CONFIG {
    unsigned int port1;
    unsigned int port2;
    unsigned int irq;
    unsigned int drq;
} local_config [NUM_FUNCS];

/*
** List of all possible addresses for the Super I/O chip
*/
static unsigned long SMC37c669_Addresses[] __initdata =
    {
    0x3F0UL,        /* Primary address        */
    0x370UL,        /* Secondary address    */
    0UL            /* End of list        */
    };

/*
** Global Pointer to the Super I/O device
*/
static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;

/*
** IRQ Translation Table
**
** The IRQ translation table is a list of SMC37c669 device 
** and standard ISA IRQs.
**
*/
static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata = 0; 

/*
** The following definition is for the default IRQ 
** translation table.
*/
static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]
__initdata = 
    { 
    { SMC37c669_DEVICE_IRQ_A, -1 }, 
    { SMC37c669_DEVICE_IRQ_B, -1 }, 
    { SMC37c669_DEVICE_IRQ_C, 7 }, 
    { SMC37c669_DEVICE_IRQ_D, 6 }, 
    { SMC37c669_DEVICE_IRQ_E, 4 }, 
    { SMC37c669_DEVICE_IRQ_F, 3 }, 
    { SMC37c669_DEVICE_IRQ_H, -1 }, 
    { -1, -1 } /* End of table */
    };

/*
** The following definition is for the MONET (XP1000) IRQ 
** translation table.
*/
static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]
__initdata = 
    { 
    { SMC37c669_DEVICE_IRQ_A, -1 }, 
    { SMC37c669_DEVICE_IRQ_B, -1 }, 
    { SMC37c669_DEVICE_IRQ_C, 6 }, 
    { SMC37c669_DEVICE_IRQ_D, 7 }, 
    { SMC37c669_DEVICE_IRQ_E, 4 }, 
    { SMC37c669_DEVICE_IRQ_F, 3 }, 
    { SMC37c669_DEVICE_IRQ_H, -1 }, 
    { -1, -1 } /* End of table */
    };

static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =
    {
    SMC37c669_default_irq_table,
    SMC37c669_monet_irq_table
    }; 

/*
** DRQ Translation Table
**
** The DRQ translation table is a list of SMC37c669 device and
** ISA DMA channels.
**
*/
static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata = 0;

/*
** The following definition is the default DRQ
** translation table.
*/
static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]
__initdata = 
    { 
    { SMC37c669_DEVICE_DRQ_A, 2 }, 
    { SMC37c669_DEVICE_DRQ_B, 3 }, 
    { SMC37c669_DEVICE_DRQ_C, -1 }, 
    { -1, -1 } /* End of table */
    };

/*
** Local Function Prototype Declarations
*/

static unsigned int SMC37c669_is_device_enabled( 
    unsigned int func 
);

#if 0
static unsigned int SMC37c669_get_device_config( 
    unsigned int func, 
    int *port, 
    int *irq, 
    int *drq 
);
#endif

static void SMC37c669_config_mode( 
    unsigned int enable 
);

static unsigned char SMC37c669_read_config( 
    unsigned char index 
);

static void SMC37c669_write_config( 
    unsigned char index, 
    unsigned char data 
);

static void SMC37c669_init_local_config( void );

static struct DEVICE_CONFIG *SMC37c669_get_config(
    unsigned int func
);

static int SMC37c669_xlate_irq(
    unsigned int irq 
);

static int SMC37c669_xlate_drq(
    unsigned int drq 
);

#if 0
/*
** External Data Declarations
*/

extern struct LOCK spl_atomic;

/*
** External Function Prototype Declarations
*/

/* From kernel_alpha.mar */
extern spinlock( 
    struct LOCK *spl 
);

extern spinunlock( 
    struct LOCK *spl 
);

/* From filesys.c */
int allocinode(
    char *name, 
    int can_create, 
    struct INODE **ipp
);

extern int null_procedure( void );

int smcc669_init( void );
int smcc669_open( struct FILE *fp, char *info, char *next, char *mode );
int smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf );
int smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf );
int smcc669_close( struct FILE *fp );

struct DDB smc_ddb = {
    "smc",            /* how this routine wants to be called    */
    smcc669_read,        /* read routine                */
    smcc669_write,        /* write routine            */
    smcc669_open,        /* open routine                */
    smcc669_close,        /* close routine            */
    null_procedure,        /* name expansion routine        */
    null_procedure,        /* delete routine            */
    null_procedure,        /* create routine            */
    null_procedure,        /* setmode                */
    null_procedure,        /* validation routine            */
    0,            /* class specific use            */
    1,            /* allows information            */
    0,            /* must be stacked            */
    0,            /* is a flash update driver        */
    0,            /* is a block device            */
    0,            /* not seekable                */
    0,            /* is an Ethernet device        */
    0,            /* is a filesystem driver        */
};
#endif

#define spinlock(x)
#define spinunlock(x)


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function detects the presence of an SMC37c669 Super I/O
**    controller.
**
**  FORMAL PARAMETERS:
**
**    None
**
**  RETURN VALUE:
**
**      Returns a pointer to the device if found, otherwise,
**    the NULL pointer is returned.
**
**  SIDE EFFECTS:
**
**      None
**
**--
*/
SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
{
    int i;
    SMC37c669_DEVICE_ID_REGISTER id;

    for ( i = 0;  SMC37c669_Addresses[i] != 0;  i++ ) {
/*
** Initialize the device pointer even though we don't yet know if
** the controller is at this address.  The support functions access
** the controller through this device pointer so we need to set it
** even when we are looking ...
*/
        SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
/*
** Enter configuration mode
*/
    SMC37c669_config_mode( TRUE );
/*
** Read the device id
*/
    id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
/*
** Exit configuration mode
*/
    SMC37c669_config_mode( FALSE );
/*
** Does the device id match?  If so, assume we have found an
** SMC37c669 controller at this address.
*/
    if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
/*
** Initialize the IRQ and DRQ translation tables.
*/
            SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
        SMC37c669_drq_table = SMC37c669_default_drq_table;
/*
** erfix
**
** If the platform can't use the IRQ and DRQ defaults set up in this 
** file, it should call a platform-specific external routine at this 
** point to reset the IRQ and DRQ translation table pointers to point 
** at the appropriate tables for the platform.  If the defaults are 
** acceptable, then the external routine should do nothing.
*/

/*
** Put the chip back into configuration mode
*/
        SMC37c669_config_mode( TRUE );
/*
** Initialize local storage for configuration information
*/
        SMC37c669_init_local_config( );
/*
** Exit configuration mode
*/
        SMC37c669_config_mode( FALSE );
/*
** SMC37c669 controller found, break out of search loop
*/
        break;
    }
    else {
/*
** Otherwise, we did not find an SMC37c669 controller at this
** address so set the device pointer to NULL.
*/
        SMC37c669 = NULL;
    }
    }
    return SMC37c669;
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function enables an SMC37c669 device function.
**
**  FORMAL PARAMETERS:
**
**      func:
**          Which device function to enable
**
**  RETURN VALUE:
**
**      Returns TRUE is the device function was enabled, otherwise, FALSE
**
**  SIDE EFFECTS:
**
**      {@description or none@}
**
**  DESIGN:
**
**      Enabling a device function in the SMC37c669 controller involves
**    setting all of its mappings (port, irq, drq ...).  A local 
**    "shadow" copy of the device configuration is kept so we can
**    just set each mapping to what the local copy says.
**
**    This function ALWAYS updates the local shadow configuration of
**    the device function being enabled, even if the device is always
**    enabled.  To avoid replication of code, functions such as
**    configure_device set up the local copy and then call this 
**    function to the update the real device.
**
**--
*/
unsigned int __init SMC37c669_enable_device ( unsigned int func )
{
    unsigned int ret_val = FALSE;
/*
** Put the device into configuration mode
*/
    SMC37c669_config_mode( TRUE );
    switch ( func ) {
        case SERIAL_0:
        {
            SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_SERIAL_IRQ_REGISTER irq;
/*
** Enable the serial 1 IRQ mapping
*/
            irq.as_uchar = 
            SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );

        irq.by_field.uart1_irq =
            SMC37c669_RAW_DEVICE_IRQ(
            SMC37c669_xlate_irq( local_config[ func ].irq )
            );

        SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
/*
** Enable the serial 1 port base address mapping
*/
        base_addr.as_uchar = 0;
        base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;

        SMC37c669_write_config( 
            SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case SERIAL_1:
        {
            SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_SERIAL_IRQ_REGISTER irq;
/*
** Enable the serial 2 IRQ mapping
*/
            irq.as_uchar = 
            SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );

        irq.by_field.uart2_irq =
            SMC37c669_RAW_DEVICE_IRQ(
            SMC37c669_xlate_irq( local_config[ func ].irq )
            );

        SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
/*
** Enable the serial 2 port base address mapping
*/
        base_addr.as_uchar = 0;
        base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;

        SMC37c669_write_config( 
            SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case PARALLEL_0:
        {
            SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
        SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
/*
** Enable the parallel port DMA channel mapping
*/
            drq.as_uchar =
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );

        drq.by_field.ppt_drq = 
            SMC37c669_RAW_DEVICE_DRQ(
            SMC37c669_xlate_drq( local_config[ func ].drq )
            );

        SMC37c669_write_config(
            SMC37c669_PARALLEL_FDC_DRQ_INDEX,
            drq.as_uchar
        );
/*
** Enable the parallel port IRQ mapping
*/
        irq.as_uchar = 
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );

        irq.by_field.ppt_irq =
            SMC37c669_RAW_DEVICE_IRQ(
            SMC37c669_xlate_irq( local_config[ func ].irq )
            );

        SMC37c669_write_config( 
            SMC37c669_PARALLEL_FDC_IRQ_INDEX,
            irq.as_uchar
        );
/*
** Enable the parallel port base address mapping
*/
        base_addr.as_uchar = 0;
        base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;

        SMC37c669_write_config(
            SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case FLOPPY_0:
        {
            SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
        SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
/*
** Enable the floppy controller DMA channel mapping
*/
            drq.as_uchar =
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
         
        drq.by_field.fdc_drq =
            SMC37c669_RAW_DEVICE_DRQ(
            SMC37c669_xlate_drq( local_config[ func ].drq )
            );
         
        SMC37c669_write_config( 
            SMC37c669_PARALLEL_FDC_DRQ_INDEX,
            drq.as_uchar
        );
/*
** Enable the floppy controller IRQ mapping
*/
        irq.as_uchar =
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
         
        irq.by_field.fdc_irq =
            SMC37c669_RAW_DEVICE_IRQ(
            SMC37c669_xlate_irq( local_config[ func ].irq )
            );
         
        SMC37c669_write_config(
            SMC37c669_PARALLEL_FDC_IRQ_INDEX,
            irq.as_uchar
        );
/*
** Enable the floppy controller base address mapping
*/
        base_addr.as_uchar = 0;
        base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
         
        SMC37c669_write_config(
            SMC37c669_FDC_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case IDE_0:
        {
            SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
/*
** Enable the IDE alternate status base address mapping
*/
            ide_addr.as_uchar = 0;
        ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
         
        SMC37c669_write_config(
            SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
            ide_addr.as_uchar
        );
/*
** Enable the IDE controller base address mapping
*/
        ide_addr.as_uchar = 0;
        ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
         
        SMC37c669_write_config(
            SMC37c669_IDE_BASE_ADDRESS_INDEX,
            ide_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    }
/*
** Exit configuration mode and return
*/
    SMC37c669_config_mode( FALSE );

    return ret_val;
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function disables a device function within the
**    SMC37c669 Super I/O controller.
**
**  FORMAL PARAMETERS:
**
**      func:
**          Which function to disable
**
**  RETURN VALUE:
**
**      Return TRUE if the device function was disabled, otherwise, FALSE
**
**  SIDE EFFECTS:
**
**      {@description or none@}
**
**  DESIGN:
**
**      Disabling a function in the SMC37c669 device involves
**    disabling all the function's mappings (port, irq, drq ...).
**    A shadow copy of the device configuration is maintained
**    in local storage so we won't worry aboving saving the
**    current configuration information.
**
**--
*/
unsigned int __init SMC37c669_disable_device ( unsigned int func )
{
    unsigned int ret_val = FALSE;

/*
** Put the device into configuration mode
*/
    SMC37c669_config_mode( TRUE );
    switch ( func ) {
        case SERIAL_0:
        {
            SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_SERIAL_IRQ_REGISTER irq;
/*
** Disable the serial 1 IRQ mapping
*/
            irq.as_uchar = 
            SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );

        irq.by_field.uart1_irq = 0;

        SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
/*
** Disable the serial 1 port base address mapping
*/
        base_addr.as_uchar = 0;
        SMC37c669_write_config( 
            SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case SERIAL_1:
        {
            SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_SERIAL_IRQ_REGISTER irq;
/*
** Disable the serial 2 IRQ mapping
*/
            irq.as_uchar = 
            SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );

        irq.by_field.uart2_irq = 0;

        SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
/*
** Disable the serial 2 port base address mapping
*/
        base_addr.as_uchar = 0;

        SMC37c669_write_config( 
            SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case PARALLEL_0:
        {
            SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
        SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
/*
** Disable the parallel port DMA channel mapping
*/
            drq.as_uchar =
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );

        drq.by_field.ppt_drq = 0;

        SMC37c669_write_config(
            SMC37c669_PARALLEL_FDC_DRQ_INDEX,
            drq.as_uchar
        );
/*
** Disable the parallel port IRQ mapping
*/
        irq.as_uchar = 
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );

        irq.by_field.ppt_irq = 0;

        SMC37c669_write_config( 
            SMC37c669_PARALLEL_FDC_IRQ_INDEX,
            irq.as_uchar
        );
/*
** Disable the parallel port base address mapping
*/
        base_addr.as_uchar = 0;

        SMC37c669_write_config(
            SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case FLOPPY_0:
        {
            SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
        SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
        SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
/*
** Disable the floppy controller DMA channel mapping
*/
            drq.as_uchar =
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
         
        drq.by_field.fdc_drq = 0;
         
        SMC37c669_write_config( 
            SMC37c669_PARALLEL_FDC_DRQ_INDEX,
            drq.as_uchar
        );
/*
** Disable the floppy controller IRQ mapping
*/
        irq.as_uchar =
            SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
         
        irq.by_field.fdc_irq = 0;
         
        SMC37c669_write_config(
            SMC37c669_PARALLEL_FDC_IRQ_INDEX,
            irq.as_uchar
        );
/*
** Disable the floppy controller base address mapping
*/
        base_addr.as_uchar = 0;
         
        SMC37c669_write_config(
            SMC37c669_FDC_BASE_ADDRESS_INDEX,
            base_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    case IDE_0:
        {
            SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
/*
** Disable the IDE alternate status base address mapping
*/
            ide_addr.as_uchar = 0;
         
        SMC37c669_write_config(
            SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
            ide_addr.as_uchar
        );
/*
** Disable the IDE controller base address mapping
*/
        ide_addr.as_uchar = 0;
         
        SMC37c669_write_config(
            SMC37c669_IDE_BASE_ADDRESS_INDEX,
            ide_addr.as_uchar
        );
        ret_val = TRUE;
        break;
        }
    }
/*
** Exit configuration mode and return
*/
    SMC37c669_config_mode( FALSE );

    return ret_val;
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function configures a device function within the 
**    SMC37c669 Super I/O controller.
**
**  FORMAL PARAMETERS:
**
**      func:
**          Which device function
**       
**      port:
**          I/O port for the function to use
**     
**      irq:
**          IRQ for the device function to use
**     
**      drq:
**          DMA channel for the device function to use
**
**  RETURN VALUE:
**
**      Returns TRUE if the device function was configured, 
**    otherwise, FALSE.
**
**  SIDE EFFECTS:
**
**      {@description or none@}
**
**  DESIGN:
**
**    If this function returns TRUE, the local shadow copy of
**    the configuration is also updated.  If the device function
**    is currently disabled, only the local shadow copy is 
**    updated and the actual device function will be updated
**    if/when it is enabled.
**
**--
*/
unsigned int __init SMC37c669_configure_device (
    unsigned int func,
    int port,
    int irq,
    int drq )
{
    struct DEVICE_CONFIG *cp;

/*
** Check for a valid configuration
*/
    if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
/*
** Configuration is valid, update the local shadow copy
*/
        if ( ( drq & ~0xFF ) == 0 ) {
        cp->drq = drq;
    }
    if ( ( irq & ~0xFF ) == 0 ) {
        cp->irq = irq;
    }
    if ( ( port & ~0xFFFF ) == 0 ) {
        cp->port1 = port;
    }
/*
** If the device function is enabled, update the actual
** device configuration.
*/
    if ( SMC37c669_is_device_enabled( func ) ) {
        SMC37c669_enable_device( func );
    }
    return TRUE;
    }
    return FALSE;
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function determines whether a device function
**    within the SMC37c669 controller is enabled.
**
**  FORMAL PARAMETERS:
**
**      func:
**          Which device function
**
**  RETURN VALUE:
**
**      Returns TRUE if the device function is enabled, otherwise, FALSE
**
**  SIDE EFFECTS:
**
**      {@description or none@}
**
**  DESIGN:
**
**      To check whether a device is enabled we will only look at 
**    the port base address mapping.  According to the SMC37c669
**    specification, all of the port base address mappings are
**    disabled if the addr<9:8> (bits <7:6> of the register) are
**    zero.
**
**--
*/
static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
{
    unsigned char base_addr = 0;
    unsigned int dev_ok = FALSE;
    unsigned int ret_val = FALSE;
/*
** Enter configuration mode
*/
    SMC37c669_config_mode( TRUE );
     
    switch ( func ) {
        case SERIAL_0:
        base_addr =
        SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
        dev_ok = TRUE;
        break;
    case SERIAL_1:
        base_addr =
        SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
        dev_ok = TRUE;
        break;
    case PARALLEL_0:
        base_addr =
        SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
        dev_ok = TRUE;
        break;
    case FLOPPY_0:
        base_addr =
        SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
        dev_ok = TRUE;
        break;
    case IDE_0:
        base_addr =
        SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
        dev_ok = TRUE;
        break;
    }
/*
** If we have a valid device, check base_addr<7:6> to see if the
** device is enabled (mapped).
*/
    if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
/*
** The mapping is not disabled, so assume that the function is 
** enabled.
*/
        ret_val = TRUE;
    }
/*
** Exit configuration mode 
*/
    SMC37c669_config_mode( FALSE );

    return ret_val;
}


#if 0
/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function retrieves the configuration information of a 
**    device function within the SMC37c699 Super I/O controller.
**
**  FORMAL PARAMETERS:
**
**      func:
**          Which device function
**       
**      port:
**          I/O port returned
**     
**      irq:
**          IRQ returned
**     
**      drq:
**          DMA channel returned
**
**  RETURN VALUE:
**
**      Returns TRUE if the device configuration was successfully
**    retrieved, otherwise, FALSE.
**
**  SIDE EFFECTS:
**
**      The data pointed to by the port, irq, and drq parameters
**    my be modified even if the configuration is not successfully
**    retrieved.
**
**  DESIGN:
**
**      The device configuration is fetched from the local shadow
**    copy.  Any unused parameters will be set to -1.  Any
**    parameter which is not desired can specify the NULL
**    pointer.
**
**--
*/
static unsigned int __init SMC37c669_get_device_config (
    unsigned int func,
    int *port,
    int *irq,
    int *drq )
{
    struct DEVICE_CONFIG *cp;
    unsigned int ret_val = FALSE;
/*
** Check for a valid device configuration
*/
    if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {
        if ( drq != NULL ) {
        *drq = cp->drq;
        ret_val = TRUE;
    }
    if ( irq != NULL ) {
        *irq = cp->irq;
        ret_val = TRUE;
    }
    if ( port != NULL ) {
        *port = cp->port1;
        ret_val = TRUE;
    }
    }
    return ret_val;
}
#endif


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function displays the current state of the SMC37c699
**    Super I/O controller's device functions.
**
**  FORMAL PARAMETERS:
**
**      None
**
**  RETURN VALUE:
**
**      None
**
**  SIDE EFFECTS:
**
**      None
**
**--
*/
void __init SMC37c669_display_device_info ( void )
{
    if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
        printk( "  Serial 0:    Enabled [ Port 0x%x, IRQ %d ]\n",
         local_config[ SERIAL_0 ].port1,
         local_config[ SERIAL_0 ].irq
    );
    }
    else {
        printk( "  Serial 0:    Disabled\n" );
    }

    if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
        printk( "  Serial 1:    Enabled [ Port 0x%x, IRQ %d ]\n",
         local_config[ SERIAL_1 ].port1,
         local_config[ SERIAL_1 ].irq
    );
    }
    else {
        printk( "  Serial 1:    Disabled\n" );
    }

    if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
        printk( "  Parallel:    Enabled [ Port 0x%x, IRQ %d/%d ]\n",
         local_config[ PARALLEL_0 ].port1,
         local_config[ PARALLEL_0 ].irq,
         local_config[ PARALLEL_0 ].drq
    );
    }
    else {
        printk( "  Parallel:    Disabled\n" );
    }

    if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
        printk( "  Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
         local_config[ FLOPPY_0 ].port1,
         local_config[ FLOPPY_0 ].irq,
         local_config[ FLOPPY_0 ].drq
    );
    }
    else {
        printk( "  Floppy Ctrl: Disabled\n" );
    }

    if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
        printk( "  IDE 0:       Enabled [ Port 0x%x, IRQ %d ]\n",
         local_config[ IDE_0 ].port1,
         local_config[ IDE_0 ].irq
    );
    }
    else {
        printk( "  IDE 0:       Disabled\n" );
    }
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function puts the SMC37c669 Super I/O controller into,
**    and takes it out of, configuration mode.
**
**  FORMAL PARAMETERS:
**
**      enable:
**          TRUE to enter configuration mode, FALSE to exit.
**
**  RETURN VALUE:
**
**      None
**
**  SIDE EFFECTS:
**
**      The SMC37c669 controller may be left in configuration mode.
**
**--
*/
static void __init SMC37c669_config_mode( 
    unsigned int enable )
{
    if ( enable ) {
/*
** To enter configuration mode, two writes in succession to the index
** port are required.  If a write to another address or port occurs
** between these two writes, the chip does not enter configuration
** mode.  Therefore, a spinlock is placed around the two writes to 
** guarantee that they complete uninterrupted.
*/
    spinlock( &spl_atomic );
        wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
        wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
    spinunlock( &spl_atomic );
    }
    else {
        wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
    }
}

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function reads an SMC37c669 Super I/O controller
**    configuration register.  This function assumes that the
**    device is already in configuration mode.
**
**  FORMAL PARAMETERS:
**
**      index:
**          Index value of configuration register to read
**
**  RETURN VALUE:
**
**      Data read from configuration register
**
**  SIDE EFFECTS:
**
**      None
**
**--
*/
static unsigned char __init SMC37c669_read_config( 
    unsigned char index )
{
    unsigned char data;

    wb( &SMC37c669->index_port, index );
    data = rb( &SMC37c669->data_port );
    return data;
}

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function writes an SMC37c669 Super I/O controller
**    configuration register.  This function assumes that the
**    device is already in configuration mode.
**
**  FORMAL PARAMETERS:
**
**      index:
**          Index of configuration register to write
**       
**      data:
**          Data to be written
**
**  RETURN VALUE:
**
**      None
**
**  SIDE EFFECTS:
**
**      None
**
**--
*/
static void __init SMC37c669_write_config( 
    unsigned char index, 
    unsigned char data )
{
    wb( &SMC37c669->index_port, index );
    wb( &SMC37c669->data_port, data );
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function initializes the local device
**    configuration storage.  This function assumes
**    that the device is already in configuration
**    mode.
**
**  FORMAL PARAMETERS:
**
**      None
**
**  RETURN VALUE:
**
**      None
**
**  SIDE EFFECTS:
**
**      Local storage for device configuration information
**    is initialized.
**
**--
*/
static void __init SMC37c669_init_local_config ( void )
{
    SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
    SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
    SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
    SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
    SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
    SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
    SMC37c669_IDE_ADDRESS_REGISTER ide_base;
    SMC37c669_IDE_ADDRESS_REGISTER ide_alt;

/*
** Get serial port 1 base address 
*/
    uart_base.as_uchar = 
    SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
/*
** Get IRQs for serial ports 1 & 2
*/
    uart_irqs.as_uchar = 
    SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
/*
** Store local configuration information for serial port 1
*/
    local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
    local_config[SERIAL_0].irq = 
    SMC37c669_xlate_irq( 
        SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq ) 
    );
/*
** Get serial port 2 base address
*/
    uart_base.as_uchar = 
    SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
/*
** Store local configuration information for serial port 2
*/
    local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
    local_config[SERIAL_1].irq = 
    SMC37c669_xlate_irq( 
        SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq ) 
    );
/*
** Get parallel port base address
*/
    ppt_base.as_uchar =
    SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
/*
** Get IRQs for parallel port and floppy controller
*/
    ppt_fdc_irqs.as_uchar =
    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
/*
** Get DRQs for parallel port and floppy controller
*/
    ppt_fdc_drqs.as_uchar =
    SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
/*
** Store local configuration information for parallel port
*/
    local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
    local_config[PARALLEL_0].irq =
    SMC37c669_xlate_irq(
        SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
    );
    local_config[PARALLEL_0].drq =
    SMC37c669_xlate_drq(
        SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
    );
/*
** Get floppy controller base address
*/
    fdc_base.as_uchar = 
    SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
/*
** Store local configuration information for floppy controller
*/
    local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
    local_config[FLOPPY_0].irq =
    SMC37c669_xlate_irq(
        SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
    );
    local_config[FLOPPY_0].drq =
    SMC37c669_xlate_drq(
        SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
    );
/*
** Get IDE controller base address
*/
    ide_base.as_uchar =
    SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
/*
** Get IDE alternate status base address
*/
    ide_alt.as_uchar =
    SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
/*
** Store local configuration information for IDE controller
*/
    local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
    local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
    local_config[IDE_0].irq = 14;
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function returns a pointer to the local shadow
**    configuration of the requested device function.
**
**  FORMAL PARAMETERS:
**
**      func:
**          Which device function
**
**  RETURN VALUE:
**
**      Returns a pointer to the DEVICE_CONFIG structure for the
**    requested function, otherwise, NULL.
**
**  SIDE EFFECTS:
**
**      {@description or none@}
**
**--
*/
static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
{
    struct DEVICE_CONFIG *cp = NULL;

    switch ( func ) {
        case SERIAL_0:
        cp = &local_config[ SERIAL_0 ];
        break;
    case SERIAL_1:
        cp = &local_config[ SERIAL_1 ];
        break;
    case PARALLEL_0:
        cp = &local_config[ PARALLEL_0 ];
        break;
    case FLOPPY_0:
        cp = &local_config[ FLOPPY_0 ];
        break;
    case IDE_0:
        cp = &local_config[ IDE_0 ];
        break;
    }
    return cp;
}

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function translates IRQs back and forth between ISA
**    IRQs and SMC37c669 device IRQs.
**
**  FORMAL PARAMETERS:
**
**      irq:
**          The IRQ to translate
**
**  RETURN VALUE:
**
**      Returns the translated IRQ, otherwise, returns -1.
**
**  SIDE EFFECTS:
**
**      {@description or none@}
**
**--
*/
static int __init SMC37c669_xlate_irq ( unsigned int irq )
{
    int i, translated_irq = -1;

    if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
/*
** We are translating a device IRQ to an ISA IRQ
*/
        for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
        if ( irq == SMC37c669_irq_table[i].device_irq ) {
            translated_irq = SMC37c669_irq_table[i].isa_irq;
        break;
        }
    }
    }
    else {
/*
** We are translating an ISA IRQ to a device IRQ
*/
        for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
        if ( irq == SMC37c669_irq_table[i].isa_irq ) {
            translated_irq = SMC37c669_irq_table[i].device_irq;
        break;
        }
    }
    }
    return translated_irq;
}


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function translates DMA channels back and forth between
**    ISA DMA channels and SMC37c669 device DMA channels.
**
**  FORMAL PARAMETERS:
**
**      drq:
**          The DMA channel to translate
**
**  RETURN VALUE:
**
**      Returns the translated DMA channel, otherwise, returns -1
**
**  SIDE EFFECTS:
**
**      {@description or none@}
**
**--
*/
static int __init SMC37c669_xlate_drq ( unsigned int drq )
{
    int i, translated_drq = -1;

    if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
/*
** We are translating a device DMA channel to an ISA DMA channel
*/
        for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
        if ( drq == SMC37c669_drq_table[i].device_drq ) {
            translated_drq = SMC37c669_drq_table[i].isa_drq;
        break;
        }
    }
    }
    else {
/*
** We are translating an ISA DMA channel to a device DMA channel
*/
        for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
        if ( drq == SMC37c669_drq_table[i].isa_drq ) {
            translated_drq = SMC37c669_drq_table[i].device_drq;
        break;
        }
    }
    }
    return translated_drq;
}

#if 0
int __init smcc669_init ( void )
{
    struct INODE *ip;

    allocinode( smc_ddb.name, 1, &ip );
    ip->dva = &smc_ddb;
    ip->attr = ATTR$M_WRITE | ATTR$M_READ;
    ip->len[0] = 0x30;
    ip->misc = 0;
    INODE_UNLOCK( ip );

    return msg_success;
}

int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )
{
    struct INODE *ip;
/*
** Allow multiple readers but only one writer.  ip->misc keeps track
** of the number of writers
*/
    ip = fp->ip;
    INODE_LOCK( ip );
    if ( fp->mode & ATTR$M_WRITE ) {
    if ( ip->misc ) {
        INODE_UNLOCK( ip );
        return msg_failure;        /* too many writers */
    }
    ip->misc++;
    }
/*
** Treat the information field as a byte offset
*/
    *fp->offset = xtoi( info );
    INODE_UNLOCK( ip );

    return msg_success;
}

int __init smcc669_close( struct FILE *fp )
{
    struct INODE *ip;

    ip = fp->ip;
    if ( fp->mode & ATTR$M_WRITE ) {
    INODE_LOCK( ip );
    ip->misc--;
    INODE_UNLOCK( ip );
    }
    return msg_success;
}

int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )
{
    int i;
    int length;
    int nbytes;
    struct INODE *ip;

/*
** Always access a byte at a time
*/
    ip = fp->ip;
    length = size * number;
    nbytes = 0;

    SMC37c669_config_mode( TRUE );
    for ( i = 0; i < length; i++ ) {
    if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 
        break;
    *buf++ = SMC37c669_read_config( *fp->offset );
    *fp->offset += 1;
    nbytes++;
    }
    SMC37c669_config_mode( FALSE );
    return nbytes;
}

int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )
{
    int i;
    int length;
    int nbytes;
    struct INODE *ip;
/*
** Always access a byte at a time
*/
    ip = fp->ip;
    length = size * number;
    nbytes = 0;

    SMC37c669_config_mode( TRUE );
    for ( i = 0; i < length; i++ ) {
    if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 
        break;
    SMC37c669_write_config( *fp->offset, *buf );
    *fp->offset += 1;
    buf++;
    nbytes++;
    }
    SMC37c669_config_mode( FALSE );
    return nbytes;
}
#endif

void __init
SMC37c669_dump_registers(void)
{
  int i;
  for (i = 0; i <= 0x29; i++)
    printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
}
/*+
 * ============================================================================
 * = SMC_init - SMC37c669 Super I/O controller initialization                 =
 * ============================================================================
 *
 * OVERVIEW:
 *
 *      This routine configures and enables device functions on the
 *      SMC37c669 Super I/O controller.
 *
 * FORM OF CALL:
 *
 *      SMC_init( );
 *
 * RETURNS:
 *
 *      1 if the chip found, 0 otherwise
 *
 * ARGUMENTS:
 *
 *      None
 *
 * SIDE EFFECTS:
 *
 *      None
 *
 */
int __init SMC669_Init ( int index )
{
    SMC37c669_CONFIG_REGS *SMC_base;
    unsigned long flags;

    __save_and_cli(flags);
    if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
#if SMC_DEBUG
    SMC37c669_config_mode( TRUE );
    SMC37c669_dump_registers( );
    SMC37c669_config_mode( FALSE );
        SMC37c669_display_device_info( );
#endif
        SMC37c669_disable_device( SERIAL_0 );
        SMC37c669_configure_device(
            SERIAL_0,
            COM1_BASE,
            COM1_IRQ,
            -1
        );
        SMC37c669_enable_device( SERIAL_0 );

        SMC37c669_disable_device( SERIAL_1 );
        SMC37c669_configure_device(
            SERIAL_1,
            COM2_BASE,
            COM2_IRQ,
            -1
        );
        SMC37c669_enable_device( SERIAL_1 );

        SMC37c669_disable_device( PARALLEL_0 );
        SMC37c669_configure_device(
            PARALLEL_0,
            PARP_BASE,
            PARP_IRQ,
            PARP_DRQ
        );
        SMC37c669_enable_device( PARALLEL_0 );

        SMC37c669_disable_device( FLOPPY_0 );
        SMC37c669_configure_device(
            FLOPPY_0,
            FDC_BASE,
            FDC_IRQ,
            FDC_DRQ
        );
        SMC37c669_enable_device( FLOPPY_0 );
          
    /* Wake up sometimes forgotten floppy, especially on DP264. */
    outb(0xc, 0x3f2);

        SMC37c669_disable_device( IDE_0 );

#if SMC_DEBUG
    SMC37c669_config_mode( TRUE );
    SMC37c669_dump_registers( );
    SMC37c669_config_mode( FALSE );
        SMC37c669_display_device_info( );
#endif
    __restore_flags(flags);
        printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n",
        (unsigned long) SMC_base );
    return 1;
    }
    else {
    __restore_flags(flags);
#if SMC_DEBUG
        printk( "No SMC37c669 Super I/O Controller found\n" );
#endif
    return 0;
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0338 ]--