ia64/linux-2.6.18-xen.hg

view arch/alpha/kernel/smc37c669.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

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