OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [x86/] [kernel/] [mca_32.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 *  Written by Martin Kolinek, February 1996
3
 *
4
 * Changes:
5
 *
6
 *      Chris Beauregard July 28th, 1996
7
 *      - Fixed up integrated SCSI detection
8
 *
9
 *      Chris Beauregard August 3rd, 1996
10
 *      - Made mca_info local
11
 *      - Made integrated registers accessible through standard function calls
12
 *      - Added name field
13
 *      - More sanity checking
14
 *
15
 *      Chris Beauregard August 9th, 1996
16
 *      - Rewrote /proc/mca
17
 *
18
 *      Chris Beauregard January 7th, 1997
19
 *      - Added basic NMI-processing
20
 *      - Added more information to mca_info structure
21
 *
22
 *      David Weinehall October 12th, 1998
23
 *      - Made a lot of cleaning up in the source
24
 *      - Added use of save_flags / restore_flags
25
 *      - Added the 'driver_loaded' flag in MCA_adapter
26
 *      - Added an alternative implemention of ZP Gu's mca_find_unused_adapter
27
 *
28
 *      David Weinehall March 24th, 1999
29
 *      - Fixed the output of 'Driver Installed' in /proc/mca/pos
30
 *      - Made the Integrated Video & SCSI show up even if they have id 0000
31
 *
32
 *      Alexander Viro November 9th, 1999
33
 *      - Switched to regular procfs methods
34
 *
35
 *      Alfred Arnold & David Weinehall August 23rd, 2000
36
 *      - Added support for Planar POS-registers
37
 */
38
 
39
#include <linux/module.h>
40
#include <linux/types.h>
41
#include <linux/errno.h>
42
#include <linux/kernel.h>
43
#include <linux/mca.h>
44
#include <linux/kprobes.h>
45
#include <asm/system.h>
46
#include <asm/io.h>
47
#include <linux/proc_fs.h>
48
#include <linux/mman.h>
49
#include <linux/mm.h>
50
#include <linux/pagemap.h>
51
#include <linux/ioport.h>
52
#include <asm/uaccess.h>
53
#include <linux/init.h>
54
#include <asm/arch_hooks.h>
55
 
56
static unsigned char which_scsi = 0;
57
 
58
int MCA_bus = 0;
59
EXPORT_SYMBOL(MCA_bus);
60
 
61
/*
62
 * Motherboard register spinlock. Untested on SMP at the moment, but
63
 * are there any MCA SMP boxes?
64
 *
65
 * Yes - Alan
66
 */
67
static DEFINE_SPINLOCK(mca_lock);
68
 
69
/* Build the status info for the adapter */
70
 
71
static void mca_configure_adapter_status(struct mca_device *mca_dev) {
72
        mca_dev->status = MCA_ADAPTER_NONE;
73
 
74
        mca_dev->pos_id = mca_dev->pos[0]
75
                + (mca_dev->pos[1] << 8);
76
 
77
        if(!mca_dev->pos_id && mca_dev->slot < MCA_MAX_SLOT_NR) {
78
 
79
                /* id = 0x0000 usually indicates hardware failure,
80
                 * however, ZP Gu (zpg@castle.net> reports that his 9556
81
                 * has 0x0000 as id and everything still works. There
82
                 * also seem to be an adapter with id = 0x0000; the
83
                 * NCR Parallel Bus Memory Card. Until this is confirmed,
84
                 * however, this code will stay.
85
                 */
86
 
87
                mca_dev->status = MCA_ADAPTER_ERROR;
88
 
89
                return;
90
        } else if(mca_dev->pos_id != 0xffff) {
91
 
92
                /* 0xffff usually indicates that there's no adapter,
93
                 * however, some integrated adapters may have 0xffff as
94
                 * their id and still be valid. Examples are on-board
95
                 * VGA of the 55sx, the integrated SCSI of the 56 & 57,
96
                 * and possibly also the 95 ULTIMEDIA.
97
                 */
98
 
99
                mca_dev->status = MCA_ADAPTER_NORMAL;
100
        }
101
 
102
        if((mca_dev->pos_id == 0xffff ||
103
            mca_dev->pos_id == 0x0000) && mca_dev->slot >= MCA_MAX_SLOT_NR) {
104
                int j;
105
 
106
                for(j = 2; j < 8; j++) {
107
                        if(mca_dev->pos[j] != 0xff) {
108
                                mca_dev->status = MCA_ADAPTER_NORMAL;
109
                                break;
110
                        }
111
                }
112
        }
113
 
114
        if(!(mca_dev->pos[2] & MCA_ENABLED)) {
115
 
116
                /* enabled bit is in POS 2 */
117
 
118
                mca_dev->status = MCA_ADAPTER_DISABLED;
119
        }
120
} /* mca_configure_adapter_status */
121
 
122
/*--------------------------------------------------------------------*/
123
 
124
static struct resource mca_standard_resources[] = {
125
        { .start = 0x60, .end = 0x60, .name = "system control port B (MCA)" },
126
        { .start = 0x90, .end = 0x90, .name = "arbitration (MCA)" },
127
        { .start = 0x91, .end = 0x91, .name = "card Select Feedback (MCA)" },
128
        { .start = 0x92, .end = 0x92, .name = "system Control port A (MCA)" },
129
        { .start = 0x94, .end = 0x94, .name = "system board setup (MCA)" },
130
        { .start = 0x96, .end = 0x97, .name = "POS (MCA)" },
131
        { .start = 0x100, .end = 0x107, .name = "POS (MCA)" }
132
};
133
 
134
#define MCA_STANDARD_RESOURCES  ARRAY_SIZE(mca_standard_resources)
135
 
136
/**
137
 *      mca_read_and_store_pos - read the POS registers into a memory buffer
138
 *      @pos: a char pointer to 8 bytes, contains the POS register value on
139
 *            successful return
140
 *
141
 *      Returns 1 if a card actually exists (i.e. the pos isn't
142
 *      all 0xff) or 0 otherwise
143
 */
144
static int mca_read_and_store_pos(unsigned char *pos) {
145
        int j;
146
        int found = 0;
147
 
148
        for(j=0; j<8; j++) {
149
                if((pos[j] = inb_p(MCA_POS_REG(j))) != 0xff) {
150
                        /* 0xff all across means no device. 0x00 means
151
                         * something's broken, but a device is
152
                         * probably there.  However, if you get 0x00
153
                         * from a motherboard register it won't matter
154
                         * what we find.  For the record, on the
155
                         * 57SLC, the integrated SCSI adapter has
156
                         * 0xffff for the adapter ID, but nonzero for
157
                         * other registers.  */
158
 
159
                        found = 1;
160
                }
161
        }
162
        return found;
163
}
164
 
165
static unsigned char mca_pc_read_pos(struct mca_device *mca_dev, int reg)
166
{
167
        unsigned char byte;
168
        unsigned long flags;
169
 
170
        if(reg < 0 || reg >= 8)
171
                return 0;
172
 
173
        spin_lock_irqsave(&mca_lock, flags);
174
        if(mca_dev->pos_register) {
175
                /* Disable adapter setup, enable motherboard setup */
176
 
177
                outb_p(0, MCA_ADAPTER_SETUP_REG);
178
                outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG);
179
 
180
                byte = inb_p(MCA_POS_REG(reg));
181
                outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
182
        } else {
183
 
184
                /* Make sure motherboard setup is off */
185
 
186
                outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
187
 
188
                /* Read the appropriate register */
189
 
190
                outb_p(0x8|(mca_dev->slot & 0xf), MCA_ADAPTER_SETUP_REG);
191
                byte = inb_p(MCA_POS_REG(reg));
192
                outb_p(0, MCA_ADAPTER_SETUP_REG);
193
        }
194
        spin_unlock_irqrestore(&mca_lock, flags);
195
 
196
        mca_dev->pos[reg] = byte;
197
 
198
        return byte;
199
}
200
 
201
static void mca_pc_write_pos(struct mca_device *mca_dev, int reg,
202
                             unsigned char byte)
203
{
204
        unsigned long flags;
205
 
206
        if(reg < 0 || reg >= 8)
207
                return;
208
 
209
        spin_lock_irqsave(&mca_lock, flags);
210
 
211
        /* Make sure motherboard setup is off */
212
 
213
        outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
214
 
215
        /* Read in the appropriate register */
216
 
217
        outb_p(0x8|(mca_dev->slot&0xf), MCA_ADAPTER_SETUP_REG);
218
        outb_p(byte, MCA_POS_REG(reg));
219
        outb_p(0, MCA_ADAPTER_SETUP_REG);
220
 
221
        spin_unlock_irqrestore(&mca_lock, flags);
222
 
223
        /* Update the global register list, while we have the byte */
224
 
225
        mca_dev->pos[reg] = byte;
226
 
227
}
228
 
229
/* for the primary MCA bus, we have identity transforms */
230
static int mca_dummy_transform_irq(struct mca_device * mca_dev, int irq)
231
{
232
        return irq;
233
}
234
 
235
static int mca_dummy_transform_ioport(struct mca_device * mca_dev, int port)
236
{
237
        return port;
238
}
239
 
240
static void *mca_dummy_transform_memory(struct mca_device * mca_dev, void *mem)
241
{
242
        return mem;
243
}
244
 
