|
|
1.1 root 1: /*
2: * Linux initialization.
3: *
4: * Copyright (C) 1996 The University of Utah and the Computer Systems
5: * Laboratory at the University of Utah (CSL)
6: *
7: * This program is free software; you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as published by
9: * the Free Software Foundation; either version 2, or (at your option)
10: * any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with this program; if not, write to the Free Software
19: * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20: *
21: * Author: Shantanu Goel, University of Utah CSL
22: */
23:
24: /*
25: * linux/init/main.c
26: *
27: * Copyright (C) 1991, 1992 Linus Torvalds
28: */
29:
30: #include <sys/types.h>
31:
32: #include <mach/vm_param.h>
33: #include <mach/vm_prot.h>
34: #include <mach/machine.h>
35:
36: #include <vm/vm_page.h>
37: #include <kern/kalloc.h>
38:
39: #include <machine/spl.h>
40: #include <machine/pmap.h>
41: #include <machine/vm_param.h>
42:
43: #define MACH_INCLUDE
44: #include <linux/sched.h>
45: #include <linux/mm.h>
46: #include <linux/interrupt.h>
47: #include <linux/delay.h>
48: #include <linux/ioport.h>
49: #include <linux/string.h>
50:
51: #include <asm/system.h>
52: #include <asm/io.h>
53:
54: #include <device-drivers.h>
55:
56: /*
57: * Timing loop count.
58: */
59: unsigned long loops_per_sec = 1;
60:
61: /*
62: * End of physical memory.
63: */
64: unsigned long high_memory;
65:
66: /*
67: * Flag to indicate auto-configuration is in progress.
68: */
69: int linux_auto_config = 1;
70:
71: /*
72: * Hard drive parameters obtained from the BIOS.
73: */
74: struct drive_info_struct
75: {
76: char dummy[32];
77: } drive_info;
78:
79: /*
80: * Forward declarations.
81: */
82: static void calibrate_delay (void);
83:
84: extern int hz;
85: extern vm_offset_t phys_last_addr;
86:
87: extern void *alloc_contig_mem (unsigned, unsigned, unsigned, vm_page_t *);
88: extern void free_contig_mem (vm_page_t);
89: extern void init_IRQ (void);
90: extern void restore_IRQ (void);
91: extern void startrtclock (void);
92: extern void linux_version_init (void);
93: extern void linux_kmem_init (void);
94: extern unsigned long pci_init (unsigned long, unsigned long);
95: extern void linux_net_emulation_init (void);
96: extern void device_setup (void);
97: extern void linux_printk (char *,...);
98: extern int linux_timer_intr (void);
99: extern spl_t spl0 (void);
100: extern spl_t splhigh (void);
101: extern void form_pic_mask (void);
102: extern int linux_bad_intr (int);
103: extern int prtnull ();
104: extern int intnull ();
105: extern void linux_sched_init (void);
106:
107:
108: /*
109: * Amount of contiguous memory to allocate for initialization.
110: */
111: #define CONTIG_ALLOC (512 * 1024)
112:
113: /*
114: * Initialize Linux drivers.
115: */
116: void
117: linux_init (void)
118: {
119: int addr;
120: unsigned memory_start, memory_end;
121: vm_page_t pages;
122:
123: /*
124: * Initialize memory size.
125: */
126: high_memory = phys_last_addr;
127: init_IRQ ();
128: linux_sched_init ();
129:
130: /*
131: * Set loop count.
132: */
133: calibrate_delay ();
134:
135: /*
136: * Initialize drive info.
137: */
138: addr = *((unsigned *) phystokv (0x104));
139: memcpy (&drive_info,
140: (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
141: addr = *((unsigned *) phystokv (0x118));
142: memcpy ((char *) &drive_info + 16,
143: (void *) ((addr & 0xffff) + ((addr >> 12) & 0xffff0)), 16);
144:
145: /*
146: * Initialize Linux memory allocator.
147: */
148: linux_kmem_init ();
149:
150: /*
151: * Allocate contiguous memory below 16 MB.
152: */
153: memory_start = (unsigned long) alloc_contig_mem (CONTIG_ALLOC,
154: 16 * 1024 * 1024,
155: 0, &pages);
156: if (memory_start == 0)
157: panic ("linux_init: alloc_contig_mem failed");
158: memory_end = memory_start + CONTIG_ALLOC;
159:
160: /*
161: * Initialize PCI bus.
162: */
163: memory_start = pci_init (memory_start, memory_end);
164:
165: if (memory_start > memory_end)
166: panic ("linux_init: ran out memory");
167:
168: /*
169: * Free unused memory.
170: */
171: while (pages && pages->phys_addr < round_page (memory_start))
172: pages = (vm_page_t) pages->pageq.next;
173: if (pages)
174: free_contig_mem (pages);
175:
176: /*
177: * Initialize devices.
178: */
179: #ifdef CONFIG_INET
180: linux_net_emulation_init ();
181: #endif
182: cli ();
183: device_setup ();
184:
185: restore_IRQ ();
186: linux_auto_config = 0;
187: }
188:
189: #ifndef NBPW
190: #define NBPW 32
191: #endif
192:
193: /*
194: * Allocate contiguous memory with the given constraints.
195: * This routine is horribly inefficient but it is presently
196: * only used during initialization so it's not that bad.
197: */
198: void *
199: alloc_contig_mem (unsigned size, unsigned limit,
200: unsigned mask, vm_page_t * pages)
201: {
202: int i, j, bits_len;
203: unsigned *bits, len;
204: void *m;
205: vm_page_t p, page_list, tail, prev;
206: vm_offset_t addr, max_addr;
207:
208: if (size == 0)
209: return (NULL);
210: size = round_page (size);
211: if ((size >> PAGE_SHIFT) > vm_page_free_count)
212: return (NULL);
213:
214: /* Allocate bit array. */
215: max_addr = phys_last_addr;
216: if (max_addr > limit)
217: max_addr = limit;
218: bits_len = ((((max_addr >> PAGE_SHIFT) + NBPW - 1) / NBPW)
219: * sizeof (unsigned));
220: bits = (unsigned *) kalloc (bits_len);
221: if (!bits)
222: return (NULL);
223: memset (bits, 0, bits_len);
224:
225: /*
226: * Walk the page free list and set a bit for every usable page.
227: */
228: simple_lock (&vm_page_queue_free_lock);
229: p = vm_page_queue_free;
230: while (p)
231: {
232: if (p->phys_addr < limit)
233: (bits[(p->phys_addr >> PAGE_SHIFT) / NBPW]
234: |= 1 << ((p->phys_addr >> PAGE_SHIFT) % NBPW));
235: p = (vm_page_t) p->pageq.next;
236: }
237:
238: /*
239: * Scan bit array for contiguous pages.
240: */
241: len = 0;
242: m = NULL;
243: for (i = 0; len < size && i < bits_len / sizeof (unsigned); i++)
244: for (j = 0; len < size && j < NBPW; j++)
245: if (!(bits[i] & (1 << j)))
246: {
247: len = 0;
248: m = NULL;
249: }
250: else
251: {
252: if (len == 0)
253: {
254: addr = ((vm_offset_t) (i * NBPW + j)
255: << PAGE_SHIFT);
256: if ((addr & mask) == 0)
257: {
258: len += PAGE_SIZE;
259: m = (void *) addr;
260: }
261: }
262: else
263: len += PAGE_SIZE;
264: }
265:
266: if (len != size)
267: {
268: simple_unlock (&vm_page_queue_free_lock);
269: kfree ((vm_offset_t) bits, bits_len);
270: return (NULL);
271: }
272:
273: /*
274: * Remove pages from free list
275: * and construct list to return to caller.
276: */
277: page_list = NULL;
278: for (len = 0; len < size; len += PAGE_SIZE, addr += PAGE_SIZE)
279: {
280: prev = NULL;
281: for (p = vm_page_queue_free; p; p = (vm_page_t) p->pageq.next)
282: {
283: if (p->phys_addr == addr)
284: break;
285: prev = p;
286: }
287: if (!p)
288: panic ("alloc_contig_mem: page not on free list");
289: if (prev)
290: prev->pageq.next = p->pageq.next;
291: else
292: vm_page_queue_free = (vm_page_t) p->pageq.next;
293: p->free = FALSE;
294: p->pageq.next = NULL;
295: if (!page_list)
296: page_list = tail = p;
297: else
298: {
299: tail->pageq.next = (queue_entry_t) p;
300: tail = p;
301: }
302: vm_page_free_count--;
303: }
304:
305: simple_unlock (&vm_page_queue_free_lock);
306: kfree ((vm_offset_t) bits, bits_len);
307: if (pages)
308: *pages = page_list;
309: return (m);
310: }
311:
312: /*
313: * Free memory allocated by alloc_contig_mem.
314: */
315: void
316: free_contig_mem (vm_page_t pages)
317: {
318: int i;
319: vm_page_t p;
320:
321: for (p = pages, i = 0; p->pageq.next; p = (vm_page_t) p->pageq.next, i++)
322: p->free = TRUE;
323: p->free = TRUE;
324: simple_lock (&vm_page_queue_free_lock);
325: vm_page_free_count += i + 1;
326: p->pageq.next = (queue_entry_t) vm_page_queue_free;
327: vm_page_queue_free = pages;
328: simple_unlock (&vm_page_queue_free_lock);
329: }
330:
331: /* This is the number of bits of precision for the loops_per_second. Each
332: * bit takes on average 1.5/HZ seconds. This (like the original) is a little
333: * better than 1%
334: */
335: #define LPS_PREC 8
336:
337: static void
338: calibrate_delay (void)
339: {
340: int ticks;
341: int loopbit;
342: int lps_precision = LPS_PREC;
343:
344: loops_per_sec = (1 << 12);
345:
346: #ifndef MACH
347: printk ("Calibrating delay loop.. ");
348: #endif
349: while (loops_per_sec <<= 1)
350: {
351: /* wait for "start of" clock tick */
352: ticks = jiffies;
353: while (ticks == jiffies)
354: /* nothing */ ;
355: /* Go .. */
356: ticks = jiffies;
357: __delay (loops_per_sec);
358: ticks = jiffies - ticks;
359: if (ticks)
360: break;
361: }
362:
363: /* Do a binary approximation to get loops_per_second set to equal one clock
364: * (up to lps_precision bits)
365: */
366: loops_per_sec >>= 1;
367: loopbit = loops_per_sec;
368: while (lps_precision-- && (loopbit >>= 1))
369: {
370: loops_per_sec |= loopbit;
371: ticks = jiffies;
372: while (ticks == jiffies);
373: ticks = jiffies;
374: __delay (loops_per_sec);
375: if (jiffies != ticks) /* longer than 1 tick */
376: loops_per_sec &= ~loopbit;
377: }
378:
379: /* finally, adjust loops per second in terms of seconds instead of clocks */
380: loops_per_sec *= HZ;
381: /* Round the value and print it */
382: #ifndef MACH
383: printk ("ok - %lu.%02lu BogoMIPS\n",
384: (loops_per_sec + 2500) / 500000,
385: ((loops_per_sec + 2500) / 5000) % 100);
386: #endif
387:
388: #if defined(__SMP__) && defined(__i386__)
389: smp_loops_per_tick = loops_per_sec / 400;
390: #endif
391: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.