1/* 2 * SMC 37C669 initialization code 3 */ 4#include <linux/kernel.h> 5 6#include <linux/slab.h> 7#include <linux/mm.h> 8#include <linux/init.h> 9#include <linux/delay.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 unsigned int irq; 957 unsigned 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 = 0; 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 = 0; 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 unsigned int irq 1076); 1077 1078static int SMC37c669_xlate_drq( 1079 unsigned int drq 1080); 1081 1082 1083#define spinlock(x) 1084#define spinunlock(x) 1085 1086 1087/* 1088**++ 1089** FUNCTIONAL DESCRIPTION: 1090** 1091** This function detects the presence of an SMC37c669 Super I/O 1092** controller. 1093** 1094** FORMAL PARAMETERS: 1095** 1096** None 1097** 1098** RETURN VALUE: 1099** 1100** Returns a pointer to the device if found, otherwise, 1101** the NULL pointer is returned. 1102** 1103** SIDE EFFECTS: 1104** 1105** None 1106** 1107**-- 1108*/ 1109SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index ) 1110{ 1111 int i; 1112 SMC37c669_DEVICE_ID_REGISTER id; 1113 1114 for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) { 1115/* 1116** Initialize the device pointer even though we don't yet know if 1117** the controller is at this address. The support functions access 1118** the controller through this device pointer so we need to set it 1119** even when we are looking ... 1120*/ 1121 SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i]; 1122/* 1123** Enter configuration mode 1124*/ 1125 SMC37c669_config_mode( TRUE ); 1126/* 1127** Read the device id 1128*/ 1129 id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX ); 1130/* 1131** Exit configuration mode 1132*/ 1133 SMC37c669_config_mode( FALSE ); 1134/* 1135** Does the device id match? If so, assume we have found an 1136** SMC37c669 controller at this address. 1137*/ 1138 if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) { 1139/* 1140** Initialize the IRQ and DRQ translation tables. 1141*/ 1142 SMC37c669_irq_table = SMC37c669_irq_tables[ index ]; 1143 SMC37c669_drq_table = SMC37c669_default_drq_table; 1144/* 1145** erfix 1146** 1147** If the platform can't use the IRQ and DRQ defaults set up in this 1148** file, it should call a platform-specific external routine at this 1149** point to reset the IRQ and DRQ translation table pointers to point 1150** at the appropriate tables for the platform. If the defaults are 1151** acceptable, then the external routine should do nothing. 1152*/ 1153 1154/* 1155** Put the chip back into configuration mode 1156*/ 1157 SMC37c669_config_mode( TRUE ); 1158/* 1159** Initialize local storage for configuration information 1160*/ 1161 SMC37c669_init_local_config( ); 1162/* 1163** Exit configuration mode 1164*/ 1165 SMC37c669_config_mode( FALSE ); 1166/* 1167** SMC37c669 controller found, break out of search loop 1168*/ 1169 break; 1170 } 1171 else { 1172/* 1173** Otherwise, we did not find an SMC37c669 controller at this 1174** address so set the device pointer to NULL. 1175*/ 1176 SMC37c669 = NULL; 1177 } 1178 } 1179 return SMC37c669; 1180} 1181 1182 1183/* 1184**++ 1185** FUNCTIONAL DESCRIPTION: 1186** 1187** This function enables an SMC37c669 device function. 1188** 1189** FORMAL PARAMETERS: 1190** 1191** func: 1192** Which device function to enable 1193** 1194** RETURN VALUE: 1195** 1196** Returns TRUE is the device function was enabled, otherwise, FALSE 1197** 1198** SIDE EFFECTS: 1199** 1200** {@description or none@} 1201** 1202** DESIGN: 1203** 1204** Enabling a device function in the SMC37c669 controller involves 1205** setting all of its mappings (port, irq, drq ...). A local 1206** "shadow" copy of the device configuration is kept so we can 1207** just set each mapping to what the local copy says. 1208** 1209** This function ALWAYS updates the local shadow configuration of 1210** the device function being enabled, even if the device is always 1211** enabled. To avoid replication of code, functions such as 1212** configure_device set up the local copy and then call this 1213** function to the update the real device. 1214** 1215**-- 1216*/ 1217unsigned int __init SMC37c669_enable_device ( unsigned int func ) 1218{ 1219 unsigned int ret_val = FALSE; 1220/* 1221** Put the device into configuration mode 1222*/ 1223 SMC37c669_config_mode( TRUE ); 1224 switch ( func ) { 1225 case SERIAL_0: 1226 { 1227 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1228 SMC37c669_SERIAL_IRQ_REGISTER irq; 1229/* 1230** Enable the serial 1 IRQ mapping 1231*/ 1232 irq.as_uchar = 1233 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1234 1235 irq.by_field.uart1_irq = 1236 SMC37c669_RAW_DEVICE_IRQ( 1237 SMC37c669_xlate_irq( local_config[ func ].irq ) 1238 ); 1239 1240 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1241/* 1242** Enable the serial 1 port base address mapping 1243*/ 1244 base_addr.as_uchar = 0; 1245 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; 1246 1247 SMC37c669_write_config( 1248 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, 1249 base_addr.as_uchar 1250 ); 1251 ret_val = TRUE; 1252 break; 1253 } 1254 case SERIAL_1: 1255 { 1256 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1257 SMC37c669_SERIAL_IRQ_REGISTER irq; 1258/* 1259** Enable the serial 2 IRQ mapping 1260*/ 1261 irq.as_uchar = 1262 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1263 1264 irq.by_field.uart2_irq = 1265 SMC37c669_RAW_DEVICE_IRQ( 1266 SMC37c669_xlate_irq( local_config[ func ].irq ) 1267 ); 1268 1269 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1270/* 1271** Enable the serial 2 port base address mapping 1272*/ 1273 base_addr.as_uchar = 0; 1274 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; 1275 1276 SMC37c669_write_config( 1277 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, 1278 base_addr.as_uchar 1279 ); 1280 ret_val = TRUE; 1281 break; 1282 } 1283 case PARALLEL_0: 1284 { 1285 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; 1286 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1287 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1288/* 1289** Enable the parallel port DMA channel mapping 1290*/ 1291 drq.as_uchar = 1292 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1293 1294 drq.by_field.ppt_drq = 1295 SMC37c669_RAW_DEVICE_DRQ( 1296 SMC37c669_xlate_drq( local_config[ func ].drq ) 1297 ); 1298 1299 SMC37c669_write_config( 1300 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1301 drq.as_uchar 1302 ); 1303/* 1304** Enable the parallel port IRQ mapping 1305*/ 1306 irq.as_uchar = 1307 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1308 1309 irq.by_field.ppt_irq = 1310 SMC37c669_RAW_DEVICE_IRQ( 1311 SMC37c669_xlate_irq( local_config[ func ].irq ) 1312 ); 1313 1314 SMC37c669_write_config( 1315 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1316 irq.as_uchar 1317 ); 1318/* 1319** Enable the parallel port base address mapping 1320*/ 1321 base_addr.as_uchar = 0; 1322 base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2; 1323 1324 SMC37c669_write_config( 1325 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, 1326 base_addr.as_uchar 1327 ); 1328 ret_val = TRUE; 1329 break; 1330 } 1331 case FLOPPY_0: 1332 { 1333 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; 1334 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1335 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1336/* 1337** Enable the floppy controller DMA channel mapping 1338*/ 1339 drq.as_uchar = 1340 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1341 1342 drq.by_field.fdc_drq = 1343 SMC37c669_RAW_DEVICE_DRQ( 1344 SMC37c669_xlate_drq( local_config[ func ].drq ) 1345 ); 1346 1347 SMC37c669_write_config( 1348 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1349 drq.as_uchar 1350 ); 1351/* 1352** Enable the floppy controller IRQ mapping 1353*/ 1354 irq.as_uchar = 1355 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1356 1357 irq.by_field.fdc_irq = 1358 SMC37c669_RAW_DEVICE_IRQ( 1359 SMC37c669_xlate_irq( local_config[ func ].irq ) 1360 ); 1361 1362 SMC37c669_write_config( 1363 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1364 irq.as_uchar 1365 ); 1366/* 1367** Enable the floppy controller base address mapping 1368*/ 1369 base_addr.as_uchar = 0; 1370 base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; 1371 1372 SMC37c669_write_config( 1373 SMC37c669_FDC_BASE_ADDRESS_INDEX, 1374 base_addr.as_uchar 1375 ); 1376 ret_val = TRUE; 1377 break; 1378 } 1379 case IDE_0: 1380 { 1381 SMC37c669_IDE_ADDRESS_REGISTER ide_addr; 1382/* 1383** Enable the IDE alternate status base address mapping 1384*/ 1385 ide_addr.as_uchar = 0; 1386 ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4; 1387 1388 SMC37c669_write_config( 1389 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, 1390 ide_addr.as_uchar 1391 ); 1392/* 1393** Enable the IDE controller base address mapping 1394*/ 1395 ide_addr.as_uchar = 0; 1396 ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; 1397 1398 SMC37c669_write_config( 1399 SMC37c669_IDE_BASE_ADDRESS_INDEX, 1400 ide_addr.as_uchar 1401 ); 1402 ret_val = TRUE; 1403 break; 1404 } 1405 } 1406/* 1407** Exit configuration mode and return 1408*/ 1409 SMC37c669_config_mode( FALSE ); 1410 1411 return ret_val; 1412} 1413 1414 1415/* 1416**++ 1417** FUNCTIONAL DESCRIPTION: 1418** 1419** This function disables a device function within the 1420** SMC37c669 Super I/O controller. 1421** 1422** FORMAL PARAMETERS: 1423** 1424** func: 1425** Which function to disable 1426** 1427** RETURN VALUE: 1428** 1429** Return TRUE if the device function was disabled, otherwise, FALSE 1430** 1431** SIDE EFFECTS: 1432** 1433** {@description or none@} 1434** 1435** DESIGN: 1436** 1437** Disabling a function in the SMC37c669 device involves 1438** disabling all the function's mappings (port, irq, drq ...). 1439** A shadow copy of the device configuration is maintained 1440** in local storage so we won't worry aboving saving the 1441** current configuration information. 1442** 1443**-- 1444*/ 1445unsigned int __init SMC37c669_disable_device ( unsigned int func ) 1446{ 1447 unsigned int ret_val = FALSE; 1448 1449/* 1450** Put the device into configuration mode 1451*/ 1452 SMC37c669_config_mode( TRUE ); 1453 switch ( func ) { 1454 case SERIAL_0: 1455 { 1456 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1457 SMC37c669_SERIAL_IRQ_REGISTER irq; 1458/* 1459** Disable the serial 1 IRQ mapping 1460*/ 1461 irq.as_uchar = 1462 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1463 1464 irq.by_field.uart1_irq = 0; 1465 1466 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1467/* 1468** Disable the serial 1 port base address mapping 1469*/ 1470 base_addr.as_uchar = 0; 1471 SMC37c669_write_config( 1472 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, 1473 base_addr.as_uchar 1474 ); 1475 ret_val = TRUE; 1476 break; 1477 } 1478 case SERIAL_1: 1479 { 1480 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1481 SMC37c669_SERIAL_IRQ_REGISTER irq; 1482/* 1483** Disable the serial 2 IRQ mapping 1484*/ 1485 irq.as_uchar = 1486 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1487 1488 irq.by_field.uart2_irq = 0; 1489 1490 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1491/* 1492** Disable the serial 2 port base address mapping 1493*/ 1494 base_addr.as_uchar = 0; 1495 1496 SMC37c669_write_config( 1497 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, 1498 base_addr.as_uchar 1499 ); 1500 ret_val = TRUE; 1501 break; 1502 } 1503 case PARALLEL_0: 1504 { 1505 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; 1506 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1507 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1508/* 1509** Disable the parallel port DMA channel mapping 1510*/ 1511 drq.as_uchar = 1512 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1513 1514 drq.by_field.ppt_drq = 0; 1515 1516 SMC37c669_write_config( 1517 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1518 drq.as_uchar 1519 ); 1520/* 1521** Disable the parallel port IRQ mapping 1522*/ 1523 irq.as_uchar = 1524 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1525 1526 irq.by_field.ppt_irq = 0; 1527 1528 SMC37c669_write_config( 1529 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1530 irq.as_uchar 1531 ); 1532/* 1533** Disable the parallel port base address mapping 1534*/ 1535 base_addr.as_uchar = 0; 1536 1537 SMC37c669_write_config( 1538 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, 1539 base_addr.as_uchar 1540 ); 1541 ret_val = TRUE; 1542 break; 1543 } 1544 case FLOPPY_0: 1545 { 1546 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; 1547 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1548 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1549/* 1550** Disable the floppy controller DMA channel mapping 1551*/ 1552 drq.as_uchar = 1553 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1554 1555 drq.by_field.fdc_drq = 0; 1556 1557 SMC37c669_write_config( 1558 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1559 drq.as_uchar 1560 ); 1561/* 1562** Disable the floppy controller IRQ mapping 1563*/ 1564 irq.as_uchar = 1565 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1566 1567 irq.by_field.fdc_irq = 0; 1568 1569 SMC37c669_write_config( 1570 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1571 irq.as_uchar 1572 ); 1573/* 1574** Disable the floppy controller base address mapping 1575*/ 1576 base_addr.as_uchar = 0; 1577 1578 SMC37c669_write_config( 1579 SMC37c669_FDC_BASE_ADDRESS_INDEX, 1580 base_addr.as_uchar 1581 ); 1582 ret_val = TRUE; 1583 break; 1584 } 1585 case IDE_0: 1586 { 1587 SMC37c669_IDE_ADDRESS_REGISTER ide_addr; 1588/* 1589** Disable the IDE alternate status base address mapping 1590*/ 1591 ide_addr.as_uchar = 0; 1592 1593 SMC37c669_write_config( 1594 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, 1595 ide_addr.as_uchar 1596 ); 1597/* 1598** Disable the IDE controller base address mapping 1599*/ 1600 ide_addr.as_uchar = 0; 1601 1602 SMC37c669_write_config( 1603 SMC37c669_IDE_BASE_ADDRESS_INDEX, 1604 ide_addr.as_uchar 1605 ); 1606 ret_val = TRUE; 1607 break; 1608 } 1609 } 1610/* 1611** Exit configuration mode and return 1612*/ 1613 SMC37c669_config_mode( FALSE ); 1614 1615 return ret_val; 1616} 1617 1618 1619/* 1620**++ 1621** FUNCTIONAL DESCRIPTION: 1622** 1623** This function configures a device function within the 1624** SMC37c669 Super I/O controller. 1625** 1626** FORMAL PARAMETERS: 1627** 1628** func: 1629** Which device function 1630** 1631** port: 1632** I/O port for the function to use 1633** 1634** irq: 1635** IRQ for the device function to use 1636** 1637** drq: 1638** DMA channel for the device function to use 1639** 1640** RETURN VALUE: 1641** 1642** Returns TRUE if the device function was configured, 1643** otherwise, FALSE. 1644** 1645** SIDE EFFECTS: 1646** 1647** {@description or none@} 1648** 1649** DESIGN: 1650** 1651** If this function returns TRUE, the local shadow copy of 1652** the configuration is also updated. If the device function 1653** is currently disabled, only the local shadow copy is 1654** updated and the actual device function will be updated 1655** if/when it is enabled. 1656** 1657**-- 1658*/ 1659unsigned int __init SMC37c669_configure_device ( 1660 unsigned int func, 1661 int port, 1662 int irq, 1663 int drq ) 1664{ 1665 struct DEVICE_CONFIG *cp; 1666 1667/* 1668** Check for a valid configuration 1669*/ 1670 if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) { 1671/* 1672** Configuration is valid, update the local shadow copy 1673*/ 1674 if ( ( drq & ~0xFF ) == 0 ) { 1675 cp->drq = drq; 1676 } 1677 if ( ( irq & ~0xFF ) == 0 ) { 1678 cp->irq = irq; 1679 } 1680 if ( ( port & ~0xFFFF ) == 0 ) { 1681 cp->port1 = port; 1682 } 1683/* 1684** If the device function is enabled, update the actual 1685** device configuration. 1686*/ 1687 if ( SMC37c669_is_device_enabled( func ) ) { 1688 SMC37c669_enable_device( func ); 1689 } 1690 return TRUE; 1691 } 1692 return FALSE; 1693} 1694 1695 1696/* 1697**++ 1698** FUNCTIONAL DESCRIPTION: 1699** 1700** This function determines whether a device function 1701** within the SMC37c669 controller is enabled. 1702** 1703** FORMAL PARAMETERS: 1704** 1705** func: 1706** Which device function 1707** 1708** RETURN VALUE: 1709** 1710** Returns TRUE if the device function is enabled, otherwise, FALSE 1711** 1712** SIDE EFFECTS: 1713** 1714** {@description or none@} 1715** 1716** DESIGN: 1717** 1718** To check whether a device is enabled we will only look at 1719** the port base address mapping. According to the SMC37c669 1720** specification, all of the port base address mappings are 1721** disabled if the addr<9:8> (bits <7:6> of the register) are 1722** zero. 1723** 1724**-- 1725*/ 1726static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func ) 1727{ 1728 unsigned char base_addr = 0; 1729 unsigned int dev_ok = FALSE; 1730 unsigned int ret_val = FALSE; 1731/* 1732** Enter configuration mode 1733*/ 1734 SMC37c669_config_mode( TRUE ); 1735 1736 switch ( func ) { 1737 case SERIAL_0: 1738 base_addr = 1739 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); 1740 dev_ok = TRUE; 1741 break; 1742 case SERIAL_1: 1743 base_addr = 1744 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); 1745 dev_ok = TRUE; 1746 break; 1747 case PARALLEL_0: 1748 base_addr = 1749 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); 1750 dev_ok = TRUE; 1751 break; 1752 case FLOPPY_0: 1753 base_addr = 1754 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); 1755 dev_ok = TRUE; 1756 break; 1757 case IDE_0: 1758 base_addr = 1759 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); 1760 dev_ok = TRUE; 1761 break; 1762 } 1763/* 1764** If we have a valid device, check base_addr<7:6> to see if the 1765** device is enabled (mapped). 1766*/ 1767 if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) { 1768/* 1769** The mapping is not disabled, so assume that the function is 1770** enabled. 1771*/ 1772 ret_val = TRUE; 1773 } 1774/* 1775** Exit configuration mode 1776*/ 1777 SMC37c669_config_mode( FALSE ); 1778 1779 return ret_val; 1780} 1781 1782 1783 1784 1785/* 1786**++ 1787** FUNCTIONAL DESCRIPTION: 1788** 1789** This function displays the current state of the SMC37c699 1790** Super I/O controller's device functions. 1791** 1792** FORMAL PARAMETERS: 1793** 1794** None 1795** 1796** RETURN VALUE: 1797** 1798** None 1799** 1800** SIDE EFFECTS: 1801** 1802** None 1803** 1804**-- 1805*/ 1806void __init SMC37c669_display_device_info ( void ) 1807{ 1808 if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) { 1809 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n", 1810 local_config[ SERIAL_0 ].port1, 1811 local_config[ SERIAL_0 ].irq 1812 ); 1813 } 1814 else { 1815 printk( " Serial 0: Disabled\n" ); 1816 } 1817 1818 if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) { 1819 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n", 1820 local_config[ SERIAL_1 ].port1, 1821 local_config[ SERIAL_1 ].irq 1822 ); 1823 } 1824 else { 1825 printk( " Serial 1: Disabled\n" ); 1826 } 1827 1828 if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) { 1829 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n", 1830 local_config[ PARALLEL_0 ].port1, 1831 local_config[ PARALLEL_0 ].irq, 1832 local_config[ PARALLEL_0 ].drq 1833 ); 1834 } 1835 else { 1836 printk( " Parallel: Disabled\n" ); 1837 } 1838 1839 if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) { 1840 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n", 1841 local_config[ FLOPPY_0 ].port1, 1842 local_config[ FLOPPY_0 ].irq, 1843 local_config[ FLOPPY_0 ].drq 1844 ); 1845 } 1846 else { 1847 printk( " Floppy Ctrl: Disabled\n" ); 1848 } 1849 1850 if ( SMC37c669_is_device_enabled( IDE_0 ) ) { 1851 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n", 1852 local_config[ IDE_0 ].port1, 1853 local_config[ IDE_0 ].irq 1854 ); 1855 } 1856 else { 1857 printk( " IDE 0: Disabled\n" ); 1858 } 1859} 1860 1861 1862/* 1863**++ 1864** FUNCTIONAL DESCRIPTION: 1865** 1866** This function puts the SMC37c669 Super I/O controller into, 1867** and takes it out of, configuration mode. 1868** 1869** FORMAL PARAMETERS: 1870** 1871** enable: 1872** TRUE to enter configuration mode, FALSE to exit. 1873** 1874** RETURN VALUE: 1875** 1876** None 1877** 1878** SIDE EFFECTS: 1879** 1880** The SMC37c669 controller may be left in configuration mode. 1881** 1882**-- 1883*/ 1884static void __init SMC37c669_config_mode( 1885 unsigned int enable ) 1886{ 1887 if ( enable ) { 1888/* 1889** To enter configuration mode, two writes in succession to the index 1890** port are required. If a write to another address or port occurs 1891** between these two writes, the chip does not enter configuration 1892** mode. Therefore, a spinlock is placed around the two writes to 1893** guarantee that they complete uninterrupted. 1894*/ 1895 spinlock( &spl_atomic ); 1896 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); 1897 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); 1898 spinunlock( &spl_atomic ); 1899 } 1900 else { 1901 wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY ); 1902 } 1903} 1904 1905/* 1906**++ 1907** FUNCTIONAL DESCRIPTION: 1908** 1909** This function reads an SMC37c669 Super I/O controller 1910** configuration register. This function assumes that the 1911** device is already in configuration mode. 1912** 1913** FORMAL PARAMETERS: 1914** 1915** index: 1916** Index value of configuration register to read 1917** 1918** RETURN VALUE: 1919** 1920** Data read from configuration register 1921** 1922** SIDE EFFECTS: 1923** 1924** None 1925** 1926**-- 1927*/ 1928static unsigned char __init SMC37c669_read_config( 1929 unsigned char index ) 1930{ 1931 unsigned char data; 1932 1933 wb( &SMC37c669->index_port, index ); 1934 data = rb( &SMC37c669->data_port ); 1935 return data; 1936} 1937 1938/* 1939**++ 1940** FUNCTIONAL DESCRIPTION: 1941** 1942** This function writes an SMC37c669 Super I/O controller 1943** configuration register. This function assumes that the 1944** device is already in configuration mode. 1945** 1946** FORMAL PARAMETERS: 1947** 1948** index: 1949** Index of configuration register to write 1950** 1951** data: 1952** Data to be written 1953** 1954** RETURN VALUE: 1955** 1956** None 1957** 1958** SIDE EFFECTS: 1959** 1960** None 1961** 1962**-- 1963*/ 1964static void __init SMC37c669_write_config( 1965 unsigned char index, 1966 unsigned char data ) 1967{ 1968 wb( &SMC37c669->index_port, index ); 1969 wb( &SMC37c669->data_port, data ); 1970} 1971 1972 1973/* 1974**++ 1975** FUNCTIONAL DESCRIPTION: 1976** 1977** This function initializes the local device 1978** configuration storage. This function assumes 1979** that the device is already in configuration 1980** mode. 1981** 1982** FORMAL PARAMETERS: 1983** 1984** None 1985** 1986** RETURN VALUE: 1987** 1988** None 1989** 1990** SIDE EFFECTS: 1991** 1992** Local storage for device configuration information 1993** is initialized. 1994** 1995**-- 1996*/ 1997static void __init SMC37c669_init_local_config ( void ) 1998{ 1999 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base; 2000 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs; 2001 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base; 2002 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs; 2003 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs; 2004 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base; 2005 SMC37c669_IDE_ADDRESS_REGISTER ide_base; 2006 SMC37c669_IDE_ADDRESS_REGISTER ide_alt; 2007 2008/* 2009** Get serial port 1 base address 2010*/ 2011 uart_base.as_uchar = 2012 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); 2013/* 2014** Get IRQs for serial ports 1 & 2 2015*/ 2016 uart_irqs.as_uchar = 2017 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 2018/* 2019** Store local configuration information for serial port 1 2020*/ 2021 local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3; 2022 local_config[SERIAL_0].irq = 2023 SMC37c669_xlate_irq( 2024 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq ) 2025 ); 2026/* 2027** Get serial port 2 base address 2028*/ 2029 uart_base.as_uchar = 2030 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); 2031/* 2032** Store local configuration information for serial port 2 2033*/ 2034 local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3; 2035 local_config[SERIAL_1].irq = 2036 SMC37c669_xlate_irq( 2037 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq ) 2038 ); 2039/* 2040** Get parallel port base address 2041*/ 2042 ppt_base.as_uchar = 2043 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); 2044/* 2045** Get IRQs for parallel port and floppy controller 2046*/ 2047 ppt_fdc_irqs.as_uchar = 2048 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 2049/* 2050** Get DRQs for parallel port and floppy controller 2051*/ 2052 ppt_fdc_drqs.as_uchar = 2053 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 2054/* 2055** Store local configuration information for parallel port 2056*/ 2057 local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2; 2058 local_config[PARALLEL_0].irq = 2059 SMC37c669_xlate_irq( 2060 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq ) 2061 ); 2062 local_config[PARALLEL_0].drq = 2063 SMC37c669_xlate_drq( 2064 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq ) 2065 ); 2066/* 2067** Get floppy controller base address 2068*/ 2069 fdc_base.as_uchar = 2070 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); 2071/* 2072** Store local configuration information for floppy controller 2073*/ 2074 local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4; 2075 local_config[FLOPPY_0].irq = 2076 SMC37c669_xlate_irq( 2077 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq ) 2078 ); 2079 local_config[FLOPPY_0].drq = 2080 SMC37c669_xlate_drq( 2081 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq ) 2082 ); 2083/* 2084** Get IDE controller base address 2085*/ 2086 ide_base.as_uchar = 2087 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); 2088/* 2089** Get IDE alternate status base address 2090*/ 2091 ide_alt.as_uchar = 2092 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX ); 2093/* 2094** Store local configuration information for IDE controller 2095*/ 2096 local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4; 2097 local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4; 2098 local_config[IDE_0].irq = 14; 2099} 2100 2101 2102/* 2103**++ 2104** FUNCTIONAL DESCRIPTION: 2105** 2106** This function returns a pointer to the local shadow 2107** configuration of the requested device function. 2108** 2109** FORMAL PARAMETERS: 2110** 2111** func: 2112** Which device function 2113** 2114** RETURN VALUE: 2115** 2116** Returns a pointer to the DEVICE_CONFIG structure for the 2117** requested function, otherwise, NULL. 2118** 2119** SIDE EFFECTS: 2120** 2121** {@description or none@} 2122** 2123**-- 2124*/ 2125static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func ) 2126{ 2127 struct DEVICE_CONFIG *cp = NULL; 2128 2129 switch ( func ) { 2130 case SERIAL_0: 2131 cp = &local_config[ SERIAL_0 ]; 2132 break; 2133 case SERIAL_1: 2134 cp = &local_config[ SERIAL_1 ]; 2135 break; 2136 case PARALLEL_0: 2137 cp = &local_config[ PARALLEL_0 ]; 2138 break; 2139 case FLOPPY_0: 2140 cp = &local_config[ FLOPPY_0 ]; 2141 break; 2142 case IDE_0: 2143 cp = &local_config[ IDE_0 ]; 2144 break; 2145 } 2146 return cp; 2147} 2148 2149/* 2150**++ 2151** FUNCTIONAL DESCRIPTION: 2152** 2153** This function translates IRQs back and forth between ISA 2154** IRQs and SMC37c669 device IRQs. 2155** 2156** FORMAL PARAMETERS: 2157** 2158** irq: 2159** The IRQ to translate 2160** 2161** RETURN VALUE: 2162** 2163** Returns the translated IRQ, otherwise, returns -1. 2164** 2165** SIDE EFFECTS: 2166** 2167** {@description or none@} 2168** 2169**-- 2170*/ 2171static int __init SMC37c669_xlate_irq ( unsigned int irq ) 2172{ 2173 int i, translated_irq = -1; 2174 2175 if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) { 2176/* 2177** We are translating a device IRQ to an ISA IRQ 2178*/ 2179 for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) { 2180 if ( irq == SMC37c669_irq_table[i].device_irq ) { 2181 translated_irq = SMC37c669_irq_table[i].isa_irq; 2182 break; 2183 } 2184 } 2185 } 2186 else { 2187/* 2188** We are translating an ISA IRQ to a device IRQ 2189*/ 2190 for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) { 2191 if ( irq == SMC37c669_irq_table[i].isa_irq ) { 2192 translated_irq = SMC37c669_irq_table[i].device_irq; 2193 break; 2194 } 2195 } 2196 } 2197 return translated_irq; 2198} 2199 2200 2201/* 2202**++ 2203** FUNCTIONAL DESCRIPTION: 2204** 2205** This function translates DMA channels back and forth between 2206** ISA DMA channels and SMC37c669 device DMA channels. 2207** 2208** FORMAL PARAMETERS: 2209** 2210** drq: 2211** The DMA channel to translate 2212** 2213** RETURN VALUE: 2214** 2215** Returns the translated DMA channel, otherwise, returns -1 2216** 2217** SIDE EFFECTS: 2218** 2219** {@description or none@} 2220** 2221**-- 2222*/ 2223static int __init SMC37c669_xlate_drq ( unsigned int drq ) 2224{ 2225 int i, translated_drq = -1; 2226 2227 if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) { 2228/* 2229** We are translating a device DMA channel to an ISA DMA channel 2230*/ 2231 for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) { 2232 if ( drq == SMC37c669_drq_table[i].device_drq ) { 2233 translated_drq = SMC37c669_drq_table[i].isa_drq; 2234 break; 2235 } 2236 } 2237 } 2238 else { 2239/* 2240** We are translating an ISA DMA channel to a device DMA channel 2241*/ 2242 for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) { 2243 if ( drq == SMC37c669_drq_table[i].isa_drq ) { 2244 translated_drq = SMC37c669_drq_table[i].device_drq; 2245 break; 2246 } 2247 } 2248 } 2249 return translated_drq; 2250} 2251 2252 2253void __init 2254SMC37c669_dump_registers(void) 2255{ 2256 int i; 2257 for (i = 0; i <= 0x29; i++) 2258 printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i)); 2259} 2260/*+ 2261 * ============================================================================ 2262 * = SMC_init - SMC37c669 Super I/O controller initialization = 2263 * ============================================================================ 2264 * 2265 * OVERVIEW: 2266 * 2267 * This routine configures and enables device functions on the 2268 * SMC37c669 Super I/O controller. 2269 * 2270 * FORM OF CALL: 2271 * 2272 * SMC_init( ); 2273 * 2274 * RETURNS: 2275 * 2276 * 1 if the chip found, 0 otherwise 2277 * 2278 * ARGUMENTS: 2279 * 2280 * None 2281 * 2282 * SIDE EFFECTS: 2283 * 2284 * None 2285 * 2286 */ 2287int __init SMC669_Init ( int index ) 2288{ 2289 SMC37c669_CONFIG_REGS *SMC_base; 2290 unsigned long flags; 2291 2292 __save_and_cli(flags); 2293 if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) { 2294#if SMC_DEBUG 2295 SMC37c669_config_mode( TRUE ); 2296 SMC37c669_dump_registers( ); 2297 SMC37c669_config_mode( FALSE ); 2298 SMC37c669_display_device_info( ); 2299#endif 2300 SMC37c669_disable_device( SERIAL_0 ); 2301 SMC37c669_configure_device( 2302 SERIAL_0, 2303 COM1_BASE, 2304 COM1_IRQ, 2305 -1 2306 ); 2307 SMC37c669_enable_device( SERIAL_0 ); 2308 2309 SMC37c669_disable_device( SERIAL_1 ); 2310 SMC37c669_configure_device( 2311 SERIAL_1, 2312 COM2_BASE, 2313 COM2_IRQ, 2314 -1 2315 ); 2316 SMC37c669_enable_device( SERIAL_1 ); 2317 2318 SMC37c669_disable_device( PARALLEL_0 ); 2319 SMC37c669_configure_device( 2320 PARALLEL_0, 2321 PARP_BASE, 2322 PARP_IRQ, 2323 PARP_DRQ 2324 ); 2325 SMC37c669_enable_device( PARALLEL_0 ); 2326 2327 SMC37c669_disable_device( FLOPPY_0 ); 2328 SMC37c669_configure_device( 2329 FLOPPY_0, 2330 FDC_BASE, 2331 FDC_IRQ, 2332 FDC_DRQ 2333 ); 2334 SMC37c669_enable_device( FLOPPY_0 ); 2335 2336 /* Wake up sometimes forgotten floppy, especially on DP264. */ 2337 outb(0xc, 0x3f2); 2338 2339 SMC37c669_disable_device( IDE_0 ); 2340 2341#if SMC_DEBUG 2342 SMC37c669_config_mode( TRUE ); 2343 SMC37c669_dump_registers( ); 2344 SMC37c669_config_mode( FALSE ); 2345 SMC37c669_display_device_info( ); 2346#endif 2347 __restore_flags(flags); 2348 printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n", 2349 (unsigned long) SMC_base ); 2350 return 1; 2351 } 2352 else { 2353 __restore_flags(flags); 2354#if SMC_DEBUG 2355 printk( "No SMC37c669 Super I/O Controller found\n" ); 2356#endif 2357 return 0; 2358 } 2359} 2360