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