2005-04-17 02:20:36 +04:00
/*
* SMC 37 C669 initialization code
*/
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/spinlock.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 37 c669 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 37 c669 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 > ) :
* * 0 x - 30u a 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 > = 0000 b
* * 10 - 8 byte block decode A < 3 : 0 > = 0 XXXb
* * 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
* * 1 xx - 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 > = 0001 b
* * 10 - 8 byte block decode ADR < 3 : 0 > = 0 XXXb
* * 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 > = 0 XXXb 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 > = 0 XXXb 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 > = 0110 b 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 .
*
* - -
*/
# 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 ;
int irq ;
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 ;
/*
* * 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 ;
/*
* * 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 (
int irq
) ;
static int SMC37c669_xlate_drq (
int drq
) ;
static __cacheline_aligned DEFINE_SPINLOCK ( smc_lock ) ;
/*
* * + +
* * 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 .
*/
spin_lock ( & smc_lock ) ;
wb ( & SMC37c669 - > index_port , SMC37c669_CONFIG_ON_KEY ) ;
wb ( & SMC37c669 - > index_port , SMC37c669_CONFIG_ON_KEY ) ;
spin_unlock ( & smc_lock ) ;
}
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 )
{
2016-09-11 09:26:51 +03:00
wb ( & SMC37c669 - > index_port , index ) ;
return rb ( & SMC37c669 - > data_port ) ;
2005-04-17 02:20:36 +04:00
}
/*
* * + +
* * 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 ( 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 ( 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 :
*
* Nothing
*
* ARGUMENTS :
*
* None
*
* SIDE EFFECTS :
*
* None
*
*/
void __init SMC669_Init ( int index )
{
SMC37c669_CONFIG_REGS * SMC_base ;
unsigned long flags ;
local_irq_save ( 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
local_irq_restore ( flags ) ;
2009-04-01 02:23:36 +04:00
printk ( " SMC37c669 Super I/O Controller found @ 0x%p \n " ,
SMC_base ) ;
2005-04-17 02:20:36 +04:00
}
else {
local_irq_restore ( flags ) ;
# if SMC_DEBUG
printk ( " No SMC37c669 Super I/O Controller found \n " ) ;
# endif
}
}