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

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

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp