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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [shared/] [bootloader/] [misc.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 *  head.S -- Bootloader Entry point
3
 *
4
 *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
5
 *
6
 *  Modified to compile in RTEMS development environment
7
 *  by Eric Valette
8
 *
9
 *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
10
 *
11
 *  The license and distribution terms for this file may be
12
 *  found in found in the file LICENSE in this distribution or at
13
 *  http://www.OARcorp.com/rtems/license.html.
14
 *
15
 * $Id: misc.c,v 1.2 2001-09-27 12:01:06 chris Exp $
16
 */
17
 
18
#include <sys/types.h>
19
#include <string.h>
20
#include <libcpu/cpu.h>
21
#include "bootldr.h"
22
#include <libcpu/spr.h>
23
#include "zlib.h"
24
#include <libcpu/page.h>
25
#include <libcpu/byteorder.h>
26
 
27
SPR_RW(DEC)
28
SPR_RO(PVR)
29
 
30
struct inode;
31
struct wait_queue;
32
struct buffer_head;
33
typedef struct { int counter; } atomic_t;
34
 
35
 
36
typedef struct page {
37
        /* these must be first (free area handling) */
38
        struct page *next;
39
        struct page *prev;
40
        struct inode *inode;
41
        unsigned long offset;
42
        struct page *next_hash;
43
        atomic_t count;
44
        unsigned long flags;    /* atomic flags, some possibly updated asynchronously */
45
        struct wait_queue *wait;
46
        struct page **pprev_hash;
47
        struct buffer_head * buffers;
48
} mem_map_t;
49
 
50
 
51
extern opaque mm_private, pci_private, v86_private, console_private;
52
 
53
#define CONSOLE_ON_SERIAL       "console=ttyS0"
54
 
55
extern struct console_io vacuum_console_functions;
56
extern opaque log_console_setup, serial_console_setup, vga_console_setup;
57
 
58
boot_data __bd = {0, 0, 0, 0, 0, 0, 0, 0,
59
                  32, 0, 0, 0, 0, 0, 0,
60
                  &mm_private,
61
                  NULL,
62
                  &pci_private,
63
                  NULL,
64
                  &v86_private,
65
                  "root=/dev/hdc1"
66
                 };
67
 
68
static void exit(void) __attribute__((noreturn));
69
 
70
static void exit(void) {
71
        printk("\nOnly way out is to press the reset button!\n");
72
        asm volatile("": : :"memory");
73
        while(1);
74
}
75
 
76
 
77
void hang(const char *s, u_long x, ctxt *p) {
78
        u_long *r1;
79
#ifdef DEBUG
80
        print_all_maps("\nMemory mappings at exception time:\n");
81
#endif
82
        printk("%s %lx NIP: %p LR: %p\n"
83
               "Callback trace (stack:return address)\n",
84
               s, x, (void *) p->nip, (void *) p->lr);
85
        asm volatile("lwz %0,0(1); lwz %0,0(%0); lwz %0,0(%0)": "=b" (r1));
86
        while(r1) {
87
                printk("  %p:%p\n", r1, (void *) r1[1]);
88
                r1 = (u_long *) *r1;
89
        }
90
        exit();
91
};
92
 
93
 
94
void *zalloc(void *x, unsigned items, unsigned size)
95
{
96
        void *p = salloc(items*size);
97
 
98
        if (!p) {
99
                printk("oops... not enough memory for gunzip\n");
100
        }
101
        return p;
102
}
103
 
104
void zfree(void *x, void *addr, unsigned nb)
105
{
106
        sfree(addr);
107
}
108
 
109
#define HEAD_CRC        2
110
#define EXTRA_FIELD     4
111
#define ORIG_NAME       8
112
#define COMMENT         0x10
113
#define RESERVED        0xe0
114
 
115
#define DEFLATED        8
116
 
117
 
118
void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
119
{
120
        z_stream s;
121
        int r, i, flags;
122
 
123
        /* skip header */
124
        i = 10;
125
        flags = src[3];
126
        if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
127
                printk("bad gzipped data\n");
128
                exit();
129
        }
130
        if ((flags & EXTRA_FIELD) != 0)
131
                i = 12 + src[10] + (src[11] << 8);
132
        if ((flags & ORIG_NAME) != 0)
133
                while (src[i++] != 0)
134
                        ;
135
        if ((flags & COMMENT) != 0)
136
                while (src[i++] != 0)
137
                        ;
138
        if ((flags & HEAD_CRC) != 0)
139
                i += 2;
140
        if (i >= *lenp) {
141
                printk("gunzip: ran out of data in header\n");
142
                exit();
143
        }
144
 
145
        s.zalloc = zalloc;
146
        s.zfree = zfree;
147
        r = inflateInit2(&s, -MAX_WBITS);
148
        if (r != Z_OK) {
149
                printk("inflateInit2 returned %d\n", r);
150
                exit();
151
        }
152
        s.next_in = src + i;
153
        s.avail_in = *lenp - i;
154
        s.next_out = dst;
155
        s.avail_out = dstlen;
156
        r = inflate(&s, Z_FINISH);
157
        if (r != Z_OK && r != Z_STREAM_END) {
158
                printk("inflate returned %d\n", r);
159
                exit();
160
        }
161
        *lenp = s.next_out - (unsigned char *) dst;
162
        inflateEnd(&s);
163
}
164
 
