source: soft/giet_vm/sys/kernel_init.c @ 172

Last change on this file since 172 was 169, checked in by alain, 12 years ago

Introducing support for FBDMA (Frame Buffer using DMA)

File size: 23.2 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : kernel_init.c
3// Date     : 26/05/2012
4// Authors  : alain greiner & mohamed karaoui
5// Copyright (c) UPMC-LIP6
6////////////////////////////////////////////////////////////////////////////////////
7// The kernel_init.c files is part of the GIET-VM nano-kernel.
8// It contains the kernel entry point for the second phase of system initialisation:
9// all processors are jumping to _kernel_init, but P[0] is first because other
10// processors are blocked until P[0] complete initilisation of task contexts,
11// vobjs and peripherals.
12// All procs in this phase have their MMU activated, because each processor P[i]
13// must initialise registers SP, SR, PTPR and EPC with informations stored
14// in _scheduler[i].
15////////////////////////////////////////////////////////////////////////////////////
16
17#include <common.h>
18#include <ctx_handler.h>
19#include <sys_handler.h>
20#include <mapping_info.h>
21#include <giet_config.h>
22#include <mips32_registers.h>
23#include <irq_handler.h>
24#include <vm_handler.h>
25#include <hwr_mapping.h>
26#include <mwmr_channel.h>
27#include <barrier.h>
28#include <drivers.h>
29
30#define in_kinit __attribute__((section (".kinit")))
31 
32///////////////////////////////////////////////////////////////////////////////////
33// array of pointers on the page tables
34// (both physical and virtual addresses)
35///////////////////////////////////////////////////////////////////////////////////
36
37__attribute__((section (".kdata"))) unsigned int _kernel_ptabs_paddr[GIET_NB_VSPACE_MAX]; 
38__attribute__((section (".kdata"))) unsigned int _kernel_ptabs_vaddr[GIET_NB_VSPACE_MAX]; 
39
40///////////////////////////////////////////////////////////////////////////////////
41// declarations required to avoid forward references
42///////////////////////////////////////////////////////////////////////////////////
43
44void    _kernel_vobjs_init(void);
45void    _kernel_tasks_init(void);
46void    _kernel_peripherals_init(void);
47void    _kernel_interrupt_vector_init(void);
48void    _kernel_start_all_procs(void);
49
50//////////////////////////////////////////////////////////////////////////////////
51// This function is the entry point for the second step of the boot sequence.
52//////////////////////////////////////////////////////////////////////////////////
53in_kinit void _kernel_init()
54{
55    // values to be written in registers
56    unsigned int        sp_value;
57    unsigned int        sr_value;
58    unsigned int        ptpr_value;
59    unsigned int        epc_value;
60
61    unsigned int        pid =   _procid();
62
63    // only processor 0 executes system initialisation
64    if ( pid == 0 )
65    {
66        _kernel_vobjs_init();
67        _kernel_tasks_init();
68        _kernel_interrupt_vector_init();
69        _kernel_peripherals_init();
70        _kernel_start_all_procs();
71    }
72
73    // each processor initialises it's SP, SR, PTPR, and EPC registers
74    // from values defined in _scheduler[pid], starts it's private
75    // context switch timer (if there is more than one task allocated)
76    // and jumps to user code.
77    // It does nothing, and keep idle if no task allocated.
78
79    static_scheduler_t*  sched = &_scheduler[pid];
80
81    if ( sched->tasks )         // at leat one task allocated
82    {
83        // initialise registers
84        sp_value   = sched->context[0][CTX_SP_ID];
85        sr_value   = sched->context[0][CTX_SR_ID];
86        ptpr_value = sched->context[0][CTX_PTPR_ID];
87        epc_value  = sched->context[0][CTX_EPC_ID];
88
89        // start TICK timer
90        if ( sched->tasks > 1 )
91        {
92            unsigned int cluster_id = pid / NB_PROCS;
93            unsigned int proc_id    = pid % NB_PROCS;
94           _timer_write( cluster_id, proc_id, TIMER_PERIOD, GIET_TICK_VALUE );
95           _timer_write( cluster_id, proc_id, TIMER_MODE  , 0x3 );
96        }
97    }
98    else                                        // no task allocated
99    {
100        _get_lock( &_tty_put_lock );
101        _puts("\n No task allocated to processor ");
102        _putw( pid );
103        _puts(" => keep idle\n");
104        _release_lock ( &_tty_put_lock );
105
106        // enable interrupts in kernel mode
107        asm volatile ( "li         $26, 0xFF01  \n"
108                       "mtc0   $26, $12     \n" 
109                       ::: "$26" );
110
111                // infinite loop in kernel mode
112        while (1) asm volatile("nop");
113    }
114
115    asm volatile (
116       "move    $29,    %0              \n"             /* SP <= ctx[CTX_SP_ID] */
117       "mtc0    %1,             $12             \n"             /* SR <= ctx[CTX_SR_ID] */
118       "mtc2    %2,             $0              \n"             /* PTPR <= ctx[CTX_PTPR_ID] */
119       "mtc0    %3,             $14             \n"             /* EPC <= ctx[CTX_EPC_ID] */
120       "eret                                    \n"             /* jump to user code */
121       "nop                                             \n"
122       :
123       : "r"(sp_value), "r"(sr_value), "r"(ptpr_value), "r"(epc_value) );
124
125} // end _kernel_init()
126
127//////////////////////////////////////////////////////////////////////////////////
128// This function wakeup all processors.
129// It should be executed by P[0] when the kernel initialisation is done.
130//////////////////////////////////////////////////////////////////////////////////
131in_kinit void _kernel_start_all_procs()
132{
133    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
134
135    _puts("\n[INIT] Starting parallel execution at cycle : ");
136    _putw( _proctime() );
137    _puts("\n");
138
139    header->signature = OUT_MAPPING_SIGNATURE;
140}
141
142//////////////////////////////////////////////////////////////////////////////////
143// _eret()
144// The address of this function is used to initialise the return address (RA)
145// in all task contexts (when the task has never been executed.
146//////////////////////////////////////////////////////////////////////////////////
147in_kinit void _eret()
148{
149    asm volatile("eret \n"
150                 "nop");
151}
152
153///////////////////////////////////////////////////////////////////////////////
154// This function maps a given task, defined in a given vspace
155// on the processor allocated in the mapping_info structure,
156// and initialises the task context.
157// There is one scheduler per processor, and processor can be shared
158// by several applications running in different vspaces.
159// There is one private context array handled by each scheduler.
160//
161// The following values must be initialised in all task contexts:
162// - sp     stack pointer = stack_base + stack_length
163// - ra     return address = &_eret
164// - epc    start address = start_vector[task->startid]
165// - sr     status register = OxFF13
166// - tty    TTY terminal index (global index)
167// - fb     FB_DMA channel index (global index)
168// - ptpr   page table base address / 8K
169// - mode   mmu_mode = 0xF (TLBs and caches activated)
170// - ptab   page table virtual address
171////////////////////////////////////////////////////////////////////////////////
172in_kinit void _task_map( unsigned int   task_id,    // global index
173                                         unsigned int   vspace_id,  // global index
174                         unsigned int   tty_id,         // TTY index
175                         unsigned int   fbdma_id )  // FBDMA index
176{
177    mapping_header_t*   header = (mapping_header_t*)&seg_mapping_base; 
178
179    mapping_task_t*     task   = _get_task_base(header);
180    mapping_vspace_t*   vspace = _get_vspace_base(header);
181    mapping_vobj_t*     vobj   = _get_vobj_base( header );
182
183   
184    // values to be initialised in task context
185    unsigned int                ra   = (unsigned int)&_eret;
186    unsigned int                sr   = 0x0000FF13; 
187    unsigned int                tty  = tty_id; 
188    unsigned int                fb   = fbdma_id;         
189    unsigned int                ptpr = _kernel_ptabs_paddr[vspace_id] >> 13;
190    unsigned int                ptab = _kernel_ptabs_vaddr[vspace_id];
191    unsigned int                mode = 0xF;
192    unsigned int                sp;
193    unsigned int                epc;     
194
195    // EPC : Get the (virtual) base address of the start_vector containing
196    // the start addresses for all tasks defined in a vspace.
197    mapping_vobj_t* vobj_data = &vobj[vspace[vspace_id].vobj_offset + 
198                                      vspace[vspace_id].start_offset]; 
199    unsigned int* start_vector = (unsigned int*)vobj_data->vaddr;
200    epc  = start_vector[task[task_id].startid];
201
202    // SP :  Get the vobj containing the stack
203    unsigned int vobj_id = task[task_id].vobjlocid + vspace[vspace_id].vobj_offset;
204    sp = vobj[vobj_id].vaddr + vobj[vobj_id].length;
205
206    // compute global processor index
207    unsigned int proc_id = task[task_id].clusterid * NB_PROCS + task[task_id].proclocid;
208
209    // compute and check local task index
210    unsigned int ltid = _scheduler[proc_id].tasks;
211    if ( ltid >= GIET_NB_TASKS_MAX )
212    {
213        _puts("\n[INIT ERROR] : too much tasks allocated to processor ");
214        _putw( proc_id );
215        _puts("\n");
216        _exit();
217    }
218   
219    // update number of tasks allocated to scheduler
220    _scheduler[proc_id].tasks = ltid + 1;
221
222    // initializes the task context
223    _scheduler[proc_id].context[ltid][CTX_SR_ID]    = sr;
224    _scheduler[proc_id].context[ltid][CTX_SP_ID]    = sp;
225    _scheduler[proc_id].context[ltid][CTX_RA_ID]    = ra;
226    _scheduler[proc_id].context[ltid][CTX_EPC_ID]   = epc;
227    _scheduler[proc_id].context[ltid][CTX_PTPR_ID]  = ptpr;
228    _scheduler[proc_id].context[ltid][CTX_MODE_ID]  = mode;
229    _scheduler[proc_id].context[ltid][CTX_TTY_ID]   = tty;
230        _scheduler[proc_id].context[ltid][CTX_FBDMA_ID] = fb;
231    _scheduler[proc_id].context[ltid][CTX_PTAB_ID]  = ptab;
232    _scheduler[proc_id].context[ltid][CTX_TASK_ID]  = task_id;
233   
234#if INIT_DEBUG_CTX
235_puts("Task ");
236_puts( task[task_id].name );
237_puts(" allocated to processor ");
238_putw( proc_id );
239_puts(" / ltid = ");
240_putw( ltid );
241_puts("\n");
242
243_puts("  - SR          = ");
244_putw( sr );
245_puts("  saved at ");
246_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SR_ID] );
247_puts("\n");
248
249_puts("  - RA          = ");
250_putw( ra );
251_puts("  saved at ");
252_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_RA_ID] );
253_puts("\n");
254
255_puts("  - SP          = ");
256_putw( sp );
257_puts("  saved at ");
258_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_SP_ID] );
259_puts("\n");
260
261_puts("  - EPC         = ");
262_putw( epc );
263_puts("  saved at ");
264_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_EPC_ID] );
265_puts("\n");
266
267_puts("  - PTPR        = ");
268_putw( ptpr<<13 );
269_puts("  saved at ");
270_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTPR_ID] );
271_puts("\n");
272
273_puts("  - TTY         = ");
274_putw( tty );
275_puts("  saved at ");
276_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_TTY_ID] );
277_puts("\n");
278
279_puts("  - FB          = ");
280_putw( fb );
281_puts("  saved at ");
282_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_FBDMA_ID] );
283_puts("\n");
284
285_puts("  - PTAB        = ");
286_putw( ptab );
287_puts("  saved at ");
288_putw( (unsigned int)&_scheduler[proc_id].context[ltid][CTX_PTAB_ID] );
289_puts("\n");
290#endif
291
292} // end _task_map()
293
294///////////////////////////////////////////////////////////////////////////////
295// This function initializes all private vobjs defined in the vspaces,
296// such as mwmr channels, barriers and locks, depending on the vobj type.
297// (Most of the vobjs are not known, and not initialised by the compiler).
298// This function initialises the _kernel_ptabs_paddr[] array indexed by the vspace_id,
299// and containing the base addresses of all page tables.
300// This _kernel_ptabs_paddr[] array is used to initialise the task contexts.
301///////////////////////////////////////////////////////////////////////////////
302in_kinit void _kernel_vobjs_init()
303{
304    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
305    mapping_vspace_t*   vspace  = _get_vspace_base( header );     
306    mapping_vobj_t*     vobj    = _get_vobj_base( header );
307
308    unsigned int        vspace_id; 
309    unsigned int        vobj_id;
310
311    // loop on the vspaces
312    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
313    {
314        char ptab_found = 0;
315
316#if INIT_DEBUG_CTX
317_puts("[INIT] --- vobjs initialisation in vspace "); 
318_puts(vspace[vspace_id].name);
319_puts("\n");
320#endif
321        // loop on the vobjs
322            for(vobj_id= vspace[vspace_id].vobj_offset; 
323                        vobj_id < (vspace[vspace_id].vobj_offset+ vspace[vspace_id].vobjs);
324                        vobj_id++)
325            {
326            switch( vobj[vobj_id].type )
327            {
328                case VOBJ_TYPE_PTAB:    // initialise page table pointers array
329                {
330                    ptab_found = 1;
331                    _kernel_ptabs_paddr[vspace_id] = vobj[vobj_id].paddr;
332                    _kernel_ptabs_vaddr[vspace_id] = vobj[vobj_id].vaddr;
333
334#if INIT_DEBUG_CTX
335_puts("[INIT]   PTAB address = "); 
336_putw(_kernel_ptabs_paddr[vspace_id]); 
337_puts("\n");
338#endif
339                    break;
340                }
341                case VOBJ_TYPE_MWMR:    // storage capacity is (vobj.length/4 - 5) words
342                        {
343                    mwmr_channel_t* mwmr = (mwmr_channel_t*)(vobj[vobj_id].vaddr);
344                    mwmr->ptw   = 0;
345                    mwmr->ptr   = 0;
346                    mwmr->sts   = 0;
347                    mwmr->depth = (vobj[vobj_id].length>>2) - 5;
348                    mwmr->lock  = 0;
349#if INIT_DEBUG_CTX
350_puts("[INIT]   MWMR channel ");
351_puts( vobj->name);
352_puts(" / depth = ");
353_putw( mwmr->depth );
354_puts("\n");
355#endif
356                    break;
357                }
358                case VOBJ_TYPE_ELF:             // initialisation done by the loader
359                {
360
361#if INIT_DEBUG_CTX
362_puts("[INIT]   ELF section "); 
363_puts( vobj->name);
364_puts(" / length = ");
365_putw( vobj->length ); 
366_puts("\n");
367#endif
368                     break;
369                }
370                case VOBJ_TYPE_BARRIER: // init is the number of participants
371                {
372                    giet_barrier_t* barrier = (giet_barrier_t*)(vobj[vobj_id].vaddr);
373                    barrier->count = 0;
374                    barrier->init  = vobj[vobj_id].init;
375#if INIT_DEBUG_CTX
376_puts("   BARRIER "); 
377_puts( vobj->name);
378_puts(" / init_value = ");
379_putw( barrier->init );
380_puts("\n");
381#endif
382                    break;
383                }
384                case VOBJ_TYPE_LOCK:    // init is "not taken"
385                {
386                    unsigned int* lock = (unsigned int*)(vobj[vobj_id].vaddr);
387                    *lock = 0;
388#if INIT_DEBUG_CTX
389_puts("   LOCK "); 
390_puts( vobj->name);
391_puts("\n");
392#endif
393                    break;
394                }
395                case VOBJ_TYPE_BUFFER:  // nothing to do
396                {
397
398#if INIT_DEBUG_CTX
399_puts("   BUFFER "); 
400_puts( vobj->name);
401_puts(" / length = ");
402_putw( vobj->length ); 
403_puts("\n");
404#endif
405                    break;
406                }
407                default:
408                {
409                    _puts("\n[INIT ERROR] illegal vobj of name ");
410                    _puts(vobj->name);
411                    _puts(" / in vspace = ");
412                    _puts(vobj->name);
413                    _puts("\n ");
414                    _exit();
415                }
416            } // end switch type
417        } // end loop on vobjs
418        if( !ptab_found )
419        {
420            _puts("\n[INIT ERROR] Missing PTAB for vspace ");
421            _putw( vspace_id );
422            _exit();
423        }
424    } // end loop on vspaces
425
426    _puts("\n[INIT] Vobjs initialisation completed at cycle : ");
427    _putw( _proctime() );
428    _puts("\n");
429
430} // end _vobjs_init()
431
432///////////////////////////////////////////////////////////////////////////////
433// This function initialises all task contexts and processors schedulers.
434// It sets the default values for all schedulers (tasks <= 0, current <= 0).
435// Finally, it scan all tasks in all vspaces to initialise the schedulers,
436// and the tasks contexts, as defined in the mapping_info data structure.
437// A global TTY index and a global FB channel are allocated if required.
438// TTY[0] is reserved for the kernel.
439///////////////////////////////////////////////////////////////////////////////
440in_kinit void _kernel_tasks_init()
441{
442    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
443    mapping_cluster_t*  cluster = _get_cluster_base( header );
444    mapping_vspace_t*   vspace  = _get_vspace_base( header );     
445    mapping_task_t*     task    = _get_task_base( header );
446
447    unsigned int        base_tty_id = 1;     // TTY index allocator
448    unsigned int        base_fb_id  = 0;     // FB channel index allocator
449
450    unsigned int        cluster_id; 
451    unsigned int        proc_id; 
452    unsigned int        vspace_id; 
453    unsigned int        task_id;
454
455    // initialise the schedulers (not done by the compiler)
456    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
457    {
458        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
459        {
460            if ( proc_id >= NB_PROCS )
461            {
462                _puts("\n[INIT ERROR] The number of processors in cluster ");
463                _putw( cluster_id );
464                _puts(" is larger than NB_PROCS \n");
465                _exit();
466            }
467            _scheduler[cluster_id*NB_PROCS+proc_id].tasks   = 0;
468            _scheduler[cluster_id*NB_PROCS+proc_id].current = 0;
469        }
470    }
471
472    // loop on the virtual spaces
473    for ( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
474    {
475
476#if INIT_DEBUG_CTX
477_puts("\n[INIT] mapping tasks in vspace ");
478_puts(vspace[vspace_id].name);
479_puts("\n");
480#endif
481        // loop on the tasks
482        for ( task_id = vspace[vspace_id].task_offset ; 
483              task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks) ; 
484              task_id++ )
485        {
486            unsigned int        tty_id = 0xFFFFFFFF;
487            unsigned int        fb_id  = 0xFFFFFFFF;
488            if ( task[task_id].use_tty ) 
489            {
490                tty_id = base_tty_id;
491                base_tty_id++;
492            }
493            if ( task[task_id].use_fb  ) 
494            {
495                fb_id = base_fb_id;
496                base_fb_id++;
497            }
498            _task_map( task_id,                         // global task index
499                       vspace_id,                       // vspace index
500                       tty_id,                          // global tty index
501                       fb_id );                         // global fbdma index
502        } // end loop on tasks
503    } // end oop on vspaces
504
505    _puts("\n[INIT] Task Contexts initialisation completed at cycle ");
506    _putw( _proctime() );
507    _puts("\n");
508
509#if INIT_DEBUG_CTX
510for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
511{
512    _puts("\nCluster ");
513    _putw( cluster_id );
514    _puts("\n");
515    for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
516    {
517        unsigned int ltid;              // local task index
518        unsigned int gtid;              // global task index
519        unsigned int pid = cluster_id * NB_PROCS + proc_id;
520       
521        _puts(" - processor ");
522        _putw( pid );
523        _puts("\n");
524        for ( ltid = 0 ; ltid < _scheduler[pid].tasks ; ltid++ )
525        {
526            gtid = _scheduler[pid].context[ltid][CTX_TASK_ID];
527            _puts("    task : ");
528            _puts( task[gtid].name );
529            _puts("\n");
530        }
531    }
532}
533#endif
534
535} // end _kernel_task_init()
536
537////////////////////////////////////////////////////////////////////////////////
538// This function intializes the external periherals such as the IOB component
539// (I/O bridge, containing the IOMMU, the IOC (external disk controller),
540// the NIC (external network controller), the FBDMA (frame buffer controller),
541////////////////////////////////////////////////////////////////////////////////
542in_kinit void _kernel_peripherals_init()
543{
544    /////////////////////
545    // IOC peripheral
546    // we simply activate the IOC interrupts...
547    if ( NB_IOC )
548    {
549        unsigned int*   ioc_address = (unsigned int*)&seg_ioc_base;
550        ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
551    }
552   
553    /////////////////////
554    // FBDMA peripheral
555    // we simply activate the DMA interrupts...
556    if ( NB_DMAS )
557    {
558        unsigned int*   dma_address = (unsigned int*)&seg_dma_base;
559        dma_address[DMA_IRQ_DISABLE] = 0;
560    }
561
562    /////////////////////
563    // IOB peripheral
564    // must be initialised in case of IOMMU
565    if ( GIET_IOMMU_ACTIVE )
566    {
567        unsigned int*   iob_address = (unsigned int*)&seg_iob_base;
568
569        // define IPI address mapping the IOC interrupt ...TODO...
570
571        // set IOMMU page table address
572        iob_address[IOB_IOMMU_PTPR] = (unsigned int)(&_iommu_ptab);   
573
574        // activate IOMMU
575        iob_address[IOB_IOMMU_ACTIVE] = 1;   
576    } 
577
578    _puts("\n[INIT] Peripherals initialisation completed at cycle ");
579    _putw( _proctime() );
580    _puts("\n");
581
582} // end _kernel_peripherals_init()
583
584////////////////////////////////////////////////////////////////////////////////
585// This function intialises the interrupt vector, and initialises
586// the ICU mask registers for all processors in all clusters.
587// It strongly depends on the actual peripheral hardware wiring.
588// In this peculiar version, all clusters are identical,
589// the number of processors per cluster cannot be larger than 8.
590// Processor 0 handle all interrupts corresponding to TTYs, DMAs and IOC
591// (ICU inputs from from IRQ[8] to IRQ[31]). Only the 8 TIMER interrupts
592// (ICU iputs IRQ[0] to IRQ[7]), that are used for context switching
593// are distributed to the 8 processors.
594////////////////////////////////////////////////////////////////////////////////
595in_kinit void _kernel_interrupt_vector_init()
596{
597    mapping_header_t*   header  = (mapping_header_t*)&seg_mapping_base; 
598    mapping_cluster_t*  cluster = _get_cluster_base( header );
599
600    unsigned int cluster_id;
601    unsigned int proc_id;
602
603    // ICU mask values (up to 8 processors per cluster)
604    unsigned int icu_mask[8] = { 0xFFFFFF01,
605                                 0x00000002,
606                                 0x00000004,
607                                 0x00000008,
608                                 0x00000010,
609                                 0x00000020,
610                                 0x00000040,
611                                 0x00000080 };
612
613    // initialise ICUs for each processor in each cluster
614    for ( cluster_id = 0 ; cluster_id < header->clusters ; cluster_id++ )
615    {
616        for ( proc_id = 0 ; proc_id < cluster[cluster_id].procs ; proc_id++ )
617        {
618            _icu_write( cluster_id, proc_id, ICU_MASK_SET, icu_mask[proc_id] ); 
619        }
620    }
621
622    // initialize Interrupt vector
623
624    _interrupt_vector[0]   = &_isr_switch;
625    _interrupt_vector[1]   = &_isr_switch;
626    _interrupt_vector[2]   = &_isr_switch;
627    _interrupt_vector[3]   = &_isr_switch;
628    _interrupt_vector[4]   = &_isr_switch;
629    _interrupt_vector[5]   = &_isr_switch;
630    _interrupt_vector[6]   = &_isr_switch;
631    _interrupt_vector[7]   = &_isr_switch;
632
633    _interrupt_vector[8]   = &_isr_dma_0;
634    _interrupt_vector[9]   = &_isr_dma_1;
635    _interrupt_vector[10]  = &_isr_dma_2;
636    _interrupt_vector[11]  = &_isr_dma_3;
637    _interrupt_vector[12]  = &_isr_dma_4;
638    _interrupt_vector[13]  = &_isr_dma_5;
639    _interrupt_vector[14]  = &_isr_dma_6;
640    _interrupt_vector[15]  = &_isr_dma_7;
641
642    _interrupt_vector[16]  = &_isr_tty_get_0;
643    _interrupt_vector[17]  = &_isr_tty_get_1;
644    _interrupt_vector[18]  = &_isr_tty_get_2;
645    _interrupt_vector[19]  = &_isr_tty_get_3;
646    _interrupt_vector[20]  = &_isr_tty_get_4;
647    _interrupt_vector[21]  = &_isr_tty_get_5;
648    _interrupt_vector[22]  = &_isr_tty_get_6;
649    _interrupt_vector[23]  = &_isr_tty_get_7;
650    _interrupt_vector[24]  = &_isr_tty_get_8;
651    _interrupt_vector[25]  = &_isr_tty_get_9;
652    _interrupt_vector[26]  = &_isr_tty_get_10;
653    _interrupt_vector[27]  = &_isr_tty_get_11;
654    _interrupt_vector[28]  = &_isr_tty_get_12;
655    _interrupt_vector[29]  = &_isr_tty_get_13;
656    _interrupt_vector[30]  = &_isr_tty_get_14;
657
658    _interrupt_vector[31]  = &_isr_ioc;
659
660    _puts("\n[INIT] Interrupt vector initialisation completed at cycle ");
661    _putw( _proctime() );
662    _puts("\n");
663
664} // end _kernel_interrup_vector_init()
Note: See TracBrowser for help on using the repository browser.