1 /* 2 * SMC 37C669 initialization code 3 */ 4 #include <linux/kernel.h> 5 6 #include <linux/slab.h> 7 #include <linux/mm.h> 8 #include <linux/init.h> 9 #include <linux/delay.h> 10 #include <linux/spinlock.h> 11 12 #include <asm/hwrpb.h> 13 #include <asm/io.h> 14 #include <asm/segment.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 #if 0 938 /* $INCLUDE_OPTIONS$ */ 939 #include "cp$inc:platform_io.h" 940 /* $INCLUDE_OPTIONS_END$ */ 941 #include "cp$src:common.h" 942 #include "cp$inc:prototypes.h" 943 #include "cp$src:kernel_def.h" 944 #include "cp$src:msg_def.h" 945 #include "cp$src:smcc669_def.h" 946 /* Platform-specific includes */ 947 #include "cp$src:platform.h" 948 #endif 949 950 #ifndef TRUE 951 #define TRUE 1 952 #endif 953 #ifndef FALSE 954 #define FALSE 0 955 #endif 956 957 #define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) ) 958 #define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) ) 959 960 /* 961 ** Local storage for device configuration information. 962 ** 963 ** Since the SMC37c669 does not provide an explicit 964 ** mechanism for enabling/disabling individual device 965 ** functions, other than unmapping the device, local 966 ** storage for device configuration information is 967 ** allocated here for use in implementing our own 968 ** function enable/disable scheme. 969 */ 970 static struct DEVICE_CONFIG { 971 unsigned int port1; 972 unsigned int port2; 973 int irq; 974 int drq; 975 } local_config [NUM_FUNCS]; 976 977 /* 978 ** List of all possible addresses for the Super I/O chip 979 */ 980 static unsigned long SMC37c669_Addresses[] __initdata = 981 { 982 0x3F0UL, /* Primary address */ 983 0x370UL, /* Secondary address */ 984 0UL /* End of list */ 985 }; 986 987 /* 988 ** Global Pointer to the Super I/O device 989 */ 990 static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL; 991 992 /* 993 ** IRQ Translation Table 994 ** 995 ** The IRQ translation table is a list of SMC37c669 device 996 ** and standard ISA IRQs. 997 ** 998 */ 999 static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata; 1000 1001 /* 1002 ** The following definition is for the default IRQ 1003 ** translation table. 1004 */ 1005 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[] 1006 __initdata = 1007 { 1008 { SMC37c669_DEVICE_IRQ_A, -1 }, 1009 { SMC37c669_DEVICE_IRQ_B, -1 }, 1010 { SMC37c669_DEVICE_IRQ_C, 7 }, 1011 { SMC37c669_DEVICE_IRQ_D, 6 }, 1012 { SMC37c669_DEVICE_IRQ_E, 4 }, 1013 { SMC37c669_DEVICE_IRQ_F, 3 }, 1014 { SMC37c669_DEVICE_IRQ_H, -1 }, 1015 { -1, -1 } /* End of table */ 1016 }; 1017 1018 /* 1019 ** The following definition is for the MONET (XP1000) IRQ 1020 ** translation table. 1021 */ 1022 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[] 1023 __initdata = 1024 { 1025 { SMC37c669_DEVICE_IRQ_A, -1 }, 1026 { SMC37c669_DEVICE_IRQ_B, -1 }, 1027 { SMC37c669_DEVICE_IRQ_C, 6 }, 1028 { SMC37c669_DEVICE_IRQ_D, 7 }, 1029 { SMC37c669_DEVICE_IRQ_E, 4 }, 1030 { SMC37c669_DEVICE_IRQ_F, 3 }, 1031 { SMC37c669_DEVICE_IRQ_H, -1 }, 1032 { -1, -1 } /* End of table */ 1033 }; 1034 1035 static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata = 1036 { 1037 SMC37c669_default_irq_table, 1038 SMC37c669_monet_irq_table 1039 }; 1040 1041 /* 1042 ** DRQ Translation Table 1043 ** 1044 ** The DRQ translation table is a list of SMC37c669 device and 1045 ** ISA DMA channels. 1046 ** 1047 */ 1048 static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata; 1049 1050 /* 1051 ** The following definition is the default DRQ 1052 ** translation table. 1053 */ 1054 static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[] 1055 __initdata = 1056 { 1057 { SMC37c669_DEVICE_DRQ_A, 2 }, 1058 { SMC37c669_DEVICE_DRQ_B, 3 }, 1059 { SMC37c669_DEVICE_DRQ_C, -1 }, 1060 { -1, -1 } /* End of table */ 1061 }; 1062 1063 /* 1064 ** Local Function Prototype Declarations 1065 */ 1066 1067 static unsigned int SMC37c669_is_device_enabled( 1068 unsigned int func 1069 ); 1070 1071 #if 0 1072 static unsigned int SMC37c669_get_device_config( 1073 unsigned int func, 1074 int *port, 1075 int *irq, 1076 int *drq 1077 ); 1078 #endif 1079 1080 static void SMC37c669_config_mode( 1081 unsigned int enable 1082 ); 1083 1084 static unsigned char SMC37c669_read_config( 1085 unsigned char index 1086 ); 1087 1088 static void SMC37c669_write_config( 1089 unsigned char index, 1090 unsigned char data 1091 ); 1092 1093 static void SMC37c669_init_local_config( void ); 1094 1095 static struct DEVICE_CONFIG *SMC37c669_get_config( 1096 unsigned int func 1097 ); 1098 1099 static int SMC37c669_xlate_irq( 1100 int irq 1101 ); 1102 1103 static int SMC37c669_xlate_drq( 1104 int drq 1105 ); 1106 1107 static __cacheline_aligned DEFINE_SPINLOCK(smc_lock); 1108 1109 /* 1110 **++ 1111 ** FUNCTIONAL DESCRIPTION: 1112 ** 1113 ** This function detects the presence of an SMC37c669 Super I/O 1114 ** controller. 1115 ** 1116 ** FORMAL PARAMETERS: 1117 ** 1118 ** None 1119 ** 1120 ** RETURN VALUE: 1121 ** 1122 ** Returns a pointer to the device if found, otherwise, 1123 ** the NULL pointer is returned. 1124 ** 1125 ** SIDE EFFECTS: 1126 ** 1127 ** None 1128 ** 1129 **-- 1130 */ 1131 SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index ) 1132 { 1133 int i; 1134 SMC37c669_DEVICE_ID_REGISTER id; 1135 1136 for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) { 1137 /* 1138 ** Initialize the device pointer even though we don't yet know if 1139 ** the controller is at this address. The support functions access 1140 ** the controller through this device pointer so we need to set it 1141 ** even when we are looking ... 1142 */ 1143 SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i]; 1144 /* 1145 ** Enter configuration mode 1146 */ 1147 SMC37c669_config_mode( TRUE ); 1148 /* 1149 ** Read the device id 1150 */ 1151 id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX ); 1152 /* 1153 ** Exit configuration mode 1154 */ 1155 SMC37c669_config_mode( FALSE ); 1156 /* 1157 ** Does the device id match? If so, assume we have found an 1158 ** SMC37c669 controller at this address. 1159 */ 1160 if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) { 1161 /* 1162 ** Initialize the IRQ and DRQ translation tables. 1163 */ 1164 SMC37c669_irq_table = SMC37c669_irq_tables[ index ]; 1165 SMC37c669_drq_table = SMC37c669_default_drq_table; 1166 /* 1167 ** erfix 1168 ** 1169 ** If the platform can't use the IRQ and DRQ defaults set up in this 1170 ** file, it should call a platform-specific external routine at this 1171 ** point to reset the IRQ and DRQ translation table pointers to point 1172 ** at the appropriate tables for the platform. If the defaults are 1173 ** acceptable, then the external routine should do nothing. 1174 */ 1175 1176 /* 1177 ** Put the chip back into configuration mode 1178 */ 1179 SMC37c669_config_mode( TRUE ); 1180 /* 1181 ** Initialize local storage for configuration information 1182 */ 1183 SMC37c669_init_local_config( ); 1184 /* 1185 ** Exit configuration mode 1186 */ 1187 SMC37c669_config_mode( FALSE ); 1188 /* 1189 ** SMC37c669 controller found, break out of search loop 1190 */ 1191 break; 1192 } 1193 else { 1194 /* 1195 ** Otherwise, we did not find an SMC37c669 controller at this 1196 ** address so set the device pointer to NULL. 1197 */ 1198 SMC37c669 = NULL; 1199 } 1200 } 1201 return SMC37c669; 1202 } 1203 1204 1205 /* 1206 **++ 1207 ** FUNCTIONAL DESCRIPTION: 1208 ** 1209 ** This function enables an SMC37c669 device function. 1210 ** 1211 ** FORMAL PARAMETERS: 1212 ** 1213 ** func: 1214 ** Which device function to enable 1215 ** 1216 ** RETURN VALUE: 1217 ** 1218 ** Returns TRUE is the device function was enabled, otherwise, FALSE 1219 ** 1220 ** SIDE EFFECTS: 1221 ** 1222 ** {@description or none@} 1223 ** 1224 ** DESIGN: 1225 ** 1226 ** Enabling a device function in the SMC37c669 controller involves 1227 ** setting all of its mappings (port, irq, drq ...). A local 1228 ** "shadow" copy of the device configuration is kept so we can 1229 ** just set each mapping to what the local copy says. 1230 ** 1231 ** This function ALWAYS updates the local shadow configuration of 1232 ** the device function being enabled, even if the device is always 1233 ** enabled. To avoid replication of code, functions such as 1234 ** configure_device set up the local copy and then call this 1235 ** function to the update the real device. 1236 ** 1237 **-- 1238 */ 1239 unsigned int __init SMC37c669_enable_device ( unsigned int func ) 1240 { 1241 unsigned int ret_val = FALSE; 1242 /* 1243 ** Put the device into configuration mode 1244 */ 1245 SMC37c669_config_mode( TRUE ); 1246 switch ( func ) { 1247 case SERIAL_0: 1248 { 1249 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1250 SMC37c669_SERIAL_IRQ_REGISTER irq; 1251 /* 1252 ** Enable the serial 1 IRQ mapping 1253 */ 1254 irq.as_uchar = 1255 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1256 1257 irq.by_field.uart1_irq = 1258 SMC37c669_RAW_DEVICE_IRQ( 1259 SMC37c669_xlate_irq( local_config[ func ].irq ) 1260 ); 1261 1262 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1263 /* 1264 ** Enable the serial 1 port base address mapping 1265 */ 1266 base_addr.as_uchar = 0; 1267 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; 1268 1269 SMC37c669_write_config( 1270 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, 1271 base_addr.as_uchar 1272 ); 1273 ret_val = TRUE; 1274 break; 1275 } 1276 case SERIAL_1: 1277 { 1278 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1279 SMC37c669_SERIAL_IRQ_REGISTER irq; 1280 /* 1281 ** Enable the serial 2 IRQ mapping 1282 */ 1283 irq.as_uchar = 1284 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1285 1286 irq.by_field.uart2_irq = 1287 SMC37c669_RAW_DEVICE_IRQ( 1288 SMC37c669_xlate_irq( local_config[ func ].irq ) 1289 ); 1290 1291 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1292 /* 1293 ** Enable the serial 2 port base address mapping 1294 */ 1295 base_addr.as_uchar = 0; 1296 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; 1297 1298 SMC37c669_write_config( 1299 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, 1300 base_addr.as_uchar 1301 ); 1302 ret_val = TRUE; 1303 break; 1304 } 1305 case PARALLEL_0: 1306 { 1307 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; 1308 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1309 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1310 /* 1311 ** Enable the parallel port DMA channel mapping 1312 */ 1313 drq.as_uchar = 1314 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1315 1316 drq.by_field.ppt_drq = 1317 SMC37c669_RAW_DEVICE_DRQ( 1318 SMC37c669_xlate_drq( local_config[ func ].drq ) 1319 ); 1320 1321 SMC37c669_write_config( 1322 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1323 drq.as_uchar 1324 ); 1325 /* 1326 ** Enable the parallel port IRQ mapping 1327 */ 1328 irq.as_uchar = 1329 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1330 1331 irq.by_field.ppt_irq = 1332 SMC37c669_RAW_DEVICE_IRQ( 1333 SMC37c669_xlate_irq( local_config[ func ].irq ) 1334 ); 1335 1336 SMC37c669_write_config( 1337 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1338 irq.as_uchar 1339 ); 1340 /* 1341 ** Enable the parallel port base address mapping 1342 */ 1343 base_addr.as_uchar = 0; 1344 base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2; 1345 1346 SMC37c669_write_config( 1347 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, 1348 base_addr.as_uchar 1349 ); 1350 ret_val = TRUE; 1351 break; 1352 } 1353 case FLOPPY_0: 1354 { 1355 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; 1356 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1357 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1358 /* 1359 ** Enable the floppy controller DMA channel mapping 1360 */ 1361 drq.as_uchar = 1362 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1363 1364 drq.by_field.fdc_drq = 1365 SMC37c669_RAW_DEVICE_DRQ( 1366 SMC37c669_xlate_drq( local_config[ func ].drq ) 1367 ); 1368 1369 SMC37c669_write_config( 1370 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1371 drq.as_uchar 1372 ); 1373 /* 1374 ** Enable the floppy controller IRQ mapping 1375 */ 1376 irq.as_uchar = 1377 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1378 1379 irq.by_field.fdc_irq = 1380 SMC37c669_RAW_DEVICE_IRQ( 1381 SMC37c669_xlate_irq( local_config[ func ].irq ) 1382 ); 1383 1384 SMC37c669_write_config( 1385 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1386 irq.as_uchar 1387 ); 1388 /* 1389 ** Enable the floppy controller base address mapping 1390 */ 1391 base_addr.as_uchar = 0; 1392 base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; 1393 1394 SMC37c669_write_config( 1395 SMC37c669_FDC_BASE_ADDRESS_INDEX, 1396 base_addr.as_uchar 1397 ); 1398 ret_val = TRUE; 1399 break; 1400 } 1401 case IDE_0: 1402 { 1403 SMC37c669_IDE_ADDRESS_REGISTER ide_addr; 1404 /* 1405 ** Enable the IDE alternate status base address mapping 1406 */ 1407 ide_addr.as_uchar = 0; 1408 ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4; 1409 1410 SMC37c669_write_config( 1411 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, 1412 ide_addr.as_uchar 1413 ); 1414 /* 1415 ** Enable the IDE controller base address mapping 1416 */ 1417 ide_addr.as_uchar = 0; 1418 ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; 1419 1420 SMC37c669_write_config( 1421 SMC37c669_IDE_BASE_ADDRESS_INDEX, 1422 ide_addr.as_uchar 1423 ); 1424 ret_val = TRUE; 1425 break; 1426 } 1427 } 1428 /* 1429 ** Exit configuration mode and return 1430 */ 1431 SMC37c669_config_mode( FALSE ); 1432 1433 return ret_val; 1434 } 1435 1436 1437 /* 1438 **++ 1439 ** FUNCTIONAL DESCRIPTION: 1440 ** 1441 ** This function disables a device function within the 1442 ** SMC37c669 Super I/O controller. 1443 ** 1444 ** FORMAL PARAMETERS: 1445 ** 1446 ** func: 1447 ** Which function to disable 1448 ** 1449 ** RETURN VALUE: 1450 ** 1451 ** Return TRUE if the device function was disabled, otherwise, FALSE 1452 ** 1453 ** SIDE EFFECTS: 1454 ** 1455 ** {@description or none@} 1456 ** 1457 ** DESIGN: 1458 ** 1459 ** Disabling a function in the SMC37c669 device involves 1460 ** disabling all the function's mappings (port, irq, drq ...). 1461 ** A shadow copy of the device configuration is maintained 1462 ** in local storage so we won't worry aboving saving the 1463 ** current configuration information. 1464 ** 1465 **-- 1466 */ 1467 unsigned int __init SMC37c669_disable_device ( unsigned int func ) 1468 { 1469 unsigned int ret_val = FALSE; 1470 1471 /* 1472 ** Put the device into configuration mode 1473 */ 1474 SMC37c669_config_mode( TRUE ); 1475 switch ( func ) { 1476 case SERIAL_0: 1477 { 1478 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1479 SMC37c669_SERIAL_IRQ_REGISTER irq; 1480 /* 1481 ** Disable the serial 1 IRQ mapping 1482 */ 1483 irq.as_uchar = 1484 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1485 1486 irq.by_field.uart1_irq = 0; 1487 1488 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1489 /* 1490 ** Disable the serial 1 port base address mapping 1491 */ 1492 base_addr.as_uchar = 0; 1493 SMC37c669_write_config( 1494 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, 1495 base_addr.as_uchar 1496 ); 1497 ret_val = TRUE; 1498 break; 1499 } 1500 case SERIAL_1: 1501 { 1502 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1503 SMC37c669_SERIAL_IRQ_REGISTER irq; 1504 /* 1505 ** Disable the serial 2 IRQ mapping 1506 */ 1507 irq.as_uchar = 1508 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1509 1510 irq.by_field.uart2_irq = 0; 1511 1512 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1513 /* 1514 ** Disable the serial 2 port base address mapping 1515 */ 1516 base_addr.as_uchar = 0; 1517 1518 SMC37c669_write_config( 1519 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, 1520 base_addr.as_uchar 1521 ); 1522 ret_val = TRUE; 1523 break; 1524 } 1525 case PARALLEL_0: 1526 { 1527 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; 1528 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1529 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1530 /* 1531 ** Disable the parallel port DMA channel mapping 1532 */ 1533 drq.as_uchar = 1534 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1535 1536 drq.by_field.ppt_drq = 0; 1537 1538 SMC37c669_write_config( 1539 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1540 drq.as_uchar 1541 ); 1542 /* 1543 ** Disable the parallel port IRQ mapping 1544 */ 1545 irq.as_uchar = 1546 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1547 1548 irq.by_field.ppt_irq = 0; 1549 1550 SMC37c669_write_config( 1551 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1552 irq.as_uchar 1553 ); 1554 /* 1555 ** Disable the parallel port base address mapping 1556 */ 1557 base_addr.as_uchar = 0; 1558 1559 SMC37c669_write_config( 1560 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, 1561 base_addr.as_uchar 1562 ); 1563 ret_val = TRUE; 1564 break; 1565 } 1566 case FLOPPY_0: 1567 { 1568 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; 1569 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1570 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1571 /* 1572 ** Disable the floppy controller DMA channel mapping 1573 */ 1574 drq.as_uchar = 1575 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1576 1577 drq.by_field.fdc_drq = 0; 1578 1579 SMC37c669_write_config( 1580 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1581 drq.as_uchar 1582 ); 1583 /* 1584 ** Disable the floppy controller IRQ mapping 1585 */ 1586 irq.as_uchar = 1587 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1588 1589 irq.by_field.fdc_irq = 0; 1590 1591 SMC37c669_write_config( 1592 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1593 irq.as_uchar 1594 ); 1595 /* 1596 ** Disable the floppy controller base address mapping 1597 */ 1598 base_addr.as_uchar = 0; 1599 1600 SMC37c669_write_config( 1601 SMC37c669_FDC_BASE_ADDRESS_INDEX, 1602 base_addr.as_uchar 1603 ); 1604 ret_val = TRUE; 1605 break; 1606 } 1607 case IDE_0: 1608 { 1609 SMC37c669_IDE_ADDRESS_REGISTER ide_addr; 1610 /* 1611 ** Disable the IDE alternate status base address mapping 1612 */ 1613 ide_addr.as_uchar = 0; 1614 1615 SMC37c669_write_config( 1616 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, 1617 ide_addr.as_uchar 1618 ); 1619 /* 1620 ** Disable the IDE controller base address mapping 1621 */ 1622 ide_addr.as_uchar = 0; 1623 1624 SMC37c669_write_config( 1625 SMC37c669_IDE_BASE_ADDRESS_INDEX, 1626 ide_addr.as_uchar 1627 ); 1628 ret_val = TRUE; 1629 break; 1630 } 1631 } 1632 /* 1633 ** Exit configuration mode and return 1634 */ 1635 SMC37c669_config_mode( FALSE ); 1636 1637 return ret_val; 1638 } 1639 1640 1641 /* 1642 **++ 1643 ** FUNCTIONAL DESCRIPTION: 1644 ** 1645 ** This function configures a device function within the 1646 ** SMC37c669 Super I/O controller. 1647 ** 1648 ** FORMAL PARAMETERS: 1649 ** 1650 ** func: 1651 ** Which device function 1652 ** 1653 ** port: 1654 ** I/O port for the function to use 1655 ** 1656 ** irq: 1657 ** IRQ for the device function to use 1658 ** 1659 ** drq: 1660 ** DMA channel for the device function to use 1661 ** 1662 ** RETURN VALUE: 1663 ** 1664 ** Returns TRUE if the device function was configured, 1665 ** otherwise, FALSE. 1666 ** 1667 ** SIDE EFFECTS: 1668 ** 1669 ** {@description or none@} 1670 ** 1671 ** DESIGN: 1672 ** 1673 ** If this function returns TRUE, the local shadow copy of 1674 ** the configuration is also updated. If the device function 1675 ** is currently disabled, only the local shadow copy is 1676 ** updated and the actual device function will be updated 1677 ** if/when it is enabled. 1678 ** 1679 **-- 1680 */ 1681 unsigned int __init SMC37c669_configure_device ( 1682 unsigned int func, 1683 int port, 1684 int irq, 1685 int drq ) 1686 { 1687 struct DEVICE_CONFIG *cp; 1688 1689 /* 1690 ** Check for a valid configuration 1691 */ 1692 if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) { 1693 /* 1694 ** Configuration is valid, update the local shadow copy 1695 */ 1696 if ( ( drq & ~0xFF ) == 0 ) { 1697 cp->drq = drq; 1698 } 1699 if ( ( irq & ~0xFF ) == 0 ) { 1700 cp->irq = irq; 1701 } 1702 if ( ( port & ~0xFFFF ) == 0 ) { 1703 cp->port1 = port; 1704 } 1705 /* 1706 ** If the device function is enabled, update the actual 1707 ** device configuration. 1708 */ 1709 if ( SMC37c669_is_device_enabled( func ) ) { 1710 SMC37c669_enable_device( func ); 1711 } 1712 return TRUE; 1713 } 1714 return FALSE; 1715 } 1716 1717 1718 /* 1719 **++ 1720 ** FUNCTIONAL DESCRIPTION: 1721 ** 1722 ** This function determines whether a device function 1723 ** within the SMC37c669 controller is enabled. 1724 ** 1725 ** FORMAL PARAMETERS: 1726 ** 1727 ** func: 1728 ** Which device function 1729 ** 1730 ** RETURN VALUE: 1731 ** 1732 ** Returns TRUE if the device function is enabled, otherwise, FALSE 1733 ** 1734 ** SIDE EFFECTS: 1735 ** 1736 ** {@description or none@} 1737 ** 1738 ** DESIGN: 1739 ** 1740 ** To check whether a device is enabled we will only look at 1741 ** the port base address mapping. According to the SMC37c669 1742 ** specification, all of the port base address mappings are 1743 ** disabled if the addr<9:8> (bits <7:6> of the register) are 1744 ** zero. 1745 ** 1746 **-- 1747 */ 1748 static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func ) 1749 { 1750 unsigned char base_addr = 0; 1751 unsigned int dev_ok = FALSE; 1752 unsigned int ret_val = FALSE; 1753 /* 1754 ** Enter configuration mode 1755 */ 1756 SMC37c669_config_mode( TRUE ); 1757 1758 switch ( func ) { 1759 case SERIAL_0: 1760 base_addr = 1761 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); 1762 dev_ok = TRUE; 1763 break; 1764 case SERIAL_1: 1765 base_addr = 1766 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); 1767 dev_ok = TRUE; 1768 break; 1769 case PARALLEL_0: 1770 base_addr = 1771 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); 1772 dev_ok = TRUE; 1773 break; 1774 case FLOPPY_0: 1775 base_addr = 1776 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); 1777 dev_ok = TRUE; 1778 break; 1779 case IDE_0: 1780 base_addr = 1781 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); 1782 dev_ok = TRUE; 1783 break; 1784 } 1785 /* 1786 ** If we have a valid device, check base_addr<7:6> to see if the 1787 ** device is enabled (mapped). 1788 */ 1789 if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) { 1790 /* 1791 ** The mapping is not disabled, so assume that the function is 1792 ** enabled. 1793 */ 1794 ret_val = TRUE; 1795 } 1796 /* 1797 ** Exit configuration mode 1798 */ 1799 SMC37c669_config_mode( FALSE ); 1800 1801 return ret_val; 1802 } 1803 1804 1805 #if 0 1806 /* 1807 **++ 1808 ** FUNCTIONAL DESCRIPTION: 1809 ** 1810 ** This function retrieves the configuration information of a 1811 ** device function within the SMC37c699 Super I/O controller. 1812 ** 1813 ** FORMAL PARAMETERS: 1814 ** 1815 ** func: 1816 ** Which device function 1817 ** 1818 ** port: 1819 ** I/O port returned 1820 ** 1821 ** irq: 1822 ** IRQ returned 1823 ** 1824 ** drq: 1825 ** DMA channel returned 1826 ** 1827 ** RETURN VALUE: 1828 ** 1829 ** Returns TRUE if the device configuration was successfully 1830 ** retrieved, otherwise, FALSE. 1831 ** 1832 ** SIDE EFFECTS: 1833 ** 1834 ** The data pointed to by the port, irq, and drq parameters 1835 ** my be modified even if the configuration is not successfully 1836 ** retrieved. 1837 ** 1838 ** DESIGN: 1839 ** 1840 ** The device configuration is fetched from the local shadow 1841 ** copy. Any unused parameters will be set to -1. Any 1842 ** parameter which is not desired can specify the NULL 1843 ** pointer. 1844 ** 1845 **-- 1846 */ 1847 static unsigned int __init SMC37c669_get_device_config ( 1848 unsigned int func, 1849 int *port, 1850 int *irq, 1851 int *drq ) 1852 { 1853 struct DEVICE_CONFIG *cp; 1854 unsigned int ret_val = FALSE; 1855 /* 1856 ** Check for a valid device configuration 1857 */ 1858 if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) { 1859 if ( drq != NULL ) { 1860 *drq = cp->drq; 1861 ret_val = TRUE; 1862 } 1863 if ( irq != NULL ) { 1864 *irq = cp->irq; 1865 ret_val = TRUE; 1866 } 1867 if ( port != NULL ) { 1868 *port = cp->port1; 1869 ret_val = TRUE; 1870 } 1871 } 1872 return ret_val; 1873 } 1874 #endif 1875 1876 1877 /* 1878 **++ 1879 ** FUNCTIONAL DESCRIPTION: 1880 ** 1881 ** This function displays the current state of the SMC37c699 1882 ** Super I/O controller's device functions. 1883 ** 1884 ** FORMAL PARAMETERS: 1885 ** 1886 ** None 1887 ** 1888 ** RETURN VALUE: 1889 ** 1890 ** None 1891 ** 1892 ** SIDE EFFECTS: 1893 ** 1894 ** None 1895 ** 1896 **-- 1897 */ 1898 void __init SMC37c669_display_device_info ( void ) 1899 { 1900 if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) { 1901 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n", 1902 local_config[ SERIAL_0 ].port1, 1903 local_config[ SERIAL_0 ].irq 1904 ); 1905 } 1906 else { 1907 printk( " Serial 0: Disabled\n" ); 1908 } 1909 1910 if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) { 1911 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n", 1912 local_config[ SERIAL_1 ].port1, 1913 local_config[ SERIAL_1 ].irq 1914 ); 1915 } 1916 else { 1917 printk( " Serial 1: Disabled\n" ); 1918 } 1919 1920 if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) { 1921 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n", 1922 local_config[ PARALLEL_0 ].port1, 1923 local_config[ PARALLEL_0 ].irq, 1924 local_config[ PARALLEL_0 ].drq 1925 ); 1926 } 1927 else { 1928 printk( " Parallel: Disabled\n" ); 1929 } 1930 1931 if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) { 1932 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n", 1933 local_config[ FLOPPY_0 ].port1, 1934 local_config[ FLOPPY_0 ].irq, 1935 local_config[ FLOPPY_0 ].drq 1936 ); 1937 } 1938 else { 1939 printk( " Floppy Ctrl: Disabled\n" ); 1940 } 1941 1942 if ( SMC37c669_is_device_enabled( IDE_0 ) ) { 1943 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n", 1944 local_config[ IDE_0 ].port1, 1945 local_config[ IDE_0 ].irq 1946 ); 1947 } 1948 else { 1949 printk( " IDE 0: Disabled\n" ); 1950 } 1951 } 1952 1953 1954 /* 1955 **++ 1956 ** FUNCTIONAL DESCRIPTION: 1957 ** 1958 ** This function puts the SMC37c669 Super I/O controller into, 1959 ** and takes it out of, configuration mode. 1960 ** 1961 ** FORMAL PARAMETERS: 1962 ** 1963 ** enable: 1964 ** TRUE to enter configuration mode, FALSE to exit. 1965 ** 1966 ** RETURN VALUE: 1967 ** 1968 ** None 1969 ** 1970 ** SIDE EFFECTS: 1971 ** 1972 ** The SMC37c669 controller may be left in configuration mode. 1973 ** 1974 **-- 1975 */ 1976 static void __init SMC37c669_config_mode( 1977 unsigned int enable ) 1978 { 1979 if ( enable ) { 1980 /* 1981 ** To enter configuration mode, two writes in succession to the index 1982 ** port are required. If a write to another address or port occurs 1983 ** between these two writes, the chip does not enter configuration 1984 ** mode. Therefore, a spinlock is placed around the two writes to 1985 ** guarantee that they complete uninterrupted. 1986 */ 1987 spin_lock(&smc_lock); 1988 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); 1989 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); 1990 spin_unlock(&smc_lock); 1991 } 1992 else { 1993 wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY ); 1994 } 1995 } 1996 1997 /* 1998 **++ 1999 ** FUNCTIONAL DESCRIPTION: 2000 ** 2001 ** This function reads an SMC37c669 Super I/O controller 2002 ** configuration register. This function assumes that the 2003 ** device is already in configuration mode. 2004 ** 2005 ** FORMAL PARAMETERS: 2006 ** 2007 ** index: 2008 ** Index value of configuration register to read 2009 ** 2010 ** RETURN VALUE: 2011 ** 2012 ** Data read from configuration register 2013 ** 2014 ** SIDE EFFECTS: 2015 ** 2016 ** None 2017 ** 2018 **-- 2019 */ 2020 static unsigned char __init SMC37c669_read_config( 2021 unsigned char index ) 2022 { 2023 unsigned char data; 2024 2025 wb( &SMC37c669->index_port, index ); 2026 data = rb( &SMC37c669->data_port ); 2027 return data; 2028 } 2029 2030 /* 2031 **++ 2032 ** FUNCTIONAL DESCRIPTION: 2033 ** 2034 ** This function writes an SMC37c669 Super I/O controller 2035 ** configuration register. This function assumes that the 2036 ** device is already in configuration mode. 2037 ** 2038 ** FORMAL PARAMETERS: 2039 ** 2040 ** index: 2041 ** Index of configuration register to write 2042 ** 2043 ** data: 2044 ** Data to be written 2045 ** 2046 ** RETURN VALUE: 2047 ** 2048 ** None 2049 ** 2050 ** SIDE EFFECTS: 2051 ** 2052 ** None 2053 ** 2054 **-- 2055 */ 2056 static void __init SMC37c669_write_config( 2057 unsigned char index, 2058 unsigned char data ) 2059 { 2060 wb( &SMC37c669->index_port, index ); 2061 wb( &SMC37c669->data_port, data ); 2062 } 2063 2064 2065 /* 2066 **++ 2067 ** FUNCTIONAL DESCRIPTION: 2068 ** 2069 ** This function initializes the local device 2070 ** configuration storage. This function assumes 2071 ** that the device is already in configuration 2072 ** mode. 2073 ** 2074 ** FORMAL PARAMETERS: 2075 ** 2076 ** None 2077 ** 2078 ** RETURN VALUE: 2079 ** 2080 ** None 2081 ** 2082 ** SIDE EFFECTS: 2083 ** 2084 ** Local storage for device configuration information 2085 ** is initialized. 2086 ** 2087 **-- 2088 */ 2089 static void __init SMC37c669_init_local_config ( void ) 2090 { 2091 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base; 2092 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs; 2093 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base; 2094 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs; 2095 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs; 2096 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base; 2097 SMC37c669_IDE_ADDRESS_REGISTER ide_base; 2098 SMC37c669_IDE_ADDRESS_REGISTER ide_alt; 2099 2100 /* 2101 ** Get serial port 1 base address 2102 */ 2103 uart_base.as_uchar = 2104 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); 2105 /* 2106 ** Get IRQs for serial ports 1 & 2 2107 */ 2108 uart_irqs.as_uchar = 2109 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 2110 /* 2111 ** Store local configuration information for serial port 1 2112 */ 2113 local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3; 2114 local_config[SERIAL_0].irq = 2115 SMC37c669_xlate_irq( 2116 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq ) 2117 ); 2118 /* 2119 ** Get serial port 2 base address 2120 */ 2121 uart_base.as_uchar = 2122 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); 2123 /* 2124 ** Store local configuration information for serial port 2 2125 */ 2126 local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3; 2127 local_config[SERIAL_1].irq = 2128 SMC37c669_xlate_irq( 2129 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq ) 2130 ); 2131 /* 2132 ** Get parallel port base address 2133 */ 2134 ppt_base.as_uchar = 2135 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); 2136 /* 2137 ** Get IRQs for parallel port and floppy controller 2138 */ 2139 ppt_fdc_irqs.as_uchar = 2140 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 2141 /* 2142 ** Get DRQs for parallel port and floppy controller 2143 */ 2144 ppt_fdc_drqs.as_uchar = 2145 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 2146 /* 2147 ** Store local configuration information for parallel port 2148 */ 2149 local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2; 2150 local_config[PARALLEL_0].irq = 2151 SMC37c669_xlate_irq( 2152 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq ) 2153 ); 2154 local_config[PARALLEL_0].drq = 2155 SMC37c669_xlate_drq( 2156 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq ) 2157 ); 2158 /* 2159 ** Get floppy controller base address 2160 */ 2161 fdc_base.as_uchar = 2162 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); 2163 /* 2164 ** Store local configuration information for floppy controller 2165 */ 2166 local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4; 2167 local_config[FLOPPY_0].irq = 2168 SMC37c669_xlate_irq( 2169 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq ) 2170 ); 2171 local_config[FLOPPY_0].drq = 2172 SMC37c669_xlate_drq( 2173 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq ) 2174 ); 2175 /* 2176 ** Get IDE controller base address 2177 */ 2178 ide_base.as_uchar = 2179 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); 2180 /* 2181 ** Get IDE alternate status base address 2182 */ 2183 ide_alt.as_uchar = 2184 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX ); 2185 /* 2186 ** Store local configuration information for IDE controller 2187 */ 2188 local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4; 2189 local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4; 2190 local_config[IDE_0].irq = 14; 2191 } 2192 2193 2194 /* 2195 **++ 2196 ** FUNCTIONAL DESCRIPTION: 2197 ** 2198 ** This function returns a pointer to the local shadow 2199 ** configuration of the requested device function. 2200 ** 2201 ** FORMAL PARAMETERS: 2202 ** 2203 ** func: 2204 ** Which device function 2205 ** 2206 ** RETURN VALUE: 2207 ** 2208 ** Returns a pointer to the DEVICE_CONFIG structure for the 2209 ** requested function, otherwise, NULL. 2210 ** 2211 ** SIDE EFFECTS: 2212 ** 2213 ** {@description or none@} 2214 ** 2215 **-- 2216 */ 2217 static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func ) 2218 { 2219 struct DEVICE_CONFIG *cp = NULL; 2220 2221 switch ( func ) { 2222 case SERIAL_0: 2223 cp = &local_config[ SERIAL_0 ]; 2224 break; 2225 case SERIAL_1: 2226 cp = &local_config[ SERIAL_1 ]; 2227 break; 2228 case PARALLEL_0: 2229 cp = &local_config[ PARALLEL_0 ]; 2230 break; 2231 case FLOPPY_0: 2232 cp = &local_config[ FLOPPY_0 ]; 2233 break; 2234 case IDE_0: 2235 cp = &local_config[ IDE_0 ]; 2236 break; 2237 } 2238 return cp; 2239 } 2240 2241 /* 2242 **++ 2243 ** FUNCTIONAL DESCRIPTION: 2244 ** 2245 ** This function translates IRQs back and forth between ISA 2246 ** IRQs and SMC37c669 device IRQs. 2247 ** 2248 ** FORMAL PARAMETERS: 2249 ** 2250 ** irq: 2251 ** The IRQ to translate 2252 ** 2253 ** RETURN VALUE: 2254 ** 2255 ** Returns the translated IRQ, otherwise, returns -1. 2256 ** 2257 ** SIDE EFFECTS: 2258 ** 2259 ** {@description or none@} 2260 ** 2261 **-- 2262 */ 2263 static int __init SMC37c669_xlate_irq ( int irq ) 2264 { 2265 int i, translated_irq = -1; 2266 2267 if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) { 2268 /* 2269 ** We are translating a device IRQ to an ISA IRQ 2270 */ 2271 for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) { 2272 if ( irq == SMC37c669_irq_table[i].device_irq ) { 2273 translated_irq = SMC37c669_irq_table[i].isa_irq; 2274 break; 2275 } 2276 } 2277 } 2278 else { 2279 /* 2280 ** We are translating an ISA IRQ to a device IRQ 2281 */ 2282 for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) { 2283 if ( irq == SMC37c669_irq_table[i].isa_irq ) { 2284 translated_irq = SMC37c669_irq_table[i].device_irq; 2285 break; 2286 } 2287 } 2288 } 2289 return translated_irq; 2290 } 2291 2292 2293 /* 2294 **++ 2295 ** FUNCTIONAL DESCRIPTION: 2296 ** 2297 ** This function translates DMA channels back and forth between 2298 ** ISA DMA channels and SMC37c669 device DMA channels. 2299 ** 2300 ** FORMAL PARAMETERS: 2301 ** 2302 ** drq: 2303 ** The DMA channel to translate 2304 ** 2305 ** RETURN VALUE: 2306 ** 2307 ** Returns the translated DMA channel, otherwise, returns -1 2308 ** 2309 ** SIDE EFFECTS: 2310 ** 2311 ** {@description or none@} 2312 ** 2313 **-- 2314 */ 2315 static int __init SMC37c669_xlate_drq ( int drq ) 2316 { 2317 int i, translated_drq = -1; 2318 2319 if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) { 2320 /* 2321 ** We are translating a device DMA channel to an ISA DMA channel 2322 */ 2323 for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) { 2324 if ( drq == SMC37c669_drq_table[i].device_drq ) { 2325 translated_drq = SMC37c669_drq_table[i].isa_drq; 2326 break; 2327 } 2328 } 2329 } 2330 else { 2331 /* 2332 ** We are translating an ISA DMA channel to a device DMA channel 2333 */ 2334 for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) { 2335 if ( drq == SMC37c669_drq_table[i].isa_drq ) { 2336 translated_drq = SMC37c669_drq_table[i].device_drq; 2337 break; 2338 } 2339 } 2340 } 2341 return translated_drq; 2342 } 2343 2344 #if 0 2345 int __init smcc669_init ( void ) 2346 { 2347 struct INODE *ip; 2348 2349 allocinode( smc_ddb.name, 1, &ip ); 2350 ip->dva = &smc_ddb; 2351 ip->attr = ATTR$M_WRITE | ATTR$M_READ; 2352 ip->len[0] = 0x30; 2353 ip->misc = 0; 2354 INODE_UNLOCK( ip ); 2355 2356 return msg_success; 2357 } 2358 2359 int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode ) 2360 { 2361 struct INODE *ip; 2362 /* 2363 ** Allow multiple readers but only one writer. ip->misc keeps track 2364 ** of the number of writers 2365 */ 2366 ip = fp->ip; 2367 INODE_LOCK( ip ); 2368 if ( fp->mode & ATTR$M_WRITE ) { 2369 if ( ip->misc ) { 2370 INODE_UNLOCK( ip ); 2371 return msg_failure; /* too many writers */ 2372 } 2373 ip->misc++; 2374 } 2375 /* 2376 ** Treat the information field as a byte offset 2377 */ 2378 *fp->offset = xtoi( info ); 2379 INODE_UNLOCK( ip ); 2380 2381 return msg_success; 2382 } 2383 2384 int __init smcc669_close( struct FILE *fp ) 2385 { 2386 struct INODE *ip; 2387 2388 ip = fp->ip; 2389 if ( fp->mode & ATTR$M_WRITE ) { 2390 INODE_LOCK( ip ); 2391 ip->misc--; 2392 INODE_UNLOCK( ip ); 2393 } 2394 return msg_success; 2395 } 2396 2397 int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf ) 2398 { 2399 int i; 2400 int length; 2401 int nbytes; 2402 struct INODE *ip; 2403 2404 /* 2405 ** Always access a byte at a time 2406 */ 2407 ip = fp->ip; 2408 length = size * number; 2409 nbytes = 0; 2410 2411 SMC37c669_config_mode( TRUE ); 2412 for ( i = 0; i < length; i++ ) { 2413 if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 2414 break; 2415 *buf++ = SMC37c669_read_config( *fp->offset ); 2416 *fp->offset += 1; 2417 nbytes++; 2418 } 2419 SMC37c669_config_mode( FALSE ); 2420 return nbytes; 2421 } 2422 2423 int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf ) 2424 { 2425 int i; 2426 int length; 2427 int nbytes; 2428 struct INODE *ip; 2429 /* 2430 ** Always access a byte at a time 2431 */ 2432 ip = fp->ip; 2433 length = size * number; 2434 nbytes = 0; 2435 2436 SMC37c669_config_mode( TRUE ); 2437 for ( i = 0; i < length; i++ ) { 2438 if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 2439 break; 2440 SMC37c669_write_config( *fp->offset, *buf ); 2441 *fp->offset += 1; 2442 buf++; 2443 nbytes++; 2444 } 2445 SMC37c669_config_mode( FALSE ); 2446 return nbytes; 2447 } 2448 #endif 2449 2450 void __init 2451 SMC37c669_dump_registers(void) 2452 { 2453 int i; 2454 for (i = 0; i <= 0x29; i++) 2455 printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i)); 2456 } 2457 /*+ 2458 * ============================================================================ 2459 * = SMC_init - SMC37c669 Super I/O controller initialization = 2460 * ============================================================================ 2461 * 2462 * OVERVIEW: 2463 * 2464 * This routine configures and enables device functions on the 2465 * SMC37c669 Super I/O controller. 2466 * 2467 * FORM OF CALL: 2468 * 2469 * SMC_init( ); 2470 * 2471 * RETURNS: 2472 * 2473 * Nothing 2474 * 2475 * ARGUMENTS: 2476 * 2477 * None 2478 * 2479 * SIDE EFFECTS: 2480 * 2481 * None 2482 * 2483 */ 2484 void __init SMC669_Init ( int index ) 2485 { 2486 SMC37c669_CONFIG_REGS *SMC_base; 2487 unsigned long flags; 2488 2489 local_irq_save(flags); 2490 if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) { 2491 #if SMC_DEBUG 2492 SMC37c669_config_mode( TRUE ); 2493 SMC37c669_dump_registers( ); 2494 SMC37c669_config_mode( FALSE ); 2495 SMC37c669_display_device_info( ); 2496 #endif 2497 SMC37c669_disable_device( SERIAL_0 ); 2498 SMC37c669_configure_device( 2499 SERIAL_0, 2500 COM1_BASE, 2501 COM1_IRQ, 2502 -1 2503 ); 2504 SMC37c669_enable_device( SERIAL_0 ); 2505 2506 SMC37c669_disable_device( SERIAL_1 ); 2507 SMC37c669_configure_device( 2508 SERIAL_1, 2509 COM2_BASE, 2510 COM2_IRQ, 2511 -1 2512 ); 2513 SMC37c669_enable_device( SERIAL_1 ); 2514 2515 SMC37c669_disable_device( PARALLEL_0 ); 2516 SMC37c669_configure_device( 2517 PARALLEL_0, 2518 PARP_BASE, 2519 PARP_IRQ, 2520 PARP_DRQ 2521 ); 2522 SMC37c669_enable_device( PARALLEL_0 ); 2523 2524 SMC37c669_disable_device( FLOPPY_0 ); 2525 SMC37c669_configure_device( 2526 FLOPPY_0, 2527 FDC_BASE, 2528 FDC_IRQ, 2529 FDC_DRQ 2530 ); 2531 SMC37c669_enable_device( FLOPPY_0 ); 2532 2533 /* Wake up sometimes forgotten floppy, especially on DP264. */ 2534 outb(0xc, 0x3f2); 2535 2536 SMC37c669_disable_device( IDE_0 ); 2537 2538 #if SMC_DEBUG 2539 SMC37c669_config_mode( TRUE ); 2540 SMC37c669_dump_registers( ); 2541 SMC37c669_config_mode( FALSE ); 2542 SMC37c669_display_device_info( ); 2543 #endif 2544 local_irq_restore(flags); 2545 printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n", 2546 (unsigned long) SMC_base ); 2547 } 2548 else { 2549 local_irq_restore(flags); 2550 #if SMC_DEBUG 2551 printk( "No SMC37c669 Super I/O Controller found\n" ); 2552 #endif 2553 } 2554 } 2555