165
void decompress_kernel(int kernel_size, void * zimage_start, int len,
166
                       void * initrd_start, int initrd_len ) {
167
        u_char *parea;
168
        RESIDUAL* rescopy;
169
        int zimage_size= len;
170
 
171
        /* That's a mess, we have to copy the residual data twice just in
172
         * case it happens to be in the low memory area where the kernel
173
         * is going to be unpacked. Later we have to copy it back to
174
         * lower addresses because only the lowest part of memory is mapped
175
         * during boot.
176
         */
177
        parea=__palloc(kernel_size, PA_LOW);
178
        if(!parea) {
179
                printk("Not enough memory to uncompress the kernel.");
180
                exit();
181
        }
182
        /* Note that this clears the bss as a side effect, so some code
183
         * with ugly special case for SMP could be removed from the kernel!
184
         */
185
        memset(parea, 0, kernel_size);
186
        printk("\nUncompressing the kernel...\n");
187
        rescopy=salloc(sizeof(RESIDUAL));
188
        /* Let us hope that residual data is aligned on word boundary */
189
        *rescopy =  *bd->residual;
190
        bd->residual = (void *)PAGE_ALIGN(kernel_size);
191
 
192
        gunzip(parea, kernel_size, zimage_start, &zimage_size);
193
 
194
        bd->of_entry = 0;
195
        bd->load_address = 0;
196
        bd->r6 = (char *)bd->residual+PAGE_ALIGN(sizeof(RESIDUAL));
197
        bd->r7 = bd->r6+strlen(bd->cmd_line);
198
        if ( initrd_len ) {
199
                /* We have to leave some room for the hash table and for the
200
                 * whole array of struct page. The hash table would be better
201
                 * located at the end of memory if possible. With some bridges
202
                 * DMA from the last pages of memory is slower because
203
                 * prefetching from PCI has to be disabled to avoid accessing
204
                 * non existing memory. So it is the ideal place to put the
205
                 * hash table.
206
                 */
207
                unsigned tmp = rescopy->TotalMemory;
208
                /* It's equivalent to tmp & (-tmp), but using the negation
209
                 * operator on unsigned variables looks so ugly.
210
                 */
211
                if ((tmp & (~tmp+1)) != tmp) tmp <<= 1; /* Next power of 2 */
212
                tmp /= 256; /* Size of hash table */
213
                if (tmp> (2<<20)) tmp=2<<20;
214
                tmp = tmp*2 + 0x40000; /* Alignment can double size + 256 kB */
215
                tmp += (rescopy->TotalMemory / PAGE_SIZE)
216
                               * sizeof(struct page);
217
                bd->load_address = (void *)PAGE_ALIGN((int)bd->r7 + tmp);
218
                bd->of_entry = (char *)bd->load_address+initrd_len;
219
        }
220
#ifdef DEBUG
221
        printk("Kernel at 0x%p, size=0x%x\n", NULL, kernel_size);
222
        printk("Initrd at 0x%p, size=0x%x\n",bd->load_address, initrd_len);
223
        printk("Residual data at 0x%p\n", bd->residual);
224
        printk("Command line at 0x%p\n",bd->r6);
225
#endif
226
        printk("done\nNow booting...\n");
227
        MMUoff();       /* We need to access address 0 ! */
228
        codemove(0, parea, kernel_size, bd->cache_lsize);
229
        codemove(bd->residual, rescopy, sizeof(RESIDUAL), bd->cache_lsize);
230
        codemove(bd->r6, bd->cmd_line, sizeof(bd->cmd_line), bd->cache_lsize);
231
        /* codemove checks for 0 length */
232
        codemove(bd->load_address, initrd_start, initrd_len, bd->cache_lsize);
233
}
234
 
