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