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