| /* | |
| * SMC 37C669 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 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. | |
| * | |
| *-- | |
| */ | |
| #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 ) | |
| { | |
| 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 ( 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); | |
| printk( "SMC37c669 Super I/O Controller found @ 0x%p\n", | |
| SMC_base ); | |
| } | |
| else { | |
| local_irq_restore(flags); | |
| #if SMC_DEBUG | |
| printk( "No SMC37c669 Super I/O Controller found\n" ); | |
| #endif | |
| } | |
| } |