2 * SMC 37C669 initialization code
4 #include <linux/kernel.h>
7 #include <linux/init.h>
8 #include <linux/delay.h>
9 #include <linux/spinlock.h>
11 #include <asm/hwrpb.h>
13 #include <asm/segment.h>
16 # define DBG_DEVS(args) printk args
18 # define DBG_DEVS(args)
27 /* File: smcc669_def.h
29 * Copyright (C) 1997 by
30 * Digital Equipment Corporation, Maynard, Massachusetts.
31 * All rights reserved.
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
40 * The information in this software is subject to change without notice
41 * and should not be construed as a commitment by Digital Equipment
44 * Digital assumes no responsibility for the use or reliability of its
45 * software on equipment which is not supplied by Digital.
50 * This file contains header definitions for the SMC37c669
51 * Super I/O controller.
57 * Modification History:
59 * er 28-Jan-1997 Initial Entry
66 ** Macros for handling device IRQs
68 ** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)
69 ** to device IRQs (A - H).
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))
80 ** Macros for handling device DRQs
82 ** The mask acts as a flag used in mapping actual ISA DMA
83 ** channels to device DMA channels (A - C).
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))
93 #define SMC37c669_DEVICE_ID 0x3
96 ** SMC37c669 Device Function Definitions
106 ** Default Device Function Mappings
108 #define COM1_BASE 0x3F8
110 #define COM2_BASE 0x2F8
112 #define PARP_BASE 0x3BC
115 #define FDC_BASE 0x3F0
120 ** Configuration On/Off Key Definitions
122 #define SMC37c669_CONFIG_ON_KEY 0x55
123 #define SMC37c669_CONFIG_OFF_KEY 0xAA
126 ** SMC 37c669 Device IRQs
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 ) )
138 ** SMC 37c669 Device DMA Channel Definitions
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 ) )
145 ** Configuration Register Index Definitions
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
191 ** Configuration Register Alias Definitions
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
206 ** Configuration Register Definitions
208 ** The INDEX (write only) and DATA (read/write) ports are effective
209 ** only when the chip is in the Configuration State.
211 typedef struct _SMC37c669_CONFIG_REGS
{
212 unsigned char index_port
;
213 unsigned char data_port
;
214 } SMC37c669_CONFIG_REGS
;
217 ** CR00 - default value 0x28
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
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.
234 typedef union _SMC37c669_CR00
{
235 unsigned char as_uchar
;
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 */
246 ** CR01 - default value 0x9C
248 typedef union _SMC37c669_CR01
{
249 unsigned char as_uchar
;
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 */
261 ** CR02 - default value 0x88
263 typedef union _SMC37c669_CR02
{
264 unsigned char as_uchar
;
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 */
274 ** CR03 - default value 0x78
276 ** CR03<7> CR03<2> Pin 94
277 ** ------- ------- ------
282 ** CR03<6> CR03<5> Op Mode
283 ** ------- ------- -------
289 typedef union _SMC37c669_CR03
{
290 unsigned char as_uchar
;
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 */
303 ** CR04 - default value 0x00
306 ** If CR01<PP_MODE> = 0 and PP_EXT_MODE =
307 ** 00 - Standard and Bidirectional
308 ** 01 - EPP mode and SPP
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.
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.
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)
338 ** 0 - Use pins IRRX, IRTX
339 ** 1 - Use pins IRRX2, IRTX2
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.
345 typedef union _SMC37c669_CR04
{
346 unsigned char as_uchar
;
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 */
358 ** CR05 - default value 0x00
361 ** 00 - Densel output normal
363 ** 10 - Densel output 1
364 ** 11 - Densel output 0
367 typedef union _SMC37c669_CR05
{
368 unsigned char as_uchar
;
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 */
380 ** CR06 - default value 0xFF
382 typedef union _SMC37c669_CR06
{
383 unsigned char as_uchar
;
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 */
393 ** CR07 - default value 0x00
395 ** Auto Power Management CR07<7:4>:
396 ** 0 - Auto Powerdown disabled (default)
397 ** 1 - Auto Powerdown enabled
399 ** This bit is reset to the default state by POR or
403 typedef union _SMC37c669_CR07
{
404 unsigned char as_uchar
;
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 */
416 ** CR08 - default value 0x00
418 typedef union _SMC37c669_CR08
{
419 unsigned char as_uchar
;
421 unsigned zero
: 4; /* 0 */
422 unsigned addrx7_4
: 4; /* ADR<7:3> for ADRx decode */
427 ** CR09 - default value 0x00
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
436 typedef union _SMC37c669_CR09
{
437 unsigned char as_uchar
;
439 unsigned adra8
: 3; /* ADR<10:8> for ADRx decode */
440 unsigned reserved1
: 3;
441 unsigned adrx_config
: 2; /* See note above */
446 ** CR0A - default value 0x00
448 typedef union _SMC37c669_CR0A
{
449 unsigned char as_uchar
;
451 unsigned ecp_fifo_threshold
: 4;
452 unsigned reserved1
: 4;
457 ** CR0B - default value 0x00
459 typedef union _SMC37c669_CR0B
{
460 unsigned char as_uchar
;
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 */
470 ** CR0C - default value 0x00
473 ** 000 - Standard (default)
474 ** 001 - IrDA (HPSIR)
475 ** 010 - Amplitude Shift Keyed IR @500 KHz
480 typedef union _SMC37c669_CR0C
{
481 unsigned char as_uchar
;
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 */
493 ** CR0D - default value 0x03
495 ** Device ID Register - read only
497 typedef union _SMC37c669_CR0D
{
498 unsigned char as_uchar
;
500 unsigned device_id
: 8; /* Returns 0x3 in this field */
505 ** CR0E - default value 0x02
507 ** Device Revision Register - read only
509 typedef union _SMC37c669_CR0E
{
510 unsigned char as_uchar
;
512 unsigned device_rev
: 8; /* Returns 0x2 in this field */
517 ** CR0F - default value 0x00
519 typedef union _SMC37c669_CR0F
{
520 unsigned char as_uchar
;
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 */
534 ** CR10 - default value 0x00
536 typedef union _SMC37c669_CR10
{
537 unsigned char as_uchar
;
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 */
549 ** CR11 - default value 0x00
551 typedef union _SMC37c669_CR11
{
552 unsigned char as_uchar
;
554 unsigned ir_loopback
: 1; /* Internal IR loop back */
555 unsigned test_10ms
: 1; /* Test 10ms autopowerdown FDC timeout */
556 unsigned reserved1
: 6; /* RAZ */
561 ** CR12 - CR1D are reserved registers
565 ** CR1E - default value 0x80
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
574 typedef union _SMC37c66_CR1E
{
575 unsigned char as_uchar
;
577 unsigned gamecs_config
: 2; /* See note above */
578 unsigned gamecs_addr9_4
: 6; /* GAMECS Addr<9:4> */
583 ** CR1F - default value 0x00
585 ** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
586 ** --- --- ------- ------- ----------
587 ** 0 0 DENSEL DRATE0 4/2/1 MB 3.5"
589 ** 2/1.6/1 MB 3.5" (3-mode)
591 ** 1 0 nDENSEL DRATE0 PS/2
594 ** Note: DENSEL, DRATE1, and DRATE0 map onto two output
595 ** pins - DRVDEN0 and DRVDEN1.
598 typedef union _SMC37c669_CR1F
{
599 unsigned char as_uchar
;
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 */
609 ** CR20 - default value 0x3C
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.
616 typedef union _SMC37c669_CR20
{
617 unsigned char as_uchar
;
619 unsigned zero
: 2; /* 0 */
620 unsigned addr9_4
: 6; /* FDC Addr<9:4> */
625 ** CR21 - default value 0x3C
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.
632 typedef union _SMC37c669_CR21
{
633 unsigned char as_uchar
;
635 unsigned zero
: 2; /* 0 */
636 unsigned addr9_4
: 6; /* IDE Addr<9:4> */
641 ** CR22 - default value 0x3D
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.
648 typedef union _SMC37c669_CR22
{
649 unsigned char as_uchar
;
651 unsigned zero
: 2; /* 0 */
652 unsigned addr9_4
: 6; /* IDE Alt Status Addr<9:4> */
657 ** CR23 - default value 0x00
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
666 typedef union _SMC37c669_CR23
{
667 unsigned char as_uchar
;
669 unsigned addr9_2
: 8; /* Parallel Port Addr<9:2> */
674 ** CR24 - default value 0x00
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.
681 typedef union _SMC37c669_CR24
{
682 unsigned char as_uchar
;
684 unsigned zero
: 1; /* 0 */
685 unsigned addr9_3
: 7; /* UART1 Addr<9:3> */
690 ** CR25 - default value 0x00
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.
697 typedef union _SMC37c669_CR25
{
698 unsigned char as_uchar
;
700 unsigned zero
: 1; /* 0 */
701 unsigned addr9_3
: 7; /* UART2 Addr<9:3> */
706 ** CR26 - default value 0x00
708 ** Parallel Port / FDC DMA Select Register
719 typedef union _SMC37c669_CR26
{
720 unsigned char as_uchar
;
722 unsigned ppt_drq
: 4; /* See note above */
723 unsigned fdc_drq
: 4; /* See note above */
728 ** CR27 - default value 0x00
730 ** Parallel Port / FDC IRQ Select Register
745 ** Any unselected IRQ REQ is in tristate
748 typedef union _SMC37c669_CR27
{
749 unsigned char as_uchar
;
751 unsigned ppt_irq
: 4; /* See note above */
752 unsigned fdc_irq
: 4; /* See note above */
757 ** CR28 - default value 0x00
759 ** UART IRQ Select Register
773 ** 1111 share with UART1 (only for UART2)
775 ** Any unselected IRQ REQ is in tristate
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.
782 typedef union _SMC37c669_CR28
{
783 unsigned char as_uchar
;
785 unsigned uart2_irq
: 4; /* See note above */
786 unsigned uart1_irq
: 4; /* See note above */
791 ** CR29 - default value 0x00
793 ** IRQIN IRQ Select Register
808 ** Any unselected IRQ REQ is in tristate
811 typedef union _SMC37c669_CR29
{
812 unsigned char as_uchar
;
814 unsigned irqin_irq
: 4; /* See note above */
815 unsigned reserved1
: 4; /* RAZ */
820 ** Aliases of Configuration Register formats (should match
821 ** the set of index aliases).
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.
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.
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
;
845 ** ISA/Device IRQ Translation Table Entry Definition
847 typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY
{
850 } SMC37c669_IRQ_TRANSLATION_ENTRY
;
853 ** ISA/Device DMA Translation Table Entry Definition
855 typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY
{
858 } SMC37c669_DRQ_TRANSLATION_ENTRY
;
861 ** External Interface Function Prototype Declarations
864 SMC37c669_CONFIG_REGS
*SMC37c669_detect(
868 unsigned int SMC37c669_enable_device(
872 unsigned int SMC37c669_disable_device(
876 unsigned int SMC37c669_configure_device(
883 void SMC37c669_display_device_info(
887 #endif /* __SMC37c669_H */
891 * Copyright (C) 1997 by
892 * Digital Equipment Corporation, Maynard, Massachusetts.
893 * All rights reserved.
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
902 * The information in this software is subject to change without notice
903 * and should not be construed as a commitment by digital equipment
906 * Digital assumes no responsibility for the use or reliability of its
907 * software on equipment which is not supplied by digital.
914 * Alpha SRM Console Firmware
916 * MODULE DESCRIPTION:
918 * SMC37c669 Super I/O controller configuration routines.
928 * MODIFICATION HISTORY:
930 * er 01-May-1997 Fixed pointer conversion errors in
931 * SMC37c669_get_device_config().
932 * er 28-Jan-1997 Initial version.
937 /* $INCLUDE_OPTIONS$ */
938 #include "cp$inc:platform_io.h"
939 /* $INCLUDE_OPTIONS_END$ */
940 #include "cp$src:common.h"
941 #include "cp$inc:prototypes.h"
942 #include "cp$src:kernel_def.h"
943 #include "cp$src:msg_def.h"
944 #include "cp$src:smcc669_def.h"
945 /* Platform-specific includes */
946 #include "cp$src:platform.h"
956 #define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) )
957 #define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) )
960 ** Local storage for device configuration information.
962 ** Since the SMC37c669 does not provide an explicit
963 ** mechanism for enabling/disabling individual device
964 ** functions, other than unmapping the device, local
965 ** storage for device configuration information is
966 ** allocated here for use in implementing our own
967 ** function enable/disable scheme.
969 static struct DEVICE_CONFIG
{
974 } local_config
[NUM_FUNCS
];
977 ** List of all possible addresses for the Super I/O chip
979 static unsigned long SMC37c669_Addresses
[] __initdata
=
981 0x3F0UL
, /* Primary address */
982 0x370UL
, /* Secondary address */
983 0UL /* End of list */
987 ** Global Pointer to the Super I/O device
989 static SMC37c669_CONFIG_REGS
*SMC37c669 __initdata
= NULL
;
992 ** IRQ Translation Table
994 ** The IRQ translation table is a list of SMC37c669 device
995 ** and standard ISA IRQs.
998 static SMC37c669_IRQ_TRANSLATION_ENTRY
*SMC37c669_irq_table __initdata
;
1001 ** The following definition is for the default IRQ
1002 ** translation table.
1004 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table
[]
1007 { SMC37c669_DEVICE_IRQ_A
, -1 },
1008 { SMC37c669_DEVICE_IRQ_B
, -1 },
1009 { SMC37c669_DEVICE_IRQ_C
, 7 },
1010 { SMC37c669_DEVICE_IRQ_D
, 6 },
1011 { SMC37c669_DEVICE_IRQ_E
, 4 },
1012 { SMC37c669_DEVICE_IRQ_F
, 3 },
1013 { SMC37c669_DEVICE_IRQ_H
, -1 },
1014 { -1, -1 } /* End of table */
1018 ** The following definition is for the MONET (XP1000) IRQ
1019 ** translation table.
1021 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table
[]
1024 { SMC37c669_DEVICE_IRQ_A
, -1 },
1025 { SMC37c669_DEVICE_IRQ_B
, -1 },
1026 { SMC37c669_DEVICE_IRQ_C
, 6 },
1027 { SMC37c669_DEVICE_IRQ_D
, 7 },
1028 { SMC37c669_DEVICE_IRQ_E
, 4 },
1029 { SMC37c669_DEVICE_IRQ_F
, 3 },
1030 { SMC37c669_DEVICE_IRQ_H
, -1 },
1031 { -1, -1 } /* End of table */
1034 static SMC37c669_IRQ_TRANSLATION_ENTRY
*SMC37c669_irq_tables
[] __initdata
=
1036 SMC37c669_default_irq_table
,
1037 SMC37c669_monet_irq_table
1041 ** DRQ Translation Table
1043 ** The DRQ translation table is a list of SMC37c669 device and
1044 ** ISA DMA channels.
1047 static SMC37c669_DRQ_TRANSLATION_ENTRY
*SMC37c669_drq_table __initdata
;
1050 ** The following definition is the default DRQ
1051 ** translation table.
1053 static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table
[]
1056 { SMC37c669_DEVICE_DRQ_A
, 2 },
1057 { SMC37c669_DEVICE_DRQ_B
, 3 },
1058 { SMC37c669_DEVICE_DRQ_C
, -1 },
1059 { -1, -1 } /* End of table */
1063 ** Local Function Prototype Declarations
1066 static unsigned int SMC37c669_is_device_enabled(
1071 static unsigned int SMC37c669_get_device_config(
1079 static void SMC37c669_config_mode(
1083 static unsigned char SMC37c669_read_config(
1087 static void SMC37c669_write_config(
1088 unsigned char index
,
1092 static void SMC37c669_init_local_config( void );
1094 static struct DEVICE_CONFIG
*SMC37c669_get_config(
1098 static int SMC37c669_xlate_irq(
1102 static int SMC37c669_xlate_drq(
1106 static __cacheline_aligned
DEFINE_SPINLOCK(smc_lock
);
1110 ** FUNCTIONAL DESCRIPTION:
1112 ** This function detects the presence of an SMC37c669 Super I/O
1115 ** FORMAL PARAMETERS:
1121 ** Returns a pointer to the device if found, otherwise,
1122 ** the NULL pointer is returned.
1130 SMC37c669_CONFIG_REGS
* __init
SMC37c669_detect( int index
)
1133 SMC37c669_DEVICE_ID_REGISTER id
;
1135 for ( i
= 0; SMC37c669_Addresses
[i
] != 0; i
++ ) {
1137 ** Initialize the device pointer even though we don't yet know if
1138 ** the controller is at this address. The support functions access
1139 ** the controller through this device pointer so we need to set it
1140 ** even when we are looking ...
1142 SMC37c669
= ( SMC37c669_CONFIG_REGS
* )SMC37c669_Addresses
[i
];
1144 ** Enter configuration mode
1146 SMC37c669_config_mode( TRUE
);
1148 ** Read the device id
1150 id
.as_uchar
= SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX
);
1152 ** Exit configuration mode
1154 SMC37c669_config_mode( FALSE
);
1156 ** Does the device id match? If so, assume we have found an
1157 ** SMC37c669 controller at this address.
1159 if ( id
.by_field
.device_id
== SMC37c669_DEVICE_ID
) {
1161 ** Initialize the IRQ and DRQ translation tables.
1163 SMC37c669_irq_table
= SMC37c669_irq_tables
[ index
];
1164 SMC37c669_drq_table
= SMC37c669_default_drq_table
;
1168 ** If the platform can't use the IRQ and DRQ defaults set up in this
1169 ** file, it should call a platform-specific external routine at this
1170 ** point to reset the IRQ and DRQ translation table pointers to point
1171 ** at the appropriate tables for the platform. If the defaults are
1172 ** acceptable, then the external routine should do nothing.
1176 ** Put the chip back into configuration mode
1178 SMC37c669_config_mode( TRUE
);
1180 ** Initialize local storage for configuration information
1182 SMC37c669_init_local_config( );
1184 ** Exit configuration mode
1186 SMC37c669_config_mode( FALSE
);
1188 ** SMC37c669 controller found, break out of search loop
1194 ** Otherwise, we did not find an SMC37c669 controller at this
1195 ** address so set the device pointer to NULL.
1206 ** FUNCTIONAL DESCRIPTION:
1208 ** This function enables an SMC37c669 device function.
1210 ** FORMAL PARAMETERS:
1213 ** Which device function to enable
1217 ** Returns TRUE is the device function was enabled, otherwise, FALSE
1221 ** {@description or none@}
1225 ** Enabling a device function in the SMC37c669 controller involves
1226 ** setting all of its mappings (port, irq, drq ...). A local
1227 ** "shadow" copy of the device configuration is kept so we can
1228 ** just set each mapping to what the local copy says.
1230 ** This function ALWAYS updates the local shadow configuration of
1231 ** the device function being enabled, even if the device is always
1232 ** enabled. To avoid replication of code, functions such as
1233 ** configure_device set up the local copy and then call this
1234 ** function to the update the real device.
1238 unsigned int __init
SMC37c669_enable_device ( unsigned int func
)
1240 unsigned int ret_val
= FALSE
;
1242 ** Put the device into configuration mode
1244 SMC37c669_config_mode( TRUE
);
1248 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1249 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1251 ** Enable the serial 1 IRQ mapping
1254 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1256 irq
.by_field
.uart1_irq
=
1257 SMC37c669_RAW_DEVICE_IRQ(
1258 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1261 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1263 ** Enable the serial 1 port base address mapping
1265 base_addr
.as_uchar
= 0;
1266 base_addr
.by_field
.addr9_3
= local_config
[ func
].port1
>> 3;
1268 SMC37c669_write_config(
1269 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
,
1277 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1278 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1280 ** Enable the serial 2 IRQ mapping
1283 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1285 irq
.by_field
.uart2_irq
=
1286 SMC37c669_RAW_DEVICE_IRQ(
1287 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1290 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1292 ** Enable the serial 2 port base address mapping
1294 base_addr
.as_uchar
= 0;
1295 base_addr
.by_field
.addr9_3
= local_config
[ func
].port1
>> 3;
1297 SMC37c669_write_config(
1298 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
,
1306 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr
;
1307 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1308 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1310 ** Enable the parallel port DMA channel mapping
1313 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1315 drq
.by_field
.ppt_drq
=
1316 SMC37c669_RAW_DEVICE_DRQ(
1317 SMC37c669_xlate_drq( local_config
[ func
].drq
)
1320 SMC37c669_write_config(
1321 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1325 ** Enable the parallel port IRQ mapping
1328 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1330 irq
.by_field
.ppt_irq
=
1331 SMC37c669_RAW_DEVICE_IRQ(
1332 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1335 SMC37c669_write_config(
1336 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1340 ** Enable the parallel port base address mapping
1342 base_addr
.as_uchar
= 0;
1343 base_addr
.by_field
.addr9_2
= local_config
[ func
].port1
>> 2;
1345 SMC37c669_write_config(
1346 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
,
1354 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr
;
1355 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1356 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1358 ** Enable the floppy controller DMA channel mapping
1361 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1363 drq
.by_field
.fdc_drq
=
1364 SMC37c669_RAW_DEVICE_DRQ(
1365 SMC37c669_xlate_drq( local_config
[ func
].drq
)
1368 SMC37c669_write_config(
1369 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1373 ** Enable the floppy controller IRQ mapping
1376 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1378 irq
.by_field
.fdc_irq
=
1379 SMC37c669_RAW_DEVICE_IRQ(
1380 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1383 SMC37c669_write_config(
1384 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1388 ** Enable the floppy controller base address mapping
1390 base_addr
.as_uchar
= 0;
1391 base_addr
.by_field
.addr9_4
= local_config
[ func
].port1
>> 4;
1393 SMC37c669_write_config(
1394 SMC37c669_FDC_BASE_ADDRESS_INDEX
,
1402 SMC37c669_IDE_ADDRESS_REGISTER ide_addr
;
1404 ** Enable the IDE alternate status base address mapping
1406 ide_addr
.as_uchar
= 0;
1407 ide_addr
.by_field
.addr9_4
= local_config
[ func
].port2
>> 4;
1409 SMC37c669_write_config(
1410 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX
,
1414 ** Enable the IDE controller base address mapping
1416 ide_addr
.as_uchar
= 0;
1417 ide_addr
.by_field
.addr9_4
= local_config
[ func
].port1
>> 4;
1419 SMC37c669_write_config(
1420 SMC37c669_IDE_BASE_ADDRESS_INDEX
,
1428 ** Exit configuration mode and return
1430 SMC37c669_config_mode( FALSE
);
1438 ** FUNCTIONAL DESCRIPTION:
1440 ** This function disables a device function within the
1441 ** SMC37c669 Super I/O controller.
1443 ** FORMAL PARAMETERS:
1446 ** Which function to disable
1450 ** Return TRUE if the device function was disabled, otherwise, FALSE
1454 ** {@description or none@}
1458 ** Disabling a function in the SMC37c669 device involves
1459 ** disabling all the function's mappings (port, irq, drq ...).
1460 ** A shadow copy of the device configuration is maintained
1461 ** in local storage so we won't worry aboving saving the
1462 ** current configuration information.
1466 unsigned int __init
SMC37c669_disable_device ( unsigned int func
)
1468 unsigned int ret_val
= FALSE
;
1471 ** Put the device into configuration mode
1473 SMC37c669_config_mode( TRUE
);
1477 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1478 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1480 ** Disable the serial 1 IRQ mapping
1483 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1485 irq
.by_field
.uart1_irq
= 0;
1487 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1489 ** Disable the serial 1 port base address mapping
1491 base_addr
.as_uchar
= 0;
1492 SMC37c669_write_config(
1493 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
,
1501 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1502 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1504 ** Disable the serial 2 IRQ mapping
1507 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1509 irq
.by_field
.uart2_irq
= 0;
1511 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1513 ** Disable the serial 2 port base address mapping
1515 base_addr
.as_uchar
= 0;
1517 SMC37c669_write_config(
1518 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
,
1526 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr
;
1527 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1528 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1530 ** Disable the parallel port DMA channel mapping
1533 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1535 drq
.by_field
.ppt_drq
= 0;
1537 SMC37c669_write_config(
1538 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1542 ** Disable the parallel port IRQ mapping
1545 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1547 irq
.by_field
.ppt_irq
= 0;
1549 SMC37c669_write_config(
1550 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1554 ** Disable the parallel port base address mapping
1556 base_addr
.as_uchar
= 0;
1558 SMC37c669_write_config(
1559 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
,
1567 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr
;
1568 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1569 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1571 ** Disable the floppy controller DMA channel mapping
1574 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1576 drq
.by_field
.fdc_drq
= 0;
1578 SMC37c669_write_config(
1579 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1583 ** Disable the floppy controller IRQ mapping
1586 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1588 irq
.by_field
.fdc_irq
= 0;
1590 SMC37c669_write_config(
1591 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1595 ** Disable the floppy controller base address mapping
1597 base_addr
.as_uchar
= 0;
1599 SMC37c669_write_config(
1600 SMC37c669_FDC_BASE_ADDRESS_INDEX
,
1608 SMC37c669_IDE_ADDRESS_REGISTER ide_addr
;
1610 ** Disable the IDE alternate status base address mapping
1612 ide_addr
.as_uchar
= 0;
1614 SMC37c669_write_config(
1615 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX
,
1619 ** Disable the IDE controller base address mapping
1621 ide_addr
.as_uchar
= 0;
1623 SMC37c669_write_config(
1624 SMC37c669_IDE_BASE_ADDRESS_INDEX
,
1632 ** Exit configuration mode and return
1634 SMC37c669_config_mode( FALSE
);
1642 ** FUNCTIONAL DESCRIPTION:
1644 ** This function configures a device function within the
1645 ** SMC37c669 Super I/O controller.
1647 ** FORMAL PARAMETERS:
1650 ** Which device function
1653 ** I/O port for the function to use
1656 ** IRQ for the device function to use
1659 ** DMA channel for the device function to use
1663 ** Returns TRUE if the device function was configured,
1664 ** otherwise, FALSE.
1668 ** {@description or none@}
1672 ** If this function returns TRUE, the local shadow copy of
1673 ** the configuration is also updated. If the device function
1674 ** is currently disabled, only the local shadow copy is
1675 ** updated and the actual device function will be updated
1676 ** if/when it is enabled.
1680 unsigned int __init
SMC37c669_configure_device (
1686 struct DEVICE_CONFIG
*cp
;
1689 ** Check for a valid configuration
1691 if ( ( cp
= SMC37c669_get_config ( func
) ) != NULL
) {
1693 ** Configuration is valid, update the local shadow copy
1695 if ( ( drq
& ~0xFF ) == 0 ) {
1698 if ( ( irq
& ~0xFF ) == 0 ) {
1701 if ( ( port
& ~0xFFFF ) == 0 ) {
1705 ** If the device function is enabled, update the actual
1706 ** device configuration.
1708 if ( SMC37c669_is_device_enabled( func
) ) {
1709 SMC37c669_enable_device( func
);
1719 ** FUNCTIONAL DESCRIPTION:
1721 ** This function determines whether a device function
1722 ** within the SMC37c669 controller is enabled.
1724 ** FORMAL PARAMETERS:
1727 ** Which device function
1731 ** Returns TRUE if the device function is enabled, otherwise, FALSE
1735 ** {@description or none@}
1739 ** To check whether a device is enabled we will only look at
1740 ** the port base address mapping. According to the SMC37c669
1741 ** specification, all of the port base address mappings are
1742 ** disabled if the addr<9:8> (bits <7:6> of the register) are
1747 static unsigned int __init
SMC37c669_is_device_enabled ( unsigned int func
)
1749 unsigned char base_addr
= 0;
1750 unsigned int dev_ok
= FALSE
;
1751 unsigned int ret_val
= FALSE
;
1753 ** Enter configuration mode
1755 SMC37c669_config_mode( TRUE
);
1760 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
);
1765 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
);
1770 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
);
1775 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX
);
1780 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX
);
1785 ** If we have a valid device, check base_addr<7:6> to see if the
1786 ** device is enabled (mapped).
1788 if ( ( dev_ok
) && ( ( base_addr
& 0xC0 ) != 0 ) ) {
1790 ** The mapping is not disabled, so assume that the function is
1796 ** Exit configuration mode
1798 SMC37c669_config_mode( FALSE
);
1807 ** FUNCTIONAL DESCRIPTION:
1809 ** This function retrieves the configuration information of a
1810 ** device function within the SMC37c699 Super I/O controller.
1812 ** FORMAL PARAMETERS:
1815 ** Which device function
1818 ** I/O port returned
1824 ** DMA channel returned
1828 ** Returns TRUE if the device configuration was successfully
1829 ** retrieved, otherwise, FALSE.
1833 ** The data pointed to by the port, irq, and drq parameters
1834 ** my be modified even if the configuration is not successfully
1839 ** The device configuration is fetched from the local shadow
1840 ** copy. Any unused parameters will be set to -1. Any
1841 ** parameter which is not desired can specify the NULL
1846 static unsigned int __init
SMC37c669_get_device_config (
1852 struct DEVICE_CONFIG
*cp
;
1853 unsigned int ret_val
= FALSE
;
1855 ** Check for a valid device configuration
1857 if ( ( cp
= SMC37c669_get_config( func
) ) != NULL
) {
1858 if ( drq
!= NULL
) {
1862 if ( irq
!= NULL
) {
1866 if ( port
!= NULL
) {
1878 ** FUNCTIONAL DESCRIPTION:
1880 ** This function displays the current state of the SMC37c699
1881 ** Super I/O controller's device functions.
1883 ** FORMAL PARAMETERS:
1897 void __init
SMC37c669_display_device_info ( void )
1899 if ( SMC37c669_is_device_enabled( SERIAL_0
) ) {
1900 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1901 local_config
[ SERIAL_0
].port1
,
1902 local_config
[ SERIAL_0
].irq
1906 printk( " Serial 0: Disabled\n" );
1909 if ( SMC37c669_is_device_enabled( SERIAL_1
) ) {
1910 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n",
1911 local_config
[ SERIAL_1
].port1
,
1912 local_config
[ SERIAL_1
].irq
1916 printk( " Serial 1: Disabled\n" );
1919 if ( SMC37c669_is_device_enabled( PARALLEL_0
) ) {
1920 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1921 local_config
[ PARALLEL_0
].port1
,
1922 local_config
[ PARALLEL_0
].irq
,
1923 local_config
[ PARALLEL_0
].drq
1927 printk( " Parallel: Disabled\n" );
1930 if ( SMC37c669_is_device_enabled( FLOPPY_0
) ) {
1931 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1932 local_config
[ FLOPPY_0
].port1
,
1933 local_config
[ FLOPPY_0
].irq
,
1934 local_config
[ FLOPPY_0
].drq
1938 printk( " Floppy Ctrl: Disabled\n" );
1941 if ( SMC37c669_is_device_enabled( IDE_0
) ) {
1942 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1943 local_config
[ IDE_0
].port1
,
1944 local_config
[ IDE_0
].irq
1948 printk( " IDE 0: Disabled\n" );
1955 ** FUNCTIONAL DESCRIPTION:
1957 ** This function puts the SMC37c669 Super I/O controller into,
1958 ** and takes it out of, configuration mode.
1960 ** FORMAL PARAMETERS:
1963 ** TRUE to enter configuration mode, FALSE to exit.
1971 ** The SMC37c669 controller may be left in configuration mode.
1975 static void __init
SMC37c669_config_mode(
1976 unsigned int enable
)
1980 ** To enter configuration mode, two writes in succession to the index
1981 ** port are required. If a write to another address or port occurs
1982 ** between these two writes, the chip does not enter configuration
1983 ** mode. Therefore, a spinlock is placed around the two writes to
1984 ** guarantee that they complete uninterrupted.
1986 spin_lock(&smc_lock
);
1987 wb( &SMC37c669
->index_port
, SMC37c669_CONFIG_ON_KEY
);
1988 wb( &SMC37c669
->index_port
, SMC37c669_CONFIG_ON_KEY
);
1989 spin_unlock(&smc_lock
);
1992 wb( &SMC37c669
->index_port
, SMC37c669_CONFIG_OFF_KEY
);
1998 ** FUNCTIONAL DESCRIPTION:
2000 ** This function reads an SMC37c669 Super I/O controller
2001 ** configuration register. This function assumes that the
2002 ** device is already in configuration mode.
2004 ** FORMAL PARAMETERS:
2007 ** Index value of configuration register to read
2011 ** Data read from configuration register
2019 static unsigned char __init
SMC37c669_read_config(
2020 unsigned char index
)
2024 wb( &SMC37c669
->index_port
, index
);
2025 data
= rb( &SMC37c669
->data_port
);
2031 ** FUNCTIONAL DESCRIPTION:
2033 ** This function writes an SMC37c669 Super I/O controller
2034 ** configuration register. This function assumes that the
2035 ** device is already in configuration mode.
2037 ** FORMAL PARAMETERS:
2040 ** Index of configuration register to write
2043 ** Data to be written
2055 static void __init
SMC37c669_write_config(
2056 unsigned char index
,
2057 unsigned char data
)
2059 wb( &SMC37c669
->index_port
, index
);
2060 wb( &SMC37c669
->data_port
, data
);
2066 ** FUNCTIONAL DESCRIPTION:
2068 ** This function initializes the local device
2069 ** configuration storage. This function assumes
2070 ** that the device is already in configuration
2073 ** FORMAL PARAMETERS:
2083 ** Local storage for device configuration information
2088 static void __init
SMC37c669_init_local_config ( void )
2090 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base
;
2091 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs
;
2092 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base
;
2093 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs
;
2094 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs
;
2095 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base
;
2096 SMC37c669_IDE_ADDRESS_REGISTER ide_base
;
2097 SMC37c669_IDE_ADDRESS_REGISTER ide_alt
;
2100 ** Get serial port 1 base address
2102 uart_base
.as_uchar
=
2103 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
);
2105 ** Get IRQs for serial ports 1 & 2
2107 uart_irqs
.as_uchar
=
2108 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
2110 ** Store local configuration information for serial port 1
2112 local_config
[SERIAL_0
].port1
= uart_base
.by_field
.addr9_3
<< 3;
2113 local_config
[SERIAL_0
].irq
=
2114 SMC37c669_xlate_irq(
2115 SMC37c669_DEVICE_IRQ( uart_irqs
.by_field
.uart1_irq
)
2118 ** Get serial port 2 base address
2120 uart_base
.as_uchar
=
2121 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
);
2123 ** Store local configuration information for serial port 2
2125 local_config
[SERIAL_1
].port1
= uart_base
.by_field
.addr9_3
<< 3;
2126 local_config
[SERIAL_1
].irq
=
2127 SMC37c669_xlate_irq(
2128 SMC37c669_DEVICE_IRQ( uart_irqs
.by_field
.uart2_irq
)
2131 ** Get parallel port base address
2134 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
);
2136 ** Get IRQs for parallel port and floppy controller
2138 ppt_fdc_irqs
.as_uchar
=
2139 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
2141 ** Get DRQs for parallel port and floppy controller
2143 ppt_fdc_drqs
.as_uchar
=
2144 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
2146 ** Store local configuration information for parallel port
2148 local_config
[PARALLEL_0
].port1
= ppt_base
.by_field
.addr9_2
<< 2;
2149 local_config
[PARALLEL_0
].irq
=
2150 SMC37c669_xlate_irq(
2151 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs
.by_field
.ppt_irq
)
2153 local_config
[PARALLEL_0
].drq
=
2154 SMC37c669_xlate_drq(
2155 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs
.by_field
.ppt_drq
)
2158 ** Get floppy controller base address
2161 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX
);
2163 ** Store local configuration information for floppy controller
2165 local_config
[FLOPPY_0
].port1
= fdc_base
.by_field
.addr9_4
<< 4;
2166 local_config
[FLOPPY_0
].irq
=
2167 SMC37c669_xlate_irq(
2168 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs
.by_field
.fdc_irq
)
2170 local_config
[FLOPPY_0
].drq
=
2171 SMC37c669_xlate_drq(
2172 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs
.by_field
.fdc_drq
)
2175 ** Get IDE controller base address
2178 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX
);
2180 ** Get IDE alternate status base address
2183 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX
);
2185 ** Store local configuration information for IDE controller
2187 local_config
[IDE_0
].port1
= ide_base
.by_field
.addr9_4
<< 4;
2188 local_config
[IDE_0
].port2
= ide_alt
.by_field
.addr9_4
<< 4;
2189 local_config
[IDE_0
].irq
= 14;
2195 ** FUNCTIONAL DESCRIPTION:
2197 ** This function returns a pointer to the local shadow
2198 ** configuration of the requested device function.
2200 ** FORMAL PARAMETERS:
2203 ** Which device function
2207 ** Returns a pointer to the DEVICE_CONFIG structure for the
2208 ** requested function, otherwise, NULL.
2212 ** {@description or none@}
2216 static struct DEVICE_CONFIG
* __init
SMC37c669_get_config( unsigned int func
)
2218 struct DEVICE_CONFIG
*cp
= NULL
;
2222 cp
= &local_config
[ SERIAL_0
];
2225 cp
= &local_config
[ SERIAL_1
];
2228 cp
= &local_config
[ PARALLEL_0
];
2231 cp
= &local_config
[ FLOPPY_0
];
2234 cp
= &local_config
[ IDE_0
];
2242 ** FUNCTIONAL DESCRIPTION:
2244 ** This function translates IRQs back and forth between ISA
2245 ** IRQs and SMC37c669 device IRQs.
2247 ** FORMAL PARAMETERS:
2250 ** The IRQ to translate
2254 ** Returns the translated IRQ, otherwise, returns -1.
2258 ** {@description or none@}
2262 static int __init
SMC37c669_xlate_irq ( int irq
)
2264 int i
, translated_irq
= -1;
2266 if ( SMC37c669_IS_DEVICE_IRQ( irq
) ) {
2268 ** We are translating a device IRQ to an ISA IRQ
2270 for ( i
= 0; ( SMC37c669_irq_table
[i
].device_irq
!= -1 ) || ( SMC37c669_irq_table
[i
].isa_irq
!= -1 ); i
++ ) {
2271 if ( irq
== SMC37c669_irq_table
[i
].device_irq
) {
2272 translated_irq
= SMC37c669_irq_table
[i
].isa_irq
;
2279 ** We are translating an ISA IRQ to a device IRQ
2281 for ( i
= 0; ( SMC37c669_irq_table
[i
].isa_irq
!= -1 ) || ( SMC37c669_irq_table
[i
].device_irq
!= -1 ); i
++ ) {
2282 if ( irq
== SMC37c669_irq_table
[i
].isa_irq
) {
2283 translated_irq
= SMC37c669_irq_table
[i
].device_irq
;
2288 return translated_irq
;
2294 ** FUNCTIONAL DESCRIPTION:
2296 ** This function translates DMA channels back and forth between
2297 ** ISA DMA channels and SMC37c669 device DMA channels.
2299 ** FORMAL PARAMETERS:
2302 ** The DMA channel to translate
2306 ** Returns the translated DMA channel, otherwise, returns -1
2310 ** {@description or none@}
2314 static int __init
SMC37c669_xlate_drq ( int drq
)
2316 int i
, translated_drq
= -1;
2318 if ( SMC37c669_IS_DEVICE_DRQ( drq
) ) {
2320 ** We are translating a device DMA channel to an ISA DMA channel
2322 for ( i
= 0; ( SMC37c669_drq_table
[i
].device_drq
!= -1 ) || ( SMC37c669_drq_table
[i
].isa_drq
!= -1 ); i
++ ) {
2323 if ( drq
== SMC37c669_drq_table
[i
].device_drq
) {
2324 translated_drq
= SMC37c669_drq_table
[i
].isa_drq
;
2331 ** We are translating an ISA DMA channel to a device DMA channel
2333 for ( i
= 0; ( SMC37c669_drq_table
[i
].isa_drq
!= -1 ) || ( SMC37c669_drq_table
[i
].device_drq
!= -1 ); i
++ ) {
2334 if ( drq
== SMC37c669_drq_table
[i
].isa_drq
) {
2335 translated_drq
= SMC37c669_drq_table
[i
].device_drq
;
2340 return translated_drq
;
2344 int __init
smcc669_init ( void )
2348 allocinode( smc_ddb
.name
, 1, &ip
);
2350 ip
->attr
= ATTR$M_WRITE
| ATTR$M_READ
;
2358 int __init
smcc669_open( struct FILE *fp
, char *info
, char *next
, char *mode
)
2362 ** Allow multiple readers but only one writer. ip->misc keeps track
2363 ** of the number of writers
2367 if ( fp
->mode
& ATTR$M_WRITE
) {
2370 return msg_failure
; /* too many writers */
2375 ** Treat the information field as a byte offset
2377 *fp
->offset
= xtoi( info
);
2383 int __init
smcc669_close( struct FILE *fp
)
2388 if ( fp
->mode
& ATTR$M_WRITE
) {
2396 int __init
smcc669_read( struct FILE *fp
, int size
, int number
, unsigned char *buf
)
2404 ** Always access a byte at a time
2407 length
= size
* number
;
2410 SMC37c669_config_mode( TRUE
);
2411 for ( i
= 0; i
< length
; i
++ ) {
2412 if ( !inrange( *fp
->offset
, 0, ip
->len
[0] ) )
2414 *buf
++ = SMC37c669_read_config( *fp
->offset
);
2418 SMC37c669_config_mode( FALSE
);
2422 int __init
smcc669_write( struct FILE *fp
, int size
, int number
, unsigned char *buf
)
2429 ** Always access a byte at a time
2432 length
= size
* number
;
2435 SMC37c669_config_mode( TRUE
);
2436 for ( i
= 0; i
< length
; i
++ ) {
2437 if ( !inrange( *fp
->offset
, 0, ip
->len
[0] ) )
2439 SMC37c669_write_config( *fp
->offset
, *buf
);
2444 SMC37c669_config_mode( FALSE
);
2450 SMC37c669_dump_registers(void)
2453 for (i
= 0; i
<= 0x29; i
++)
2454 printk("-- CR%02x : %02x\n", i
, SMC37c669_read_config(i
));
2457 * ============================================================================
2458 * = SMC_init - SMC37c669 Super I/O controller initialization =
2459 * ============================================================================
2463 * This routine configures and enables device functions on the
2464 * SMC37c669 Super I/O controller.
2483 void __init
SMC669_Init ( int index
)
2485 SMC37c669_CONFIG_REGS
*SMC_base
;
2486 unsigned long flags
;
2488 local_irq_save(flags
);
2489 if ( ( SMC_base
= SMC37c669_detect( index
) ) != NULL
) {
2491 SMC37c669_config_mode( TRUE
);
2492 SMC37c669_dump_registers( );
2493 SMC37c669_config_mode( FALSE
);
2494 SMC37c669_display_device_info( );
2496 SMC37c669_disable_device( SERIAL_0
);
2497 SMC37c669_configure_device(
2503 SMC37c669_enable_device( SERIAL_0
);
2505 SMC37c669_disable_device( SERIAL_1
);
2506 SMC37c669_configure_device(
2512 SMC37c669_enable_device( SERIAL_1
);
2514 SMC37c669_disable_device( PARALLEL_0
);
2515 SMC37c669_configure_device(
2521 SMC37c669_enable_device( PARALLEL_0
);
2523 SMC37c669_disable_device( FLOPPY_0
);
2524 SMC37c669_configure_device(
2530 SMC37c669_enable_device( FLOPPY_0
);
2532 /* Wake up sometimes forgotten floppy, especially on DP264. */
2535 SMC37c669_disable_device( IDE_0
);
2538 SMC37c669_config_mode( TRUE
);
2539 SMC37c669_dump_registers( );
2540 SMC37c669_config_mode( FALSE
);
2541 SMC37c669_display_device_info( );
2543 local_irq_restore(flags
);
2544 printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",
2548 local_irq_restore(flags
);
2550 printk( "No SMC37c669 Super I/O Controller found\n" );