235
void
236
setup_hw(void)
237
{
238
        char *cp, ch;
239
        register RESIDUAL * res;
240
        /* PPC_DEVICE * nvram; */
241
        struct pci_dev *default_vga;
242
        int timer, err;
243
        u_short default_vga_cmd;
244
        static unsigned int indic;
245
 
246
        indic = 0;
247
 
248
        res=bd->residual;
249
        default_vga=NULL;
250
        default_vga_cmd = 0;
251
 
252
#define vpd res->VitalProductData
253
        if (_read_PVR()>>16 != 1) {
254
                if ( res && vpd.ProcessorBusHz ) {
255
                        ticks_per_ms = vpd.ProcessorBusHz/
256
                            (vpd.TimeBaseDivisor ? vpd.TimeBaseDivisor : 4000);
257
                } else {
258
                        ticks_per_ms = 16500; /* assume 66 MHz on bus */
259
                }
260
        }
261
 
262
        select_console(CONSOLE_LOG);
263
 
264
        /* We check that the keyboard is present and immediately
265
         * select the serial console if not.
266
         */
267
        err = kbdreset();
268
        if (err) select_console(CONSOLE_SERIAL);
269
 
270
        printk("\nModel: %s\nSerial: %s\n"
271
               "Processor/Bus frequencies (Hz): %ld/%ld\n"
272
               "Time Base Divisor: %ld\n"
273
               "Memory Size: %lx\n",
274
               vpd.PrintableModel,
275
               vpd.Serial,
276
               vpd.ProcessorHz,
277
               vpd.ProcessorBusHz,
278
               (vpd.TimeBaseDivisor ? vpd.TimeBaseDivisor : 4000),
279
               res->TotalMemory);
280
        printk("Original MSR: %lx\nOriginal HID0: %lx\nOriginal R31: %lx\n",
281
               bd->o_msr, bd->o_hid0, bd->o_r31);
282
 
283
        /* This reconfigures all the PCI subsystem */
284
        pci_init();
285
 
286
        /* The Motorola NT firmware does not set the correct mem size */
287
        if ( vpd.FirmwareSupplier == 0x10000 ) {
288
                int memsize;
289
                memsize = find_max_mem(bd->pci_devices);
290
                if ( memsize != res->TotalMemory ) {
291
                        printk("Changed Memory size from %lx to %x\n",
292
                                res->TotalMemory, memsize);
293
                        res->TotalMemory = memsize;
294
                        res->GoodMemory = memsize;
295
                }
296
        }
297
#define ENABLE_VGA_USAGE
298
#undef ENABLE_VGA_USAGE 
299
#ifdef ENABLE_VGA_USAGE
300
        /* Find the primary VGA device, chosing the first one found
301
         * if none is enabled. The basic loop structure has been copied
302
         * from linux/drivers/char/bttv.c by Alan Cox.
303
         */
304
        for (p = bd->pci_devices; p; p = p->next) {
305
                u_short cmd;
306
                if (p->class != PCI_CLASS_NOT_DEFINED_VGA &&
307
                    ((p->class) >> 16 != PCI_BASE_CLASS_DISPLAY))
308
                        continue;
309
                if (p->bus->number != 0) {
310
                        printk("VGA device not on bus 0 not initialized!\n");
311
                        continue;
312
                }
313
                /* Only one can be active in text mode, which for now will
314
                 * be assumed as equivalent to having I/O response enabled.
315
                 */
316
                pci_read_config_word(p, PCI_COMMAND, &cmd);
317
                if(cmd & PCI_COMMAND_IO || !default_vga) {
318
                        default_vga=p;
319
                        default_vga_cmd=cmd;
320
                }
321
        }
322
 
323
        /* Disable the enabled VGA device, if any. */
324
        if (default_vga)
325
                pci_write_config_word(default_vga, PCI_COMMAND,
326
                                      default_vga_cmd&
327
                                      ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
328
        init_v86();
329
        /* Same loop copied from bttv.c, this time doing the serious work */
330
        for (p = bd->pci_devices; p; p = p->next) {
331
                u_short cmd;
332
                if (p->class != PCI_CLASS_NOT_DEFINED_VGA &&
333
                    ((p->class) >> 16 != PCI_BASE_CLASS_DISPLAY))
334
                        continue;
335
                if (p->bus->number != 0) continue;
336
                pci_read_config_word(p, PCI_COMMAND, &cmd);
337
                pci_write_config_word(p, PCI_COMMAND,
338
                                      cmd|PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
339
                printk("Calling the emulator.\n");
340
                em86_main(p);
341
                pci_write_config_word(p, PCI_COMMAND, cmd);
342
        }
343
 
344
        cleanup_v86_mess();
345
#endif  
346
        /* Reenable the primary VGA device */
347
        if (default_vga) {
348
                pci_write_config_word(default_vga, PCI_COMMAND,
349
                                      default_vga_cmd|
350
                                      (PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
351
                if (err) {
352
                        printk("Keyboard error %d, using serial console!\n",
353
                               err);
354
                } else {
355
                        select_console(CONSOLE_VGA);
356
                }
357
        } else if (!err) {
358
                select_console(CONSOLE_SERIAL);
359
                if (bd->cmd_line[0] == '\0') {
360
                  strcat(&bd->cmd_line[0], CONSOLE_ON_SERIAL);
361
                }
362
                else {
363
                  int s = strlen (bd->cmd_line);
364
                  bd->cmd_line[s + 1] = ' ';
365
                  bd->cmd_line[s + 2] = '\0';
366
                  strcat(&bd->cmd_line[0], CONSOLE_ON_SERIAL);
367
                }
368
        }
369
#if 0
370
        /* In the future we may use the NVRAM to store default
371
         * kernel parameters.
372
         */
373
        nvram=residual_find_device(~0UL, NULL, SystemPeripheral, NVRAM,
374
                                   ~0UL, 0);
375
        if (nvram) {
376
                PnP_TAG_PACKET * pkt;
377
                switch (nvram->DevId.Interface) {
378
                case IndirectNVRAM:
379
                          pkt=PnP_find_packet(res->DevicePnpHeap
380
                                      +nvram->AllocatedOffset,
381
                                              )
382
                }
383
        }
384
#endif
385
 
386
        printk("\nRTEMS 4.x/PPC load: ");
387
        timer = 0;
388
        cp = bd->cmd_line+strlen(bd->cmd_line);
389
        while (timer++ < 5*1000) {
390
                if (debug_tstc()) {
391
                        while ((ch = debug_getc()) != '\n' && ch != '\r') {
392
                                if (ch == '\b' || ch == 0177) {
393
                                        if (cp != bd->cmd_line) {
394
                                                cp--;
395
                                                printk("\b \b");
396
                                        }
397
                                } else {
398
                                        *cp++ = ch;
399
                                        debug_putc(ch);
400
                                }
401
                        }
402
                        break;  /* Exit 'timer' loop */
403
                }
404
                udelay(1000);  /* 1 msec */
405
        }
406
        *cp = 0;
407
}
408
 
409
 
410
/* Functions to deal with the residual data */
411
static int same_DevID(unsigned short vendor,
412
               unsigned short Number,
413
               char * str)
414
{
415
        static unsigned const char hexdigit[]="0123456789ABCDEF";
416
        if (strlen(str)!=7) return 0;
417
        if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0])  &&
418
             ( ((vendor>>5)&0x1f)+'A'-1 == str[1])   &&
419
             ( (vendor&0x1f)+'A'-1 == str[2])        &&
420
             (hexdigit[(Number>>12)&0x0f] == str[3]) &&
421
             (hexdigit[(Number>>8)&0x0f] == str[4])  &&
422
             (hexdigit[(Number>>4)&0x0f] == str[5])  &&
423
             (hexdigit[Number&0x0f] == str[6]) ) return 1;
424
        return 0;
425
}
426
 
427
PPC_DEVICE *residual_find_device(unsigned long BusMask,
428
                         unsigned char * DevID,
429
                         int BaseType,
430
                         int SubType,
431
                         int Interface,
432
                         int n)
433
{
434
        int i;
435
        RESIDUAL *res = bd->residual;
436
        if ( !res || !res->ResidualLength ) return NULL;
437
        for (i=0; i<res->ActualNumDevices; i++) {
438
#define Dev res->Devices[i].DeviceId
439
                if ( (Dev.BusId&BusMask)                                  &&
440
                     (BaseType==-1 || Dev.BaseType==BaseType)             &&
441
                     (SubType==-1 || Dev.SubType==SubType)                &&
442
                     (Interface==-1 || Dev.Interface==Interface)          &&
443
                     (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff,
444
                                                Dev.DevId&0xffff, DevID)) &&
445
                     !(n--) ) return res->Devices+i;
446
#undef Dev
447
        }
448
        return 0;
449
}
450
 
