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