File Index
Files and directories
Sign in
FILE

smc37c669.c

File preview with syntax highlighting.

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