451
PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
452
                                unsigned packet_tag,
453
                                int n)
454
{
455
        unsigned mask, masked_tag, size;
456
        if(!p) return 0;
457
        if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
458
        masked_tag = packet_tag&mask;
459
        for(; *p != END_TAG; p+=size) {
460
                if ((*p & mask) == masked_tag && !(n--))
461
                        return (PnP_TAG_PACKET *) p;
462
                if (tag_type(*p))
463
                        size=ld_le16((unsigned short *)(p+1))+3;
464
                else
465
                        size=tag_small_count(*p)+1;
466
        }
467
        return 0; /* not found */
468
}
469
 
470
PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
471
                                             unsigned packet_type,
472
                                             int n)
473
{
474
        int next=0;
475
        while (p) {
476
                p = (unsigned char *) PnP_find_packet(p, 0x70, next);
477
                if (p && p[1]==packet_type && !(n--))
478
                        return (PnP_TAG_PACKET *) p;
479
                next = 1;
480
        };
481
        return 0; /* not found */
482
}
483
 
484
PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
485
                                           unsigned packet_type,
486
                                           int n)
487
{
488
        int next=0;
489
        while (p) {
490
                p = (unsigned char *) PnP_find_packet(p, 0x84, next);
491
                if (p && p[3]==packet_type && !(n--))
492
                        return (PnP_TAG_PACKET *) p;
493
                next = 1;
494
        };
495
        return 0; /* not found */
496
}
497
 
498
/* Find out the amount of installed memory. For MPC105 and IBM 660 this
499
 * can be done by finding the bank with the highest memory ending address
500
 */
501
int
502
find_max_mem( struct pci_dev *dev )
503
{
504
        u_char banks,tmp;
505
        int i, top, max;
506
 
507
        max = 0;
508
        for ( ; dev; dev = dev->next) {
509
                if ( ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
510
                      (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC105)) ||
511
                     ((dev->vendor == PCI_VENDOR_ID_IBM) &&
512
                      (dev->device == 0x0037/*IBM 660 Bridge*/)) ) {
513
                        pci_read_config_byte(dev, 0xa0, &banks);
514
                        for (i = 0; i < 8; i++) {
515
                                if ( banks & (1<<i) ) {
516
                                        pci_read_config_byte(dev, 0x90+i, &tmp);
517
                                        top = tmp;
518
                                        pci_read_config_byte(dev, 0x98+i, &tmp);
519
                                        top |= (tmp&3)<<8;
520
                                        if ( top > max ) max = top;
521
                                }
522
                        }
523
                        if ( max ) return ((max+1)<<20);
524
                        else return(0);
525
                }
526
        }
527
        return(0);
528
}

powered by: WebSVN 2.1.0

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