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