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