245
 
246
static int __init mca_init(void)
247
{
248
        unsigned int i, j;
249
        struct mca_device *mca_dev;
250
        unsigned char pos[8];
251
        short mca_builtin_scsi_ports[] = {0xf7, 0xfd, 0x00};
252
        struct mca_bus *bus;
253
 
254
        /* WARNING: Be careful when making changes here. Putting an adapter
255
         * and the motherboard simultaneously into setup mode may result in
256
         * damage to chips (according to The Indispensible PC Hardware Book
257
         * by Hans-Peter Messmer). Also, we disable system interrupts (so
258
         * that we are not disturbed in the middle of this).
259
         */
260
 
261
        /* Make sure the MCA bus is present */
262
 
263
        if (mca_system_init()) {
264
                printk(KERN_ERR "MCA bus system initialisation failed\n");
265
                return -ENODEV;
266
        }
267
 
268
        if (!MCA_bus)
269
                return -ENODEV;
270
 
271
        printk(KERN_INFO "Micro Channel bus detected.\n");
272
 
273
        /* All MCA systems have at least a primary bus */
274
        bus = mca_attach_bus(MCA_PRIMARY_BUS);
275
        if (!bus)
276
                goto out_nomem;
277
        bus->default_dma_mask = 0xffffffffLL;
278
        bus->f.mca_write_pos = mca_pc_write_pos;
279
        bus->f.mca_read_pos = mca_pc_read_pos;
280
        bus->f.mca_transform_irq = mca_dummy_transform_irq;
281
        bus->f.mca_transform_ioport = mca_dummy_transform_ioport;
282
        bus->f.mca_transform_memory = mca_dummy_transform_memory;
283
 
284
        /* get the motherboard device */
285
        mca_dev = kzalloc(sizeof(struct mca_device), GFP_KERNEL);
286
        if(unlikely(!mca_dev))
287
                goto out_nomem;
288
 
289
        /*
290
         * We do not expect many MCA interrupts during initialization,
291
         * but let us be safe:
292
         */
293
        spin_lock_irq(&mca_lock);
294
 
295
        /* Make sure adapter setup is off */
296
 
297
        outb_p(0, MCA_ADAPTER_SETUP_REG);
298
 
299
        /* Read motherboard POS registers */
300
 
301
        mca_dev->pos_register = 0x7f;
302
        outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG);
303
        mca_dev->name[0] = 0;
304
        mca_read_and_store_pos(mca_dev->pos);
305
        mca_configure_adapter_status(mca_dev);
306
        /* fake POS and slot for a motherboard */
307
        mca_dev->pos_id = MCA_MOTHERBOARD_POS;
308
        mca_dev->slot = MCA_MOTHERBOARD;
309
        mca_register_device(MCA_PRIMARY_BUS, mca_dev);
310
 
311
        mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
312
        if(unlikely(!mca_dev))
313
                goto out_unlock_nomem;
314
 
315
        /* Put motherboard into video setup mode, read integrated video
316
         * POS registers, and turn motherboard setup off.
317
         */
318
 
319
        mca_dev->pos_register = 0xdf;
320
        outb_p(mca_dev->pos_register, MCA_MOTHERBOARD_SETUP_REG);
321
        mca_dev->name[0] = 0;
322
        mca_read_and_store_pos(mca_dev->pos);
323
        mca_configure_adapter_status(mca_dev);
324
        /* fake POS and slot for the integrated video */
325
        mca_dev->pos_id = MCA_INTEGVIDEO_POS;
326
        mca_dev->slot = MCA_INTEGVIDEO;
327
        mca_register_device(MCA_PRIMARY_BUS, mca_dev);
328
 
329
        /* Put motherboard into scsi setup mode, read integrated scsi
330
         * POS registers, and turn motherboard setup off.
331
         *
332
         * It seems there are two possible SCSI registers. Martin says that
333
         * for the 56,57, 0xf7 is the one, but fails on the 76.
334
         * Alfredo (apena@vnet.ibm.com) says
335
         * 0xfd works on his machine. We'll try both of them. I figure it's
336
         * a good bet that only one could be valid at a time. This could
337
         * screw up though if one is used for something else on the other
338
         * machine.
339
         */
340
 
341
        for(i = 0; (which_scsi = mca_builtin_scsi_ports[i]) != 0; i++) {
342
                outb_p(which_scsi, MCA_MOTHERBOARD_SETUP_REG);
343
                if(mca_read_and_store_pos(pos))
344
                        break;
345
        }
