/*1* SMC 37C669 initialization code2*/3#include <linux/kernel.h>45#include <linux/mm.h>6#include <linux/init.h>7#include <linux/delay.h>8#include <linux/spinlock.h>910#include <asm/hwrpb.h>11#include <asm/io.h>1213#include "proto.h"1415#if 016# define DBG_DEVS(args) printk args17#else18# define DBG_DEVS(args)19#endif2021#define KB 102422#define MB (1024*KB)23#define GB (1024*MB)2425#define SMC_DEBUG 02627/* File: smcc669_def.h28*29* Copyright (C) 1997 by30* Digital Equipment Corporation, Maynard, Massachusetts.31* All rights reserved.32*33* This software is furnished under a license and may be used and copied34* only in accordance of the terms of such license and with the35* inclusion of the above copyright notice. This software or any other36* copies thereof may not be provided or otherwise made available to any37* other person. No title to and ownership of the software is hereby38* transferred.39*40* The information in this software is subject to change without notice41* and should not be construed as a commitment by Digital Equipment42* Corporation.43*44* Digital assumes no responsibility for the use or reliability of its45* software on equipment which is not supplied by Digital.46*47*48* Abstract:49*50* This file contains header definitions for the SMC37c66951* Super I/O controller.52*53* Author:54*55* Eric Rasmussen56*57* Modification History:58*59* er 28-Jan-1997 Initial Entry60*/6162#ifndef __SMC37c669_H63#define __SMC37c669_H6465/*66** Macros for handling device IRQs67**68** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)69** to device IRQs (A - H).70*/71#define SMC37c669_DEVICE_IRQ_MASK 0x8000000072#define SMC37c669_DEVICE_IRQ( __i ) \73((SMC37c669_DEVICE_IRQ_MASK) | (__i))74#define SMC37c669_IS_DEVICE_IRQ(__i) \75(((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))76#define SMC37c669_RAW_DEVICE_IRQ(__i) \77((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))7879/*80** Macros for handling device DRQs81**82** The mask acts as a flag used in mapping actual ISA DMA83** channels to device DMA channels (A - C).84*/85#define SMC37c669_DEVICE_DRQ_MASK 0x8000000086#define SMC37c669_DEVICE_DRQ(__d) \87((SMC37c669_DEVICE_DRQ_MASK) | (__d))88#define SMC37c669_IS_DEVICE_DRQ(__d) \89(((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))90#define SMC37c669_RAW_DEVICE_DRQ(__d) \91((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))9293#define SMC37c669_DEVICE_ID 0x39495/*96** SMC37c669 Device Function Definitions97*/98#define SERIAL_0 099#define SERIAL_1 1100#define PARALLEL_0 2101#define FLOPPY_0 3102#define IDE_0 4103#define NUM_FUNCS 5104105/*106** Default Device Function Mappings107*/108#define COM1_BASE 0x3F8109#define COM1_IRQ 4110#define COM2_BASE 0x2F8111#define COM2_IRQ 3112#define PARP_BASE 0x3BC113#define PARP_IRQ 7114#define PARP_DRQ 3115#define FDC_BASE 0x3F0116#define FDC_IRQ 6117#define FDC_DRQ 2118119/*120** Configuration On/Off Key Definitions121*/122#define SMC37c669_CONFIG_ON_KEY 0x55123#define SMC37c669_CONFIG_OFF_KEY 0xAA124125/*126** SMC 37c669 Device IRQs127*/128#define SMC37c669_DEVICE_IRQ_A ( SMC37c669_DEVICE_IRQ( 0x01 ) )129#define SMC37c669_DEVICE_IRQ_B ( SMC37c669_DEVICE_IRQ( 0x02 ) )130#define SMC37c669_DEVICE_IRQ_C ( SMC37c669_DEVICE_IRQ( 0x03 ) )131#define SMC37c669_DEVICE_IRQ_D ( SMC37c669_DEVICE_IRQ( 0x04 ) )132#define SMC37c669_DEVICE_IRQ_E ( SMC37c669_DEVICE_IRQ( 0x05 ) )133#define SMC37c669_DEVICE_IRQ_F ( SMC37c669_DEVICE_IRQ( 0x06 ) )134/* SMC37c669_DEVICE_IRQ_G *** RESERVED ***/135#define SMC37c669_DEVICE_IRQ_H ( SMC37c669_DEVICE_IRQ( 0x08 ) )136137/*138** SMC 37c669 Device DMA Channel Definitions139*/140#define SMC37c669_DEVICE_DRQ_A ( SMC37c669_DEVICE_DRQ( 0x01 ) )141#define SMC37c669_DEVICE_DRQ_B ( SMC37c669_DEVICE_DRQ( 0x02 ) )142#define SMC37c669_DEVICE_DRQ_C ( SMC37c669_DEVICE_DRQ( 0x03 ) )143144/*145** Configuration Register Index Definitions146*/147#define SMC37c669_CR00_INDEX 0x00148#define SMC37c669_CR01_INDEX 0x01149#define SMC37c669_CR02_INDEX 0x02150#define SMC37c669_CR03_INDEX 0x03151#define SMC37c669_CR04_INDEX 0x04152#define SMC37c669_CR05_INDEX 0x05153#define SMC37c669_CR06_INDEX 0x06154#define SMC37c669_CR07_INDEX 0x07155#define SMC37c669_CR08_INDEX 0x08156#define SMC37c669_CR09_INDEX 0x09157#define SMC37c669_CR0A_INDEX 0x0A158#define SMC37c669_CR0B_INDEX 0x0B159#define SMC37c669_CR0C_INDEX 0x0C160#define SMC37c669_CR0D_INDEX 0x0D161#define SMC37c669_CR0E_INDEX 0x0E162#define SMC37c669_CR0F_INDEX 0x0F163#define SMC37c669_CR10_INDEX 0x10164#define SMC37c669_CR11_INDEX 0x11165#define SMC37c669_CR12_INDEX 0x12166#define SMC37c669_CR13_INDEX 0x13167#define SMC37c669_CR14_INDEX 0x14168#define SMC37c669_CR15_INDEX 0x15169#define SMC37c669_CR16_INDEX 0x16170#define SMC37c669_CR17_INDEX 0x17171#define SMC37c669_CR18_INDEX 0x18172#define SMC37c669_CR19_INDEX 0x19173#define SMC37c669_CR1A_INDEX 0x1A174#define SMC37c669_CR1B_INDEX 0x1B175#define SMC37c669_CR1C_INDEX 0x1C176#define SMC37c669_CR1D_INDEX 0x1D177#define SMC37c669_CR1E_INDEX 0x1E178#define SMC37c669_CR1F_INDEX 0x1F179#define SMC37c669_CR20_INDEX 0x20180#define SMC37c669_CR21_INDEX 0x21181#define SMC37c669_CR22_INDEX 0x22182#define SMC37c669_CR23_INDEX 0x23183#define SMC37c669_CR24_INDEX 0x24184#define SMC37c669_CR25_INDEX 0x25185#define SMC37c669_CR26_INDEX 0x26186#define SMC37c669_CR27_INDEX 0x27187#define SMC37c669_CR28_INDEX 0x28188#define SMC37c669_CR29_INDEX 0x29189190/*191** Configuration Register Alias Definitions192*/193#define SMC37c669_DEVICE_ID_INDEX SMC37c669_CR0D_INDEX194#define SMC37c669_DEVICE_REVISION_INDEX SMC37c669_CR0E_INDEX195#define SMC37c669_FDC_BASE_ADDRESS_INDEX SMC37c669_CR20_INDEX196#define SMC37c669_IDE_BASE_ADDRESS_INDEX SMC37c669_CR21_INDEX197#define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX SMC37c669_CR22_INDEX198#define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX SMC37c669_CR23_INDEX199#define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX SMC37c669_CR24_INDEX200#define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX SMC37c669_CR25_INDEX201#define SMC37c669_PARALLEL_FDC_DRQ_INDEX SMC37c669_CR26_INDEX202#define SMC37c669_PARALLEL_FDC_IRQ_INDEX SMC37c669_CR27_INDEX203#define SMC37c669_SERIAL_IRQ_INDEX SMC37c669_CR28_INDEX204205/*206** Configuration Register Definitions207**208** The INDEX (write only) and DATA (read/write) ports are effective209** only when the chip is in the Configuration State.210*/211typedef struct _SMC37c669_CONFIG_REGS {212unsigned char index_port;213unsigned char data_port;214} SMC37c669_CONFIG_REGS;215216/*217** CR00 - default value 0x28218**219** IDE_EN (CR00<1:0>):220** 0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1221** 11 - IRQ_H available as IRQ output,222** IRRX2, IRTX2 available as alternate IR pins223** 10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE224**225** VALID (CR00<7>):226** A high level on this software controlled bit can227** be used to indicate that a valid configuration228** cycle has occurred. The control software must229** take care to set this bit at the appropriate times.230** Set to zero after power up. This bit has no231** effect on any other hardware in the chip.232**233*/234typedef union _SMC37c669_CR00 {235unsigned char as_uchar;236struct {237unsigned ide_en : 2; /* See note above */238unsigned reserved1 : 1; /* RAZ */239unsigned fdc_pwr : 1; /* 1 = supply power to FDC */240unsigned reserved2 : 3; /* Read as 010b */241unsigned valid : 1; /* See note above */242} by_field;243} SMC37c669_CR00;244245/*246** CR01 - default value 0x9C247*/248typedef union _SMC37c669_CR01 {249unsigned char as_uchar;250struct {251unsigned reserved1 : 2; /* RAZ */252unsigned ppt_pwr : 1; /* 1 = supply power to PPT */253unsigned ppt_mode : 1; /* 1 = Printer mode, 0 = EPP */254unsigned reserved2 : 1; /* Read as 1 */255unsigned reserved3 : 2; /* RAZ */256unsigned lock_crx: 1; /* Lock CR00 - CR18 */257} by_field;258} SMC37c669_CR01;259260/*261** CR02 - default value 0x88262*/263typedef union _SMC37c669_CR02 {264unsigned char as_uchar;265struct {266unsigned reserved1 : 3; /* RAZ */267unsigned uart1_pwr : 1; /* 1 = supply power to UART1 */268unsigned reserved2 : 3; /* RAZ */269unsigned uart2_pwr : 1; /* 1 = supply power to UART2 */270} by_field;271} SMC37c669_CR02;272273/*274** CR03 - default value 0x78275**276** CR03<7> CR03<2> Pin 94277** ------- ------- ------278** 0 X DRV2 (input)279** 1 0 ADRX280** 1 1 IRQ_B281**282** CR03<6> CR03<5> Op Mode283** ------- ------- -------284** 0 0 Model 30285** 0 1 PS/2286** 1 0 Reserved287** 1 1 AT Mode288*/289typedef union _SMC37c669_CR03 {290unsigned char as_uchar;291struct {292unsigned pwrgd_gamecs : 1; /* 1 = PWRGD, 0 = GAMECS */293unsigned fdc_mode2 : 1; /* 1 = Enhanced Mode 2 */294unsigned pin94_0 : 1; /* See note above */295unsigned reserved1 : 1; /* RAZ */296unsigned drvden : 1; /* 1 = high, 0 - output */297unsigned op_mode : 2; /* See note above */298unsigned pin94_1 : 1; /* See note above */299} by_field;300} SMC37c669_CR03;301302/*303** CR04 - default value 0x00304**305** PP_EXT_MODE:306** If CR01<PP_MODE> = 0 and PP_EXT_MODE =307** 00 - Standard and Bidirectional308** 01 - EPP mode and SPP309** 10 - ECP mode310** In this mode, 2 drives can be supported311** directly, 3 or 4 drives must use external312** 4 drive support. SPP can be selected313** through the ECR register of ECP as mode 000.314** 11 - ECP mode and EPP mode315** In this mode, 2 drives can be supported316** directly, 3 or 4 drives must use external317** 4 drive support. SPP can be selected318** through the ECR register of ECP as mode 000.319** In this mode, EPP can be selected through320** the ECR register of ECP as mode 100.321**322** PP_FDC:323** 00 - Normal324** 01 - PPFD1325** 10 - PPFD2326** 11 - Reserved327**328** MIDI1:329** Serial Clock Select:330** A low level on this bit disables MIDI support,331** clock = divide by 13. A high level on this332** bit enables MIDI support, clock = divide by 12.333**334** MIDI operates at 31.25 Kbps which can be derived335** from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)336**337** ALT_IO:338** 0 - Use pins IRRX, IRTX339** 1 - Use pins IRRX2, IRTX2340**341** If this bit is set, the IR receive and transmit342** functions will not be available on pins 25 and 26343** unless CR00<IDE_EN> = 11.344*/345typedef union _SMC37c669_CR04 {346unsigned char as_uchar;347struct {348unsigned ppt_ext_mode : 2; /* See note above */349unsigned ppt_fdc : 2; /* See note above */350unsigned midi1 : 1; /* See note above */351unsigned midi2 : 1; /* See note above */352unsigned epp_type : 1; /* 0 = EPP 1.9, 1 = EPP 1.7 */353unsigned alt_io : 1; /* See note above */354} by_field;355} SMC37c669_CR04;356357/*358** CR05 - default value 0x00359**360** DEN_SEL:361** 00 - Densel output normal362** 01 - Reserved363** 10 - Densel output 1364** 11 - Densel output 0365**366*/367typedef union _SMC37c669_CR05 {368unsigned char as_uchar;369struct {370unsigned reserved1 : 2; /* RAZ */371unsigned fdc_dma_mode : 1; /* 0 = burst, 1 = non-burst */372unsigned den_sel : 2; /* See note above */373unsigned swap_drv : 1; /* Swap the FDC motor selects */374unsigned extx4 : 1; /* 0 = 2 drive, 1 = external 4 drive decode */375unsigned reserved2 : 1; /* RAZ */376} by_field;377} SMC37c669_CR05;378379/*380** CR06 - default value 0xFF381*/382typedef union _SMC37c669_CR06 {383unsigned char as_uchar;384struct {385unsigned floppy_a : 2; /* Type of floppy drive A */386unsigned floppy_b : 2; /* Type of floppy drive B */387unsigned floppy_c : 2; /* Type of floppy drive C */388unsigned floppy_d : 2; /* Type of floppy drive D */389} by_field;390} SMC37c669_CR06;391392/*393** CR07 - default value 0x00394**395** Auto Power Management CR07<7:4>:396** 0 - Auto Powerdown disabled (default)397** 1 - Auto Powerdown enabled398**399** This bit is reset to the default state by POR or400** a hardware reset.401**402*/403typedef union _SMC37c669_CR07 {404unsigned char as_uchar;405struct {406unsigned floppy_boot : 2; /* 0 = A:, 1 = B: */407unsigned reserved1 : 2; /* RAZ */408unsigned ppt_en : 1; /* See note above */409unsigned uart1_en : 1; /* See note above */410unsigned uart2_en : 1; /* See note above */411unsigned fdc_en : 1; /* See note above */412} by_field;413} SMC37c669_CR07;414415/*416** CR08 - default value 0x00417*/418typedef union _SMC37c669_CR08 {419unsigned char as_uchar;420struct {421unsigned zero : 4; /* 0 */422unsigned addrx7_4 : 4; /* ADR<7:3> for ADRx decode */423} by_field;424} SMC37c669_CR08;425426/*427** CR09 - default value 0x00428**429** ADRx_CONFIG:430** 00 - ADRx disabled431** 01 - 1 byte decode A<3:0> = 0000b432** 10 - 8 byte block decode A<3:0> = 0XXXb433** 11 - 16 byte block decode A<3:0> = XXXXb434**435*/436typedef union _SMC37c669_CR09 {437unsigned char as_uchar;438struct {439unsigned adra8 : 3; /* ADR<10:8> for ADRx decode */440unsigned reserved1 : 3;441unsigned adrx_config : 2; /* See note above */442} by_field;443} SMC37c669_CR09;444445/*446** CR0A - default value 0x00447*/448typedef union _SMC37c669_CR0A {449unsigned char as_uchar;450struct {451unsigned ecp_fifo_threshold : 4;452unsigned reserved1 : 4;453} by_field;454} SMC37c669_CR0A;455456/*457** CR0B - default value 0x00458*/459typedef union _SMC37c669_CR0B {460unsigned char as_uchar;461struct {462unsigned fdd0_drtx : 2; /* FDD0 Data Rate Table */463unsigned fdd1_drtx : 2; /* FDD1 Data Rate Table */464unsigned fdd2_drtx : 2; /* FDD2 Data Rate Table */465unsigned fdd3_drtx : 2; /* FDD3 Data Rate Table */466} by_field;467} SMC37c669_CR0B;468469/*470** CR0C - default value 0x00471**472** UART2_MODE:473** 000 - Standard (default)474** 001 - IrDA (HPSIR)475** 010 - Amplitude Shift Keyed IR @500 KHz476** 011 - Reserved477** 1xx - Reserved478**479*/480typedef union _SMC37c669_CR0C {481unsigned char as_uchar;482struct {483unsigned uart2_rcv_polarity : 1; /* 1 = invert RX */484unsigned uart2_xmit_polarity : 1; /* 1 = invert TX */485unsigned uart2_duplex : 1; /* 1 = full, 0 = half */486unsigned uart2_mode : 3; /* See note above */487unsigned uart1_speed : 1; /* 1 = high speed enabled */488unsigned uart2_speed : 1; /* 1 = high speed enabled */489} by_field;490} SMC37c669_CR0C;491492/*493** CR0D - default value 0x03494**495** Device ID Register - read only496*/497typedef union _SMC37c669_CR0D {498unsigned char as_uchar;499struct {500unsigned device_id : 8; /* Returns 0x3 in this field */501} by_field;502} SMC37c669_CR0D;503504/*505** CR0E - default value 0x02506**507** Device Revision Register - read only508*/509typedef union _SMC37c669_CR0E {510unsigned char as_uchar;511struct {512unsigned device_rev : 8; /* Returns 0x2 in this field */513} by_field;514} SMC37c669_CR0E;515516/*517** CR0F - default value 0x00518*/519typedef union _SMC37c669_CR0F {520unsigned char as_uchar;521struct {522unsigned test0 : 1; /* Reserved - set to 0 */523unsigned test1 : 1; /* Reserved - set to 0 */524unsigned test2 : 1; /* Reserved - set to 0 */525unsigned test3 : 1; /* Reserved - set t0 0 */526unsigned test4 : 1; /* Reserved - set to 0 */527unsigned test5 : 1; /* Reserved - set t0 0 */528unsigned test6 : 1; /* Reserved - set t0 0 */529unsigned test7 : 1; /* Reserved - set to 0 */530} by_field;531} SMC37c669_CR0F;532533/*534** CR10 - default value 0x00535*/536typedef union _SMC37c669_CR10 {537unsigned char as_uchar;538struct {539unsigned reserved1 : 3; /* RAZ */540unsigned pll_gain : 1; /* 1 = 3V, 2 = 5V operation */541unsigned pll_stop : 1; /* 1 = stop PLLs */542unsigned ace_stop : 1; /* 1 = stop UART clocks */543unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz */544unsigned ir_test : 1; /* Enable IR test mode */545} by_field;546} SMC37c669_CR10;547548/*549** CR11 - default value 0x00550*/551typedef union _SMC37c669_CR11 {552unsigned char as_uchar;553struct {554unsigned ir_loopback : 1; /* Internal IR loop back */555unsigned test_10ms : 1; /* Test 10ms autopowerdown FDC timeout */556unsigned reserved1 : 6; /* RAZ */557} by_field;558} SMC37c669_CR11;559560/*561** CR12 - CR1D are reserved registers562*/563564/*565** CR1E - default value 0x80566**567** GAMECS:568** 00 - GAMECS disabled569** 01 - 1 byte decode ADR<3:0> = 0001b570** 10 - 8 byte block decode ADR<3:0> = 0XXXb571** 11 - 16 byte block decode ADR<3:0> = XXXXb572**573*/574typedef union _SMC37c66_CR1E {575unsigned char as_uchar;576struct {577unsigned gamecs_config: 2; /* See note above */578unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4> */579} by_field;580} SMC37c669_CR1E;581582/*583** CR1F - default value 0x00584**585** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type586** --- --- ------- ------- ----------587** 0 0 DENSEL DRATE0 4/2/1 MB 3.5"588** 2/1 MB 5.25"589** 2/1.6/1 MB 3.5" (3-mode)590** 0 1 DRATE1 DRATE0591** 1 0 nDENSEL DRATE0 PS/2592** 1 1 DRATE0 DRATE1593**594** Note: DENSEL, DRATE1, and DRATE0 map onto two output595** pins - DRVDEN0 and DRVDEN1.596**597*/598typedef union _SMC37c669_CR1F {599unsigned char as_uchar;600struct {601unsigned fdd0_drive_type : 2; /* FDD0 drive type */602unsigned fdd1_drive_type : 2; /* FDD1 drive type */603unsigned fdd2_drive_type : 2; /* FDD2 drive type */604unsigned fdd3_drive_type : 2; /* FDD3 drive type */605} by_field;606} SMC37c669_CR1F;607608/*609** CR20 - default value 0x3C610**611** FDC Base Address Register612** - To disable this decode set Addr<9:8> = 0613** - A<10> = 0, A<3:0> = 0XXXb to access.614**615*/616typedef union _SMC37c669_CR20 {617unsigned char as_uchar;618struct {619unsigned zero : 2; /* 0 */620unsigned addr9_4 : 6; /* FDC Addr<9:4> */621} by_field;622} SMC37c669_CR20;623624/*625** CR21 - default value 0x3C626**627** IDE Base Address Register628** - To disable this decode set Addr<9:8> = 0629** - A<10> = 0, A<3:0> = 0XXXb to access.630**631*/632typedef union _SMC37c669_CR21 {633unsigned char as_uchar;634struct {635unsigned zero : 2; /* 0 */636unsigned addr9_4 : 6; /* IDE Addr<9:4> */637} by_field;638} SMC37c669_CR21;639640/*641** CR22 - default value 0x3D642**643** IDE Alternate Status Base Address Register644** - To disable this decode set Addr<9:8> = 0645** - A<10> = 0, A<3:0> = 0110b to access.646**647*/648typedef union _SMC37c669_CR22 {649unsigned char as_uchar;650struct {651unsigned zero : 2; /* 0 */652unsigned addr9_4 : 6; /* IDE Alt Status Addr<9:4> */653} by_field;654} SMC37c669_CR22;655656/*657** CR23 - default value 0x00658**659** Parallel Port Base Address Register660** - To disable this decode set Addr<9:8> = 0661** - A<10> = 0 to access.662** - If EPP is enabled, A<2:0> = XXXb to access.663** If EPP is NOT enabled, A<1:0> = XXb to access664**665*/666typedef union _SMC37c669_CR23 {667unsigned char as_uchar;668struct {669unsigned addr9_2 : 8; /* Parallel Port Addr<9:2> */670} by_field;671} SMC37c669_CR23;672673/*674** CR24 - default value 0x00675**676** UART1 Base Address Register677** - To disable this decode set Addr<9:8> = 0678** - A<10> = 0, A<2:0> = XXXb to access.679**680*/681typedef union _SMC37c669_CR24 {682unsigned char as_uchar;683struct {684unsigned zero : 1; /* 0 */685unsigned addr9_3 : 7; /* UART1 Addr<9:3> */686} by_field;687} SMC37c669_CR24;688689/*690** CR25 - default value 0x00691**692** UART2 Base Address Register693** - To disable this decode set Addr<9:8> = 0694** - A<10> = 0, A<2:0> = XXXb to access.695**696*/697typedef union _SMC37c669_CR25 {698unsigned char as_uchar;699struct {700unsigned zero : 1; /* 0 */701unsigned addr9_3 : 7; /* UART2 Addr<9:3> */702} by_field;703} SMC37c669_CR25;704705/*706** CR26 - default value 0x00707**708** Parallel Port / FDC DMA Select Register709**710** D3 - D0 DMA711** D7 - D4 Selected712** ------- --------713** 0000 None714** 0001 DMA_A715** 0010 DMA_B716** 0011 DMA_C717**718*/719typedef union _SMC37c669_CR26 {720unsigned char as_uchar;721struct {722unsigned ppt_drq : 4; /* See note above */723unsigned fdc_drq : 4; /* See note above */724} by_field;725} SMC37c669_CR26;726727/*728** CR27 - default value 0x00729**730** Parallel Port / FDC IRQ Select Register731**732** D3 - D0 IRQ733** D7 - D4 Selected734** ------- --------735** 0000 None736** 0001 IRQ_A737** 0010 IRQ_B738** 0011 IRQ_C739** 0100 IRQ_D740** 0101 IRQ_E741** 0110 IRQ_F742** 0111 Reserved743** 1000 IRQ_H744**745** Any unselected IRQ REQ is in tristate746**747*/748typedef union _SMC37c669_CR27 {749unsigned char as_uchar;750struct {751unsigned ppt_irq : 4; /* See note above */752unsigned fdc_irq : 4; /* See note above */753} by_field;754} SMC37c669_CR27;755756/*757** CR28 - default value 0x00758**759** UART IRQ Select Register760**761** D3 - D0 IRQ762** D7 - D4 Selected763** ------- --------764** 0000 None765** 0001 IRQ_A766** 0010 IRQ_B767** 0011 IRQ_C768** 0100 IRQ_D769** 0101 IRQ_E770** 0110 IRQ_F771** 0111 Reserved772** 1000 IRQ_H773** 1111 share with UART1 (only for UART2)774**775** Any unselected IRQ REQ is in tristate776**777** To share an IRQ between UART1 and UART2, set778** UART1 to use the desired IRQ and set UART2 to779** 0xF to enable sharing mechanism.780**781*/782typedef union _SMC37c669_CR28 {783unsigned char as_uchar;784struct {785unsigned uart2_irq : 4; /* See note above */786unsigned uart1_irq : 4; /* See note above */787} by_field;788} SMC37c669_CR28;789790/*791** CR29 - default value 0x00792**793** IRQIN IRQ Select Register794**795** D3 - D0 IRQ796** D7 - D4 Selected797** ------- --------798** 0000 None799** 0001 IRQ_A800** 0010 IRQ_B801** 0011 IRQ_C802** 0100 IRQ_D803** 0101 IRQ_E804** 0110 IRQ_F805** 0111 Reserved806** 1000 IRQ_H807**808** Any unselected IRQ REQ is in tristate809**810*/811typedef union _SMC37c669_CR29 {812unsigned char as_uchar;813struct {814unsigned irqin_irq : 4; /* See note above */815unsigned reserved1 : 4; /* RAZ */816} by_field;817} SMC37c669_CR29;818819/*820** Aliases of Configuration Register formats (should match821** the set of index aliases).822**823** Note that CR24 and CR25 have the same format and are the824** base address registers for UART1 and UART2. Because of825** this we only define 1 alias here - for CR24 - as the serial826** base address register.827**828** Note that CR21 and CR22 have the same format and are the829** base address and alternate status address registers for830** the IDE controller. Because of this we only define 1 alias831** here - for CR21 - as the IDE address register.832**833*/834typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;835typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;836typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;837typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;838typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;839typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;840typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;841typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;842typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;843844/*845** ISA/Device IRQ Translation Table Entry Definition846*/847typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {848int device_irq;849int isa_irq;850} SMC37c669_IRQ_TRANSLATION_ENTRY;851852/*853** ISA/Device DMA Translation Table Entry Definition854*/855typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {856int device_drq;857int isa_drq;858} SMC37c669_DRQ_TRANSLATION_ENTRY;859860/*861** External Interface Function Prototype Declarations862*/863864SMC37c669_CONFIG_REGS *SMC37c669_detect(865int866);867868unsigned int SMC37c669_enable_device(869unsigned int func870);871872unsigned int SMC37c669_disable_device(873unsigned int func874);875876unsigned int SMC37c669_configure_device(877unsigned int func,878int port,879int irq,880int drq881);882883void SMC37c669_display_device_info(884void885);886887#endif /* __SMC37c669_H */888889/* file: smcc669.c890*891* Copyright (C) 1997 by892* Digital Equipment Corporation, Maynard, Massachusetts.893* All rights reserved.894*895* This software is furnished under a license and may be used and copied896* only in accordance of the terms of such license and with the897* inclusion of the above copyright notice. This software or any other898* copies thereof may not be provided or otherwise made available to any899* other person. No title to and ownership of the software is hereby900* transferred.901*902* The information in this software is subject to change without notice903* and should not be construed as a commitment by digital equipment904* corporation.905*906* Digital assumes no responsibility for the use or reliability of its907* software on equipment which is not supplied by digital.908*/909910/*911*++912* FACILITY:913*914* Alpha SRM Console Firmware915*916* MODULE DESCRIPTION:917*918* SMC37c669 Super I/O controller configuration routines.919*920* AUTHORS:921*922* Eric Rasmussen923*924* CREATION DATE:925*926* 28-Jan-1997927*928* MODIFICATION HISTORY:929*930* er 01-May-1997 Fixed pointer conversion errors in931* SMC37c669_get_device_config().932* er 28-Jan-1997 Initial version.933*934*--935*/936937#ifndef TRUE938#define TRUE 1939#endif940#ifndef FALSE941#define FALSE 0942#endif943944#define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) )945#define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) )946947/*948** Local storage for device configuration information.949**950** Since the SMC37c669 does not provide an explicit951** mechanism for enabling/disabling individual device952** functions, other than unmapping the device, local953** storage for device configuration information is954** allocated here for use in implementing our own955** function enable/disable scheme.956*/957static struct DEVICE_CONFIG {958unsigned int port1;959unsigned int port2;960int irq;961int drq;962} local_config [NUM_FUNCS];963964/*965** List of all possible addresses for the Super I/O chip966*/967static unsigned long SMC37c669_Addresses[] __initdata =968{9690x3F0UL, /* Primary address */9700x370UL, /* Secondary address */9710UL /* End of list */972};973974/*975** Global Pointer to the Super I/O device976*/977static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;978979/*980** IRQ Translation Table981**982** The IRQ translation table is a list of SMC37c669 device983** and standard ISA IRQs.984**985*/986static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata;987988/*989** The following definition is for the default IRQ990** translation table.991*/992static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]993__initdata =994{995{ SMC37c669_DEVICE_IRQ_A, -1 },996{ SMC37c669_DEVICE_IRQ_B, -1 },997{ SMC37c669_DEVICE_IRQ_C, 7 },998{ SMC37c669_DEVICE_IRQ_D, 6 },999{ SMC37c669_DEVICE_IRQ_E, 4 },1000{ SMC37c669_DEVICE_IRQ_F, 3 },1001{ SMC37c669_DEVICE_IRQ_H, -1 },1002{ -1, -1 } /* End of table */1003};10041005/*1006** The following definition is for the MONET (XP1000) IRQ1007** translation table.1008*/1009static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]1010__initdata =1011{1012{ SMC37c669_DEVICE_IRQ_A, -1 },1013{ SMC37c669_DEVICE_IRQ_B, -1 },1014{ SMC37c669_DEVICE_IRQ_C, 6 },1015{ SMC37c669_DEVICE_IRQ_D, 7 },1016{ SMC37c669_DEVICE_IRQ_E, 4 },1017{ SMC37c669_DEVICE_IRQ_F, 3 },1018{ SMC37c669_DEVICE_IRQ_H, -1 },1019{ -1, -1 } /* End of table */1020};10211022static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =1023{1024SMC37c669_default_irq_table,1025SMC37c669_monet_irq_table1026};10271028/*1029** DRQ Translation Table1030**1031** The DRQ translation table is a list of SMC37c669 device and1032** ISA DMA channels.1033**1034*/1035static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata;10361037/*1038** The following definition is the default DRQ1039** translation table.1040*/1041static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]1042__initdata =1043{1044{ SMC37c669_DEVICE_DRQ_A, 2 },1045{ SMC37c669_DEVICE_DRQ_B, 3 },1046{ SMC37c669_DEVICE_DRQ_C, -1 },1047{ -1, -1 } /* End of table */1048};10491050/*1051** Local Function Prototype Declarations1052*/10531054static unsigned int SMC37c669_is_device_enabled(1055unsigned int func1056);10571058#if 01059static unsigned int SMC37c669_get_device_config(1060unsigned int func,1061int *port,1062int *irq,1063int *drq1064);1065#endif10661067static void SMC37c669_config_mode(1068unsigned int enable1069);10701071static unsigned char SMC37c669_read_config(1072unsigned char index1073);10741075static void SMC37c669_write_config(1076unsigned char index,1077unsigned char data1078);10791080static void SMC37c669_init_local_config( void );10811082static struct DEVICE_CONFIG *SMC37c669_get_config(1083unsigned int func1084);10851086static int SMC37c669_xlate_irq(1087int irq1088);10891090static int SMC37c669_xlate_drq(1091int drq1092);10931094static __cacheline_aligned DEFINE_SPINLOCK(smc_lock);10951096/*1097**++1098** FUNCTIONAL DESCRIPTION:1099**1100** This function detects the presence of an SMC37c669 Super I/O1101** controller.1102**1103** FORMAL PARAMETERS:1104**1105** None1106**1107** RETURN VALUE:1108**1109** Returns a pointer to the device if found, otherwise,1110** the NULL pointer is returned.1111**1112** SIDE EFFECTS:1113**1114** None1115**1116**--1117*/1118SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )1119{1120int i;1121SMC37c669_DEVICE_ID_REGISTER id;11221123for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) {1124/*1125** Initialize the device pointer even though we don't yet know if1126** the controller is at this address. The support functions access1127** the controller through this device pointer so we need to set it1128** even when we are looking ...1129*/1130SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];1131/*1132** Enter configuration mode1133*/1134SMC37c669_config_mode( TRUE );1135/*1136** Read the device id1137*/1138id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );1139/*1140** Exit configuration mode1141*/1142SMC37c669_config_mode( FALSE );1143/*1144** Does the device id match? If so, assume we have found an1145** SMC37c669 controller at this address.1146*/1147if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {1148/*1149** Initialize the IRQ and DRQ translation tables.1150*/1151SMC37c669_irq_table = SMC37c669_irq_tables[ index ];1152SMC37c669_drq_table = SMC37c669_default_drq_table;1153/*1154** erfix1155**1156** If the platform can't use the IRQ and DRQ defaults set up in this1157** file, it should call a platform-specific external routine at this1158** point to reset the IRQ and DRQ translation table pointers to point1159** at the appropriate tables for the platform. If the defaults are1160** acceptable, then the external routine should do nothing.1161*/11621163/*1164** Put the chip back into configuration mode1165*/1166SMC37c669_config_mode( TRUE );1167/*1168** Initialize local storage for configuration information1169*/1170SMC37c669_init_local_config( );1171/*1172** Exit configuration mode1173*/1174SMC37c669_config_mode( FALSE );1175/*1176** SMC37c669 controller found, break out of search loop1177*/1178break;1179}1180else {1181/*1182** Otherwise, we did not find an SMC37c669 controller at this1183** address so set the device pointer to NULL.1184*/1185SMC37c669 = NULL;1186}1187}1188return SMC37c669;1189}119011911192/*1193**++1194** FUNCTIONAL DESCRIPTION:1195**1196** This function enables an SMC37c669 device function.1197**1198** FORMAL PARAMETERS:1199**1200** func:1201** Which device function to enable1202**1203** RETURN VALUE:1204**1205** Returns TRUE is the device function was enabled, otherwise, FALSE1206**1207** SIDE EFFECTS:1208**1209** {@description or none@}1210**1211** DESIGN:1212**1213** Enabling a device function in the SMC37c669 controller involves1214** setting all of its mappings (port, irq, drq ...). A local1215** "shadow" copy of the device configuration is kept so we can1216** just set each mapping to what the local copy says.1217**1218** This function ALWAYS updates the local shadow configuration of1219** the device function being enabled, even if the device is always1220** enabled. To avoid replication of code, functions such as1221** configure_device set up the local copy and then call this1222** function to the update the real device.1223**1224**--1225*/1226unsigned int __init SMC37c669_enable_device ( unsigned int func )1227{1228unsigned int ret_val = FALSE;1229/*1230** Put the device into configuration mode1231*/1232SMC37c669_config_mode( TRUE );1233switch ( func ) {1234case SERIAL_0:1235{1236SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;1237SMC37c669_SERIAL_IRQ_REGISTER irq;1238/*1239** Enable the serial 1 IRQ mapping1240*/1241irq.as_uchar =1242SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );12431244irq.by_field.uart1_irq =1245SMC37c669_RAW_DEVICE_IRQ(1246SMC37c669_xlate_irq( local_config[ func ].irq )1247);12481249SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );1250/*1251** Enable the serial 1 port base address mapping1252*/1253base_addr.as_uchar = 0;1254base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;12551256SMC37c669_write_config(1257SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,1258base_addr.as_uchar1259);1260ret_val = TRUE;1261break;1262}1263case SERIAL_1:1264{1265SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;1266SMC37c669_SERIAL_IRQ_REGISTER irq;1267/*1268** Enable the serial 2 IRQ mapping1269*/1270irq.as_uchar =1271SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );12721273irq.by_field.uart2_irq =1274SMC37c669_RAW_DEVICE_IRQ(1275SMC37c669_xlate_irq( local_config[ func ].irq )1276);12771278SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );1279/*1280** Enable the serial 2 port base address mapping1281*/1282base_addr.as_uchar = 0;1283base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;12841285SMC37c669_write_config(1286SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,1287base_addr.as_uchar1288);1289ret_val = TRUE;1290break;1291}1292case PARALLEL_0:1293{1294SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;1295SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;1296SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;1297/*1298** Enable the parallel port DMA channel mapping1299*/1300drq.as_uchar =1301SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );13021303drq.by_field.ppt_drq =1304SMC37c669_RAW_DEVICE_DRQ(1305SMC37c669_xlate_drq( local_config[ func ].drq )1306);13071308SMC37c669_write_config(1309SMC37c669_PARALLEL_FDC_DRQ_INDEX,1310drq.as_uchar1311);1312/*1313** Enable the parallel port IRQ mapping1314*/1315irq.as_uchar =1316SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );13171318irq.by_field.ppt_irq =1319SMC37c669_RAW_DEVICE_IRQ(1320SMC37c669_xlate_irq( local_config[ func ].irq )1321);13221323SMC37c669_write_config(1324SMC37c669_PARALLEL_FDC_IRQ_INDEX,1325irq.as_uchar1326);1327/*1328** Enable the parallel port base address mapping1329*/1330base_addr.as_uchar = 0;1331base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;13321333SMC37c669_write_config(1334SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,1335base_addr.as_uchar1336);1337ret_val = TRUE;1338break;1339}1340case FLOPPY_0:1341{1342SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;1343SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;1344SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;1345/*1346** Enable the floppy controller DMA channel mapping1347*/1348drq.as_uchar =1349SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );13501351drq.by_field.fdc_drq =1352SMC37c669_RAW_DEVICE_DRQ(1353SMC37c669_xlate_drq( local_config[ func ].drq )1354);13551356SMC37c669_write_config(1357SMC37c669_PARALLEL_FDC_DRQ_INDEX,1358drq.as_uchar1359);1360/*1361** Enable the floppy controller IRQ mapping1362*/1363irq.as_uchar =1364SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );13651366irq.by_field.fdc_irq =1367SMC37c669_RAW_DEVICE_IRQ(1368SMC37c669_xlate_irq( local_config[ func ].irq )1369);13701371SMC37c669_write_config(1372SMC37c669_PARALLEL_FDC_IRQ_INDEX,1373irq.as_uchar1374);1375/*1376** Enable the floppy controller base address mapping1377*/1378base_addr.as_uchar = 0;1379base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;13801381SMC37c669_write_config(1382SMC37c669_FDC_BASE_ADDRESS_INDEX,1383base_addr.as_uchar1384);1385ret_val = TRUE;1386break;1387}1388case IDE_0:1389{1390SMC37c669_IDE_ADDRESS_REGISTER ide_addr;1391/*1392** Enable the IDE alternate status base address mapping1393*/1394ide_addr.as_uchar = 0;1395ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;13961397SMC37c669_write_config(1398SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,1399ide_addr.as_uchar1400);1401/*1402** Enable the IDE controller base address mapping1403*/1404ide_addr.as_uchar = 0;1405ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;14061407SMC37c669_write_config(1408SMC37c669_IDE_BASE_ADDRESS_INDEX,1409ide_addr.as_uchar1410);1411ret_val = TRUE;1412break;1413}1414}1415/*1416** Exit configuration mode and return1417*/1418SMC37c669_config_mode( FALSE );14191420return ret_val;1421}142214231424/*1425**++1426** FUNCTIONAL DESCRIPTION:1427**1428** This function disables a device function within the1429** SMC37c669 Super I/O controller.1430**1431** FORMAL PARAMETERS:1432**1433** func:1434** Which function to disable1435**1436** RETURN VALUE:1437**1438** Return TRUE if the device function was disabled, otherwise, FALSE1439**1440** SIDE EFFECTS:1441**1442** {@description or none@}1443**1444** DESIGN:1445**1446** Disabling a function in the SMC37c669 device involves1447** disabling all the function's mappings (port, irq, drq ...).1448** A shadow copy of the device configuration is maintained1449** in local storage so we won't worry aboving saving the1450** current configuration information.1451**1452**--1453*/1454unsigned int __init SMC37c669_disable_device ( unsigned int func )1455{1456unsigned int ret_val = FALSE;14571458/*1459** Put the device into configuration mode1460*/1461SMC37c669_config_mode( TRUE );1462switch ( func ) {1463case SERIAL_0:1464{1465SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;1466SMC37c669_SERIAL_IRQ_REGISTER irq;1467/*1468** Disable the serial 1 IRQ mapping1469*/1470irq.as_uchar =1471SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );14721473irq.by_field.uart1_irq = 0;14741475SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );1476/*1477** Disable the serial 1 port base address mapping1478*/1479base_addr.as_uchar = 0;1480SMC37c669_write_config(1481SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,1482base_addr.as_uchar1483);1484ret_val = TRUE;1485break;1486}1487case SERIAL_1:1488{1489SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;1490SMC37c669_SERIAL_IRQ_REGISTER irq;1491/*1492** Disable the serial 2 IRQ mapping1493*/1494irq.as_uchar =1495SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );14961497irq.by_field.uart2_irq = 0;14981499SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );1500/*1501** Disable the serial 2 port base address mapping1502*/1503base_addr.as_uchar = 0;15041505SMC37c669_write_config(1506SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,1507base_addr.as_uchar1508);1509ret_val = TRUE;1510break;1511}1512case PARALLEL_0:1513{1514SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;1515SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;1516SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;1517/*1518** Disable the parallel port DMA channel mapping1519*/1520drq.as_uchar =1521SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );15221523drq.by_field.ppt_drq = 0;15241525SMC37c669_write_config(1526SMC37c669_PARALLEL_FDC_DRQ_INDEX,1527drq.as_uchar1528);1529/*1530** Disable the parallel port IRQ mapping1531*/1532irq.as_uchar =1533SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );15341535irq.by_field.ppt_irq = 0;15361537SMC37c669_write_config(1538SMC37c669_PARALLEL_FDC_IRQ_INDEX,1539irq.as_uchar1540);1541/*1542** Disable the parallel port base address mapping1543*/1544base_addr.as_uchar = 0;15451546SMC37c669_write_config(1547SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,1548base_addr.as_uchar1549);1550ret_val = TRUE;1551break;1552}1553case FLOPPY_0:1554{1555SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;1556SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;1557SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;1558/*1559** Disable the floppy controller DMA channel mapping1560*/1561drq.as_uchar =1562SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );15631564drq.by_field.fdc_drq = 0;15651566SMC37c669_write_config(1567SMC37c669_PARALLEL_FDC_DRQ_INDEX,1568drq.as_uchar1569);1570/*1571** Disable the floppy controller IRQ mapping1572*/1573irq.as_uchar =1574SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );15751576irq.by_field.fdc_irq = 0;15771578SMC37c669_write_config(1579SMC37c669_PARALLEL_FDC_IRQ_INDEX,1580irq.as_uchar1581);1582/*1583** Disable the floppy controller base address mapping1584*/1585base_addr.as_uchar = 0;15861587SMC37c669_write_config(1588SMC37c669_FDC_BASE_ADDRESS_INDEX,1589base_addr.as_uchar1590);1591ret_val = TRUE;1592break;1593}1594case IDE_0:1595{1596SMC37c669_IDE_ADDRESS_REGISTER ide_addr;1597/*1598** Disable the IDE alternate status base address mapping1599*/1600ide_addr.as_uchar = 0;16011602SMC37c669_write_config(1603SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,1604ide_addr.as_uchar1605);1606/*1607** Disable the IDE controller base address mapping1608*/1609ide_addr.as_uchar = 0;16101611SMC37c669_write_config(1612SMC37c669_IDE_BASE_ADDRESS_INDEX,1613ide_addr.as_uchar1614);1615ret_val = TRUE;1616break;1617}1618}1619/*1620** Exit configuration mode and return1621*/1622SMC37c669_config_mode( FALSE );16231624return ret_val;1625}162616271628/*1629**++1630** FUNCTIONAL DESCRIPTION:1631**1632** This function configures a device function within the1633** SMC37c669 Super I/O controller.1634**1635** FORMAL PARAMETERS:1636**1637** func:1638** Which device function1639**1640** port:1641** I/O port for the function to use1642**1643** irq:1644** IRQ for the device function to use1645**1646** drq:1647** DMA channel for the device function to use1648**1649** RETURN VALUE:1650**1651** Returns TRUE if the device function was configured,1652** otherwise, FALSE.1653**1654** SIDE EFFECTS:1655**1656** {@description or none@}1657**1658** DESIGN:1659**1660** If this function returns TRUE, the local shadow copy of1661** the configuration is also updated. If the device function1662** is currently disabled, only the local shadow copy is1663** updated and the actual device function will be updated1664** if/when it is enabled.1665**1666**--1667*/1668unsigned int __init SMC37c669_configure_device (1669unsigned int func,1670int port,1671int irq,1672int drq )1673{1674struct DEVICE_CONFIG *cp;16751676/*1677** Check for a valid configuration1678*/1679if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {1680/*1681** Configuration is valid, update the local shadow copy1682*/1683if ( ( drq & ~0xFF ) == 0 ) {1684cp->drq = drq;1685}1686if ( ( irq & ~0xFF ) == 0 ) {1687cp->irq = irq;1688}1689if ( ( port & ~0xFFFF ) == 0 ) {1690cp->port1 = port;1691}1692/*1693** If the device function is enabled, update the actual1694** device configuration.1695*/1696if ( SMC37c669_is_device_enabled( func ) ) {1697SMC37c669_enable_device( func );1698}1699return TRUE;1700}1701return FALSE;1702}170317041705/*1706**++1707** FUNCTIONAL DESCRIPTION:1708**1709** This function determines whether a device function1710** within the SMC37c669 controller is enabled.1711**1712** FORMAL PARAMETERS:1713**1714** func:1715** Which device function1716**1717** RETURN VALUE:1718**1719** Returns TRUE if the device function is enabled, otherwise, FALSE1720**1721** SIDE EFFECTS:1722**1723** {@description or none@}1724**1725** DESIGN:1726**1727** To check whether a device is enabled we will only look at1728** the port base address mapping. According to the SMC37c6691729** specification, all of the port base address mappings are1730** disabled if the addr<9:8> (bits <7:6> of the register) are1731** zero.1732**1733**--1734*/1735static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )1736{1737unsigned char base_addr = 0;1738unsigned int dev_ok = FALSE;1739unsigned int ret_val = FALSE;1740/*1741** Enter configuration mode1742*/1743SMC37c669_config_mode( TRUE );17441745switch ( func ) {1746case SERIAL_0:1747base_addr =1748SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );1749dev_ok = TRUE;1750break;1751case SERIAL_1:1752base_addr =1753SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );1754dev_ok = TRUE;1755break;1756case PARALLEL_0:1757base_addr =1758SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );1759dev_ok = TRUE;1760break;1761case FLOPPY_0:1762base_addr =1763SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );1764dev_ok = TRUE;1765break;1766case IDE_0:1767base_addr =1768SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );1769dev_ok = TRUE;1770break;1771}1772/*1773** If we have a valid device, check base_addr<7:6> to see if the1774** device is enabled (mapped).1775*/1776if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {1777/*1778** The mapping is not disabled, so assume that the function is1779** enabled.1780*/1781ret_val = TRUE;1782}1783/*1784** Exit configuration mode1785*/1786SMC37c669_config_mode( FALSE );17871788return ret_val;1789}179017911792#if 01793/*1794**++1795** FUNCTIONAL DESCRIPTION:1796**1797** This function retrieves the configuration information of a1798** device function within the SMC37c699 Super I/O controller.1799**1800** FORMAL PARAMETERS:1801**1802** func:1803** Which device function1804**1805** port:1806** I/O port returned1807**1808** irq:1809** IRQ returned1810**1811** drq:1812** DMA channel returned1813**1814** RETURN VALUE:1815**1816** Returns TRUE if the device configuration was successfully1817** retrieved, otherwise, FALSE.1818**1819** SIDE EFFECTS:1820**1821** The data pointed to by the port, irq, and drq parameters1822** my be modified even if the configuration is not successfully1823** retrieved.1824**1825** DESIGN:1826**1827** The device configuration is fetched from the local shadow1828** copy. Any unused parameters will be set to -1. Any1829** parameter which is not desired can specify the NULL1830** pointer.1831**1832**--1833*/1834static unsigned int __init SMC37c669_get_device_config (1835unsigned int func,1836int *port,1837int *irq,1838int *drq )1839{1840struct DEVICE_CONFIG *cp;1841unsigned int ret_val = FALSE;1842/*1843** Check for a valid device configuration1844*/1845if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {1846if ( drq != NULL ) {1847*drq = cp->drq;1848ret_val = TRUE;1849}1850if ( irq != NULL ) {1851*irq = cp->irq;1852ret_val = TRUE;1853}1854if ( port != NULL ) {1855*port = cp->port1;1856ret_val = TRUE;1857}1858}1859return ret_val;1860}1861#endif186218631864/*1865**++1866** FUNCTIONAL DESCRIPTION:1867**1868** This function displays the current state of the SMC37c6991869** Super I/O controller's device functions.1870**1871** FORMAL PARAMETERS:1872**1873** None1874**1875** RETURN VALUE:1876**1877** None1878**1879** SIDE EFFECTS:1880**1881** None1882**1883**--1884*/1885void __init SMC37c669_display_device_info ( void )1886{1887if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {1888printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n",1889local_config[ SERIAL_0 ].port1,1890local_config[ SERIAL_0 ].irq1891);1892}1893else {1894printk( " Serial 0: Disabled\n" );1895}18961897if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {1898printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n",1899local_config[ SERIAL_1 ].port1,1900local_config[ SERIAL_1 ].irq1901);1902}1903else {1904printk( " Serial 1: Disabled\n" );1905}19061907if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {1908printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n",1909local_config[ PARALLEL_0 ].port1,1910local_config[ PARALLEL_0 ].irq,1911local_config[ PARALLEL_0 ].drq1912);1913}1914else {1915printk( " Parallel: Disabled\n" );1916}19171918if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {1919printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",1920local_config[ FLOPPY_0 ].port1,1921local_config[ FLOPPY_0 ].irq,1922local_config[ FLOPPY_0 ].drq1923);1924}1925else {1926printk( " Floppy Ctrl: Disabled\n" );1927}19281929if ( SMC37c669_is_device_enabled( IDE_0 ) ) {1930printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n",1931local_config[ IDE_0 ].port1,1932local_config[ IDE_0 ].irq1933);1934}1935else {1936printk( " IDE 0: Disabled\n" );1937}1938}193919401941/*1942**++1943** FUNCTIONAL DESCRIPTION:1944**1945** This function puts the SMC37c669 Super I/O controller into,1946** and takes it out of, configuration mode.1947**1948** FORMAL PARAMETERS:1949**1950** enable:1951** TRUE to enter configuration mode, FALSE to exit.1952**1953** RETURN VALUE:1954**1955** None1956**1957** SIDE EFFECTS:1958**1959** The SMC37c669 controller may be left in configuration mode.1960**1961**--1962*/1963static void __init SMC37c669_config_mode(1964unsigned int enable )1965{1966if ( enable ) {1967/*1968** To enter configuration mode, two writes in succession to the index1969** port are required. If a write to another address or port occurs1970** between these two writes, the chip does not enter configuration1971** mode. Therefore, a spinlock is placed around the two writes to1972** guarantee that they complete uninterrupted.1973*/1974spin_lock(&smc_lock);1975wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );1976wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );1977spin_unlock(&smc_lock);1978}1979else {1980wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );1981}1982}19831984/*1985**++1986** FUNCTIONAL DESCRIPTION:1987**1988** This function reads an SMC37c669 Super I/O controller1989** configuration register. This function assumes that the1990** device is already in configuration mode.1991**1992** FORMAL PARAMETERS:1993**1994** index:1995** Index value of configuration register to read1996**1997** RETURN VALUE:1998**1999** Data read from configuration register2000**2001** SIDE EFFECTS:2002**2003** None2004**2005**--2006*/2007static unsigned char __init SMC37c669_read_config(2008unsigned char index )2009{2010wb(&SMC37c669->index_port, index);2011return rb(&SMC37c669->data_port);2012}20132014/*2015**++2016** FUNCTIONAL DESCRIPTION:2017**2018** This function writes an SMC37c669 Super I/O controller2019** configuration register. This function assumes that the2020** device is already in configuration mode.2021**2022** FORMAL PARAMETERS:2023**2024** index:2025** Index of configuration register to write2026**2027** data:2028** Data to be written2029**2030** RETURN VALUE:2031**2032** None2033**2034** SIDE EFFECTS:2035**2036** None2037**2038**--2039*/2040static void __init SMC37c669_write_config(2041unsigned char index,2042unsigned char data )2043{2044wb( &SMC37c669->index_port, index );2045wb( &SMC37c669->data_port, data );2046}204720482049/*2050**++2051** FUNCTIONAL DESCRIPTION:2052**2053** This function initializes the local device2054** configuration storage. This function assumes2055** that the device is already in configuration2056** mode.2057**2058** FORMAL PARAMETERS:2059**2060** None2061**2062** RETURN VALUE:2063**2064** None2065**2066** SIDE EFFECTS:2067**2068** Local storage for device configuration information2069** is initialized.2070**2071**--2072*/2073static void __init SMC37c669_init_local_config ( void )2074{2075SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;2076SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;2077SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;2078SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;2079SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;2080SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;2081SMC37c669_IDE_ADDRESS_REGISTER ide_base;2082SMC37c669_IDE_ADDRESS_REGISTER ide_alt;20832084/*2085** Get serial port 1 base address2086*/2087uart_base.as_uchar =2088SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );2089/*2090** Get IRQs for serial ports 1 & 22091*/2092uart_irqs.as_uchar =2093SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );2094/*2095** Store local configuration information for serial port 12096*/2097local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;2098local_config[SERIAL_0].irq =2099SMC37c669_xlate_irq(2100SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq )2101);2102/*2103** Get serial port 2 base address2104*/2105uart_base.as_uchar =2106SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );2107/*2108** Store local configuration information for serial port 22109*/2110local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;2111local_config[SERIAL_1].irq =2112SMC37c669_xlate_irq(2113SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq )2114);2115/*2116** Get parallel port base address2117*/2118ppt_base.as_uchar =2119SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );2120/*2121** Get IRQs for parallel port and floppy controller2122*/2123ppt_fdc_irqs.as_uchar =2124SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );2125/*2126** Get DRQs for parallel port and floppy controller2127*/2128ppt_fdc_drqs.as_uchar =2129SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );2130/*2131** Store local configuration information for parallel port2132*/2133local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;2134local_config[PARALLEL_0].irq =2135SMC37c669_xlate_irq(2136SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )2137);2138local_config[PARALLEL_0].drq =2139SMC37c669_xlate_drq(2140SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )2141);2142/*2143** Get floppy controller base address2144*/2145fdc_base.as_uchar =2146SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );2147/*2148** Store local configuration information for floppy controller2149*/2150local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;2151local_config[FLOPPY_0].irq =2152SMC37c669_xlate_irq(2153SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )2154);2155local_config[FLOPPY_0].drq =2156SMC37c669_xlate_drq(2157SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )2158);2159/*2160** Get IDE controller base address2161*/2162ide_base.as_uchar =2163SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );2164/*2165** Get IDE alternate status base address2166*/2167ide_alt.as_uchar =2168SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );2169/*2170** Store local configuration information for IDE controller2171*/2172local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;2173local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;2174local_config[IDE_0].irq = 14;2175}217621772178/*2179**++2180** FUNCTIONAL DESCRIPTION:2181**2182** This function returns a pointer to the local shadow2183** configuration of the requested device function.2184**2185** FORMAL PARAMETERS:2186**2187** func:2188** Which device function2189**2190** RETURN VALUE:2191**2192** Returns a pointer to the DEVICE_CONFIG structure for the2193** requested function, otherwise, NULL.2194**2195** SIDE EFFECTS:2196**2197** {@description or none@}2198**2199**--2200*/2201static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )2202{2203struct DEVICE_CONFIG *cp = NULL;22042205switch ( func ) {2206case SERIAL_0:2207cp = &local_config[ SERIAL_0 ];2208break;2209case SERIAL_1:2210cp = &local_config[ SERIAL_1 ];2211break;2212case PARALLEL_0:2213cp = &local_config[ PARALLEL_0 ];2214break;2215case FLOPPY_0:2216cp = &local_config[ FLOPPY_0 ];2217break;2218case IDE_0:2219cp = &local_config[ IDE_0 ];2220break;2221}2222return cp;2223}22242225/*2226**++2227** FUNCTIONAL DESCRIPTION:2228**2229** This function translates IRQs back and forth between ISA2230** IRQs and SMC37c669 device IRQs.2231**2232** FORMAL PARAMETERS:2233**2234** irq:2235** The IRQ to translate2236**2237** RETURN VALUE:2238**2239** Returns the translated IRQ, otherwise, returns -1.2240**2241** SIDE EFFECTS:2242**2243** {@description or none@}2244**2245**--2246*/2247static int __init SMC37c669_xlate_irq ( int irq )2248{2249int i, translated_irq = -1;22502251if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {2252/*2253** We are translating a device IRQ to an ISA IRQ2254*/2255for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {2256if ( irq == SMC37c669_irq_table[i].device_irq ) {2257translated_irq = SMC37c669_irq_table[i].isa_irq;2258break;2259}2260}2261}2262else {2263/*2264** We are translating an ISA IRQ to a device IRQ2265*/2266for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {2267if ( irq == SMC37c669_irq_table[i].isa_irq ) {2268translated_irq = SMC37c669_irq_table[i].device_irq;2269break;2270}2271}2272}2273return translated_irq;2274}227522762277/*2278**++2279** FUNCTIONAL DESCRIPTION:2280**2281** This function translates DMA channels back and forth between2282** ISA DMA channels and SMC37c669 device DMA channels.2283**2284** FORMAL PARAMETERS:2285**2286** drq:2287** The DMA channel to translate2288**2289** RETURN VALUE:2290**2291** Returns the translated DMA channel, otherwise, returns -12292**2293** SIDE EFFECTS:2294**2295** {@description or none@}2296**2297**--2298*/2299static int __init SMC37c669_xlate_drq ( int drq )2300{2301int i, translated_drq = -1;23022303if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {2304/*2305** We are translating a device DMA channel to an ISA DMA channel2306*/2307for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {2308if ( drq == SMC37c669_drq_table[i].device_drq ) {2309translated_drq = SMC37c669_drq_table[i].isa_drq;2310break;2311}2312}2313}2314else {2315/*2316** We are translating an ISA DMA channel to a device DMA channel2317*/2318for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {2319if ( drq == SMC37c669_drq_table[i].isa_drq ) {2320translated_drq = SMC37c669_drq_table[i].device_drq;2321break;2322}2323}2324}2325return translated_drq;2326}23272328#if 02329int __init smcc669_init ( void )2330{2331struct INODE *ip;23322333allocinode( smc_ddb.name, 1, &ip );2334ip->dva = &smc_ddb;2335ip->attr = ATTR$M_WRITE | ATTR$M_READ;2336ip->len[0] = 0x30;2337ip->misc = 0;2338INODE_UNLOCK( ip );23392340return msg_success;2341}23422343int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )2344{2345struct INODE *ip;2346/*2347** Allow multiple readers but only one writer. ip->misc keeps track2348** of the number of writers2349*/2350ip = fp->ip;2351INODE_LOCK( ip );2352if ( fp->mode & ATTR$M_WRITE ) {2353if ( ip->misc ) {2354INODE_UNLOCK( ip );2355return msg_failure; /* too many writers */2356}2357ip->misc++;2358}2359/*2360** Treat the information field as a byte offset2361*/2362*fp->offset = xtoi( info );2363INODE_UNLOCK( ip );23642365return msg_success;2366}23672368int __init smcc669_close( struct FILE *fp )2369{2370struct INODE *ip;23712372ip = fp->ip;2373if ( fp->mode & ATTR$M_WRITE ) {2374INODE_LOCK( ip );2375ip->misc--;2376INODE_UNLOCK( ip );2377}2378return msg_success;2379}23802381int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )2382{2383int i;2384int length;2385int nbytes;2386struct INODE *ip;23872388/*2389** Always access a byte at a time2390*/2391ip = fp->ip;2392length = size * number;2393nbytes = 0;23942395SMC37c669_config_mode( TRUE );2396for ( i = 0; i < length; i++ ) {2397if ( !inrange( *fp->offset, 0, ip->len[0] ) )2398break;2399*buf++ = SMC37c669_read_config( *fp->offset );2400*fp->offset += 1;2401nbytes++;2402}2403SMC37c669_config_mode( FALSE );2404return nbytes;2405}24062407int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )2408{2409int i;2410int length;2411int nbytes;2412struct INODE *ip;2413/*2414** Always access a byte at a time2415*/2416ip = fp->ip;2417length = size * number;2418nbytes = 0;24192420SMC37c669_config_mode( TRUE );2421for ( i = 0; i < length; i++ ) {2422if ( !inrange( *fp->offset, 0, ip->len[0] ) )2423break;2424SMC37c669_write_config( *fp->offset, *buf );2425*fp->offset += 1;2426buf++;2427nbytes++;2428}2429SMC37c669_config_mode( FALSE );2430return nbytes;2431}2432#endif24332434#if SMC_DEBUG2435static void __init2436SMC37c669_dump_registers(void)2437{2438int i;2439for (i = 0; i <= 0x29; i++)2440printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));2441}2442#endif2443/*+2444* ============================================================================2445* = SMC_init - SMC37c669 Super I/O controller initialization =2446* ============================================================================2447*2448* OVERVIEW:2449*2450* This routine configures and enables device functions on the2451* SMC37c669 Super I/O controller.2452*2453* FORM OF CALL:2454*2455* SMC_init( );2456*2457* RETURNS:2458*2459* Nothing2460*2461* ARGUMENTS:2462*2463* None2464*2465* SIDE EFFECTS:2466*2467* None2468*2469*/2470void __init SMC669_Init ( int index )2471{2472SMC37c669_CONFIG_REGS *SMC_base;2473unsigned long flags;24742475local_irq_save(flags);2476if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {2477#if SMC_DEBUG2478SMC37c669_config_mode( TRUE );2479SMC37c669_dump_registers( );2480SMC37c669_config_mode( FALSE );2481SMC37c669_display_device_info( );2482#endif2483SMC37c669_disable_device( SERIAL_0 );2484SMC37c669_configure_device(2485SERIAL_0,2486COM1_BASE,2487COM1_IRQ,2488-12489);2490SMC37c669_enable_device( SERIAL_0 );24912492SMC37c669_disable_device( SERIAL_1 );2493SMC37c669_configure_device(2494SERIAL_1,2495COM2_BASE,2496COM2_IRQ,2497-12498);2499SMC37c669_enable_device( SERIAL_1 );25002501SMC37c669_disable_device( PARALLEL_0 );2502SMC37c669_configure_device(2503PARALLEL_0,2504PARP_BASE,2505PARP_IRQ,2506PARP_DRQ2507);2508SMC37c669_enable_device( PARALLEL_0 );25092510SMC37c669_disable_device( FLOPPY_0 );2511SMC37c669_configure_device(2512FLOPPY_0,2513FDC_BASE,2514FDC_IRQ,2515FDC_DRQ2516);2517SMC37c669_enable_device( FLOPPY_0 );25182519/* Wake up sometimes forgotten floppy, especially on DP264. */2520outb(0xc, 0x3f2);25212522SMC37c669_disable_device( IDE_0 );25232524#if SMC_DEBUG2525SMC37c669_config_mode( TRUE );2526SMC37c669_dump_registers( );2527SMC37c669_config_mode( FALSE );2528SMC37c669_display_device_info( );2529#endif2530local_irq_restore(flags);2531printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",2532SMC_base );2533}2534else {2535local_irq_restore(flags);2536#if SMC_DEBUG2537printk( "No SMC37c669 Super I/O Controller found\n" );2538#endif2539}2540}254125422543