~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/alpha/kernel/smc37c669.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php