346
        if(which_scsi) {
347
                /* found a scsi card */
348
                mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
349
                if(unlikely(!mca_dev))
350
                        goto out_unlock_nomem;
351
 
352
                for(j = 0; j < 8; j++)
353
                        mca_dev->pos[j] = pos[j];
354
 
355
                mca_configure_adapter_status(mca_dev);
356
                /* fake POS and slot for integrated SCSI controller */
357
                mca_dev->pos_id = MCA_INTEGSCSI_POS;
358
                mca_dev->slot = MCA_INTEGSCSI;
359
                mca_dev->pos_register = which_scsi;
360
                mca_register_device(MCA_PRIMARY_BUS, mca_dev);
361
        }
362
 
363
        /* Turn off motherboard setup */
364
 
365
        outb_p(0xff, MCA_MOTHERBOARD_SETUP_REG);
366
 
367
        /* Now loop over MCA slots: put each adapter into setup mode, and
368
         * read its POS registers. Then put adapter setup off.
369
         */
370
 
371
        for(i=0; i<MCA_MAX_SLOT_NR; i++) {
372
                outb_p(0x8|(i&0xf), MCA_ADAPTER_SETUP_REG);
373
                if(!mca_read_and_store_pos(pos))
374
                        continue;
375
 
376
                mca_dev = kzalloc(sizeof(struct mca_device), GFP_ATOMIC);
377
                if(unlikely(!mca_dev))
378
                        goto out_unlock_nomem;
379
 
380
                for(j=0; j<8; j++)
381
                        mca_dev->pos[j]=pos[j];
382
 
383
                mca_dev->driver_loaded = 0;
384
                mca_dev->slot = i;
385
                mca_dev->pos_register = 0;
386
                mca_configure_adapter_status(mca_dev);
387
                mca_register_device(MCA_PRIMARY_BUS, mca_dev);
388
        }
389
        outb_p(0, MCA_ADAPTER_SETUP_REG);
390
 
391
        /* Enable interrupts and return memory start */
392
        spin_unlock_irq(&mca_lock);
393
 
394
        for (i = 0; i < MCA_STANDARD_RESOURCES; i++)
395
                request_resource(&ioport_resource, mca_standard_resources + i);
396
 
397
        mca_do_proc_init();
398
 
399
        return 0;
400
 
401
 out_unlock_nomem:
402
        spin_unlock_irq(&mca_lock);
403
 out_nomem:
404
        printk(KERN_EMERG "Failed memory allocation in MCA setup!\n");
405
        return -ENOMEM;
406
}
407
 
408
subsys_initcall(mca_init);
409
 
410
/*--------------------------------------------------------------------*/
411
 
412
static __kprobes void
413
mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
414
{
415
        int slot = mca_dev->slot;
416
 
417
        if(slot == MCA_INTEGSCSI) {
418
                printk(KERN_CRIT "NMI: caused by MCA integrated SCSI adapter (%s)\n",
419
                        mca_dev->name);
420
        } else if(slot == MCA_INTEGVIDEO) {
421
                printk(KERN_CRIT "NMI: caused by MCA integrated video adapter (%s)\n",
422
                        mca_dev->name);
423
        } else if(slot == MCA_MOTHERBOARD) {
424
                printk(KERN_CRIT "NMI: caused by motherboard (%s)\n",
425
                        mca_dev->name);
426
        }
427
 
428
        /* More info available in POS 6 and 7? */
429
 
430
        if(check_flag) {
431
                unsigned char pos6, pos7;
432
 
433
                pos6 = mca_device_read_pos(mca_dev, 6);
434
                pos7 = mca_device_read_pos(mca_dev, 7);
435
 
436
                printk(KERN_CRIT "NMI: POS 6 = 0x%x, POS 7 = 0x%x\n", pos6, pos7);
437
        }
438
 
439
} /* mca_handle_nmi_slot */
440
 
441
/*--------------------------------------------------------------------*/
442
 
443
static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
444
{
445
        struct mca_device *mca_dev = to_mca_device(dev);
446
        unsigned char pos5;
447
 
448
        pos5 = mca_device_read_pos(mca_dev, 5);
449
 
450
        if(!(pos5 & 0x80)) {
451
                /* Bit 7 of POS 5 is reset when this adapter has a hardware
452
                 * error. Bit 7 it reset if there's error information
453
                 * available in POS 6 and 7.
454
                 */
455
                mca_handle_nmi_device(mca_dev, !(pos5 & 0x40));
456
                return 1;
457
        }
458
        return 0;
459
}
460
 
461
void __kprobes mca_handle_nmi(void)
462
{
463
        /* First try - scan the various adapters and see if a specific
464
         * adapter was responsible for the error.
465
         */
466
        bus_for_each_dev(&mca_bus_type, NULL, NULL, mca_handle_nmi_callback);
467
 
468
        mca_nmi_hook();
469
} /* mca_handle_nmi */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.