source: soft/giet_vm/sys/drivers.c @ 252

Last change on this file since 252 was 249, checked in by alain, 11 years ago

Various modifications to support IO Bridge,
and MEMC configuration interface.

File size: 57.6 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : drivers.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The drivers.c and drivers.h files are part ot the GIET-VM nano kernel.
8// They contains the drivers for the peripherals available in the SoCLib library:
9// - vci_multi_tty
10// - vci_multi_timer
11// - vci_multi_dma
12// - vci_multi_icu
13// - vci_xicu & vci_multi_icu
14// - vci_gcd
15// - vci_frame_buffer
16// - vci_block_device
17//
18// For the peripherals replicated in each cluster (ICU, TIMER, DMA),
19// the corresponding (virtual) base addresses must be completed by an offset
20// depending on the cluster index.
21//
22// The following global parameter must be defined in the giet_config.h file:
23// - GIET_CLUSTER_INCREMENT
24//
25// The following global parameters must be defined in the hard_config.h file:
26// - NB_CLUSTERS   
27// - NB_PROCS_MAX 
28// - NB_TIM_CHANNELS   
29// - NB_DMA_CHANNELS     
30// - NB_TTY_CHANNELS_MAX   
31//
32// The following virtual base addresses must be defined in the giet_vsegs.ld file:
33// - seg_icu_base
34// - seg_tim_base
35// - seg_dma_base
36// - seg_tty_base
37// - seg_gcd_base
38// - seg_fbf_base
39// - seg_ioc_base
40// - seg_nic_base
41// - seg_cma_base
42// - seg_iob_base
43// - seg_mmc_base
44//
45///////////////////////////////////////////////////////////////////////////////////
46
47#include <vm_handler.h>
48#include <sys_handler.h>
49#include <giet_config.h>
50#include <drivers.h>
51#include <common.h>
52#include <hwr_mapping.h>
53#include <mips32_registers.h>
54#include <ctx_handler.h>
55
56#if !defined(NB_CLUSTERS)
57# error: You must define NB_CLUSTERS in the hard_config.h file
58#endif
59
60#if (NB_CLUSTERS > 256)
61# error: NB_CLUSTERS cannot be larger than 256!
62#endif
63
64#if !defined(NB_PROCS_MAX)
65# error: You must define NB_PROCS_MAX in the hard_config.h file
66#endif
67
68#if (NB_PROCS_MAX > 8)
69# error: NB_PROCS_MAX cannot be larger than 8!
70#endif
71
72#if !defined(GIET_CLUSTER_INCREMENT)
73# error: You must define GIET_CLUSTER_INCREMENT in the giet_config.h file
74#endif
75
76#if !defined(GIET_USE_IOMMU)
77# error: You must define GIET_USE_IOMMU in the giet_config.h file
78#endif
79
80#if !defined(NB_TTY_CHANNELS)
81# error: You must define NB_TTY_CHANNELS in the hard_config.h file
82#endif
83
84#if (NB_TTY_CHANNELS < 1)
85# error: NB_TTY_CHANNELS cannot be smaller than 1!
86#endif
87
88#if !defined(NB_DMA_CHANNELS)
89# error: You must define NB_DMA_CHANNELS in the hard_config.h file
90#endif
91
92#if (NB_DMA_CHANNELS > 8)
93# error: NB_DMA_CHANNELS cannot be smaller than 8!
94#endif
95
96#if !defined(NB_TIM_CHANNELS)
97#define NB_TIM_CHANNELS 0
98#endif
99
100#if ( (NB_TIM_CHANNELS + NB_PROC_MAX) > 32 )
101# error: NB_TIM_CHANNELS + NB_PROCS_MAX cannot be larger than 32
102#endif
103
104#if !defined(NB_IOC_CHANNELS)
105# error: You must define NB_IOC_CHANNELS in the hard_config.h file
106#endif
107
108#if ( NB_IOC_CHANNELS > 8 )
109# error: NB_IOC_CHANNELS cannot be larger than 8
110#endif
111
112#if !defined(NB_NIC_CHANNELS)
113# error: You must define NB_NIC_CHANNELS in the hard_config.h file
114#endif
115
116#if ( NB_NIC_CHANNELS > 8 )
117# error: NB_NIC_CHANNELS cannot be larger than 8
118#endif
119
120#if !defined(NB_CMA_CHANNELS)
121# error: You must define NB_CMA_CHANNELS in the hard_config.h file
122#endif
123
124#if ( NB_CMA_CHANNELS > 8 )
125# error: NB_CMA_CHANNELS cannot be larger than 8
126#endif
127
128#if !defined( USE_XICU )
129# error: You must define USE_XICU in the hard_config.h file
130#endif
131
132#if !defined( USE_IOB )
133# error: You must define USE_IOB in the hard_config.h file
134#endif
135
136
137#define in_unckdata __attribute__((section (".unckdata")))
138
139//////////////////////////////////////////////////////////////////////////////
140//     Timers driver
141//////////////////////////////////////////////////////////////////////////////
142// This peripheral is replicated in all clusters.
143// The timers can be implemented in a vci_timer component or in a vci_xicu
144// component (depending on the USE_XICU parameter).
145// There is one timer (or xicu) component per cluster.
146// There is two types of timers:
147// - "system" timers : one per processor, used for context switch.
148//   local_id in [0, NB_PROCS_MAX-1],
149// - "user" timers : requested by the task in the mapping_info data structure.
150//   For each user timer, the timer_id is stored in the context of the task.
151// The global index is cluster_id * (NB_PROCS_MAX+NB_TIM_CHANNELS) + local_id
152//////////////////////////////////////////////////////////////////////////////
153// The (virtual) base address of the associated segment is:
154//
155//       timer_address = seg_icu_base + cluster_id * GIET_CLUSTER_INCREMENT
156//
157// - cluster id is an explicit argument of all access functions
158// - seg_icu_base must be defined in the giet_vsegs.ld file
159// - GIET_CLUSTER_INCREMENT must be defined in the giet_config.h file
160////////////////////////////////////////////////////////////////////////////////
161
162// User Timer signaling variables
163
164#if (NB_TIM_CHANNELS > 0)
165in_unckdata volatile unsigned char _user_timer_event[NB_CLUSTERS * NB_TIM_CHANNELS] 
166                            = { [0 ... ((NB_CLUSTERS * NB_TIM_CHANNELS) - 1)] = 0 };
167#endif
168
169//////////////////////////////////////////////////////////////////////////////
170//     _timer_start()
171// This function activates a timer in the vci_timer (or vci_xicu) component
172// by writing in the proper register the period value.
173// It can be used by both the kernel to initialise a "system" timer,
174// or by a task (through a system call) to configure an "user" timer.
175// Returns 0 if success, > 0 if error.
176//////////////////////////////////////////////////////////////////////////////
177unsigned int _timer_start( unsigned int cluster_id, 
178                           unsigned int local_id, 
179                           unsigned int period) 
180{
181    // parameters checking
182    if (cluster_id >= NB_CLUSTERS)  return 1;
183    if (local_id >= NB_TIM_CHANNELS)  return 2;
184
185#if USE_XICU
186    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base + 
187                                                     (cluster_id * GIET_CLUSTER_INCREMENT));
188
189    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = period;
190#else
191    unsigned int* timer_address = (unsigned int *) ((char *) &seg_tim_base + 
192                                                    (cluster_id * GIET_CLUSTER_INCREMENT));
193
194    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
195    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0x3;
196#endif
197    return 0;
198}
199
200//////////////////////////////////////////////////////////////////////////////
201//     _timer_stop()
202// This function desactivates a timer in the vci_timer (or vci_xicu) component
203// by writing in the proper register.
204// Returns 0 if success, > 0 if error.
205//////////////////////////////////////////////////////////////////////////////
206unsigned int _timer_stop( unsigned int cluster_id, 
207                          unsigned int local_id) 
208{
209    // parameters checking
210    if (cluster_id >= NB_CLUSTERS)  return 1;
211    if (local_id >= NB_TIM_CHANNELS)  return 2;
212
213#if USE_XICU
214    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base + 
215                                                     (cluster_id * GIET_CLUSTER_INCREMENT));
216
217    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
218#else
219    unsigned int* timer_address = (unsigned int *) ((char *) &seg_tim_base + 
220                                                    (cluster_id * GIET_CLUSTER_INCREMENT));
221
222    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
223#endif
224    return 0;
225}
226
227
228//////////////////////////////////////////////////////////////////////////////
229//     _timer_reset_irq()
230// This function acknowlegge a timer interrupt in the vci_timer (or vci_xicu)
231// component by reading/writing in the proper register.
232// It can be used by both the isr_switch() for a "system" timer,
233// or by the _isr_timer() for an "user" timer.
234// Returns 0 if success, > 0 if error.
235//////////////////////////////////////////////////////////////////////////////
236unsigned int _timer_reset_irq( unsigned int cluster_id, 
237                               unsigned int local_id ) 
238{
239    // parameters checking
240    if (cluster_id >= NB_CLUSTERS)  return 1;
241    if (local_id >= NB_TIM_CHANNELS)  return 2;
242
243#if USE_XICU
244    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base +
245                                                     (cluster_id * GIET_CLUSTER_INCREMENT));
246
247    unsigned int bloup = timer_address[XICU_REG(XICU_PTI_ACK, local_id)];
248    bloup++; // to avoid a warning
249#else
250    unsigned int * timer_address = (unsigned int *) ((char *) &seg_tim_base + 
251            (cluster_id * GIET_CLUSTER_INCREMENT));
252
253    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
254#endif
255    return 0;
256}
257
258
259
260///////////////////////////////////////////////////////////////////////
261// _timer_reset_irq_cpt()
262///////////////////////////////////////////////////////////////////////
263// This function resets the period at the end of which
264// an interrupt is sent. To do so, we re-write the period
265// ini the proper register, what causes the count to restart.
266// The period value is read from the same (TIMER_PERIOD) register,
267// this is why in appearance we do nothing useful (read a value
268// from a register and write this value in the same register)
269// This function is called during a context switch (user or preemptive)
270///////////////////////////////////////////////////////////////////////
271unsigned int _timer_reset_irq_cpt(unsigned int cluster_id, unsigned int local_id) {
272    // parameters checking
273    if (cluster_id >= NB_CLUSTERS) {
274        return 1;
275    }
276    if (local_id >= NB_TIM_CHANNELS) {
277        return 2;
278    }
279
280#if USE_XICU
281    unsigned int * timer_address = (unsigned int *) ((char *) &seg_icu_base + (cluster_id * GIET_CLUSTER_INCREMENT));
282    unsigned int timer_period = timer_address[XICU_REG(XICU_PTI_PER, local_id)];
283
284    // we write 0 first because if the timer is currently running, the corresponding timer counter is not reset
285    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
286    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = timer_period;
287#else
288    // We suppose that the TIMER_MODE register value is 0x3
289    unsigned int * timer_address = (unsigned int *) ((char *) &seg_tim_base + (cluster_id * GIET_CLUSTER_INCREMENT));
290    unsigned int timer_period = timer_address[local_id * TIMER_SPAN + TIMER_PERIOD];
291
292    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = timer_period;
293#endif
294
295    return 0;
296}
297
298
299/////////////////////////////////////////////////////////////////////////////////
300//     VciMultiTty driver
301/////////////////////////////////////////////////////////////////////////////////
302// There is only one multi_tty controler in the architecture.
303// The total number of TTYs is defined by the configuration parameter NB_TTY_CHANNELS.
304// The "system" terminal is TTY[0].
305// The "user" TTYs are allocated to applications by the GIET in the boot phase,
306// as defined in the mapping_info data structure. The corresponding tty_id must
307// be stored in the context of the task by the boot code.
308// The TTY address is : seg_tty_base + tty_id*TTY_SPAN
309/////////////////////////////////////////////////////////////////////////////////
310
311// TTY variables
312in_unckdata volatile unsigned char _tty_get_buf[NB_TTY_CHANNELS];
313in_unckdata volatile unsigned char _tty_get_full[NB_TTY_CHANNELS] 
314                                     = { [0 ... NB_TTY_CHANNELS - 1] = 0 };
315in_unckdata unsigned int _tty_put_lock = 0;  // protect kernel TTY[0]
316
317////////////////////////////////////////////////////////////////////////////////
318//      _tty_error()
319////////////////////////////////////////////////////////////////////////////////
320void _tty_error(unsigned int tty_id, unsigned int task_id) 
321{
322    unsigned int proc_id = _procid();
323
324    _get_lock(&_tty_put_lock);
325    if (tty_id == 0xFFFFFFFF) _puts("\n[GIET ERROR] no TTY assigned to the task ");
326    else                      _puts("\n[GIET ERROR] TTY index too large for task ");
327    _putd(task_id);
328    _puts(" on processor ");
329    _putd(proc_id);
330    _puts("\n");
331    _release_lock(&_tty_put_lock);
332}
333
334
335/////////////////////////////////////////////////////////////////////////////////
336//      _tty_write()
337// Write one or several characters directly from a fixed-length user buffer to
338// the TTY_WRITE register of the TTY controler.
339// It doesn't use the TTY_PUT_IRQ interrupt and the associated kernel buffer.
340// This is a non blocking call: it tests the TTY_STATUS register, and stops
341// the transfer as soon as the TTY_STATUS[WRITE] bit is set.
342// The function returns  the number of characters that have been written.
343/////////////////////////////////////////////////////////////////////////////////
344unsigned int _tty_write(const char * buffer, 
345                        unsigned int length) 
346{
347    unsigned int nwritten;
348    unsigned int tty_id = _get_context_slot(CTX_TTY_ID);
349    unsigned int* tty_address = (unsigned int *) &seg_tty_base;
350
351    for (nwritten = 0; nwritten < length; nwritten++) 
352    {
353        // check tty's status
354        if ((tty_address[tty_id * TTY_SPAN + TTY_STATUS] & 0x2) == 0x2) break;
355        tty_address[tty_id * TTY_SPAN + TTY_WRITE] = (unsigned int) buffer[nwritten];
356    }
357    return nwritten;
358}
359
360//////////////////////////////////////////////////////////////////////////////
361//      _tty_read()
362// This non-blocking function uses the TTY_GET_IRQ[tty_id] interrupt and
363// the associated kernel buffer, that has been written by the ISR.
364// It get the TTY terminal index from the context of the current task.
365// It fetches one single character from the _tty_get_buf[tty_id] kernel
366// buffer, writes this character to the user buffer, and resets the
367// _tty_get_full[tty_id] buffer.
368// The length argument is not used.
369// Returns 0 if the kernel buffer is empty, 1 if the buffer is full.
370//////////////////////////////////////////////////////////////////////////////
371unsigned int _tty_read(char * buffer, 
372                       unsigned int length) 
373{
374    unsigned int tty_id = _get_context_slot(CTX_TTY_ID);
375
376    if (_tty_get_full[tty_id] == 0) 
377    {
378        return 0;
379    }
380    else 
381    {
382        *buffer = _tty_get_buf[tty_id];
383        _tty_get_full[tty_id] = 0;
384        return 1;
385    }
386}
387
388////////////////////////////////////////////////////////////////////////////////
389//     _tty_get_char()
390// This function is used by the _isr_tty to read a character in the TTY
391// terminal defined by the tty_id argument. The character is stored
392// in requested buffer, and the IRQ is acknowledged.
393// Returns 0 if success, 1 if tty_id too large.
394////////////////////////////////////////////////////////////////////////////////
395unsigned int _tty_get_char(unsigned int tty_id, 
396                           unsigned char * buffer) 
397{
398    // checking argument
399    if (tty_id >= NB_TTY_CHANNELS) { return 1; }
400
401    // compute terminal base address
402    unsigned int * tty_address = (unsigned int *) &seg_tty_base; 
403
404    *buffer = (unsigned char) tty_address[tty_id * TTY_SPAN + TTY_READ];
405    return 0;
406}
407
408
409////////////////////////////////////////////////////////////////////////////////
410//     VciMultiIcu or VciXicu driver
411////////////////////////////////////////////////////////////////////////////////
412// This hardware component is replicated in all clusters.
413// There is one vci_multi_icu (or vci_xicu) component per cluster,
414// and the number of independant ICUs is equal to NB_PROCS_MAX,
415// because there is one private interrupt controler per processor.
416////////////////////////////////////////////////////////////////////////////////
417// The (virtual) base address of the associated segment is:
418//
419//       icu_address = seg_icu_base + cluster_id * GIET_CLUSTER_INCREMENT
420//
421// - cluster id is an explicit argument of all access functions
422// - seg_icu_base must be defined in the giet_vsegs.ld file
423// - GIET_CLUSTER_INCREMENT must be defined in the giet_config.h file
424////////////////////////////////////////////////////////////////////////////////
425
426////////////////////////////////////////////////////////////////////////////////
427//     _icu_set_mask()
428// This function can be used with both the vci_xicu & vci_multi_icu components.
429// It set the mask register for the ICU channel identified by the cluster index
430// and the processor index: all '1' bits are set / all '0' bits are not modified.
431// Returns 0 if success, > 0 if error.
432////////////////////////////////////////////////////////////////////////////////
433unsigned int _icu_set_mask( unsigned int cluster_id,
434                            unsigned int proc_id,
435                            unsigned int value,
436                            unsigned int is_timer) 
437{
438    // parameters checking
439    if (cluster_id >= NB_CLUSTERS) return 1; 
440    if (proc_id >= NB_PROCS_MAX)   return 1; 
441
442    unsigned int * icu_address = (unsigned int *) ((char *) &seg_icu_base + 
443                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
444#if USE_XICU
445    if (is_timer) 
446    {
447        icu_address[XICU_REG(XICU_MSK_PTI_ENABLE, proc_id)] = value;
448    }
449    else 
450    {
451        icu_address[XICU_REG(XICU_MSK_HWI_ENABLE, proc_id)] = value;
452    }
453#else
454    icu_address[proc_id * ICU_SPAN + ICU_MASK_SET] = value; 
455#endif
456    return 0;
457}
458
459
460////////////////////////////////////////////////////////////////////////////////
461//     _icu_get_index()
462// This function can be used with both the vci_xicu & vci_multi_icu components.
463// It returns the index of the highest priority (smaller index) active HWI.
464// The ICU channel is identified by the cluster index and the processor index.
465// Returns 0 if success, > 0 if error.
466////////////////////////////////////////////////////////////////////////////////
467unsigned int _icu_get_index( unsigned int cluster_id, 
468                             unsigned int proc_id, 
469                             unsigned int * buffer) 
470{
471    // parameters checking
472    if (cluster_id >= NB_CLUSTERS)  return 1;
473    if (proc_id >= NB_PROCS_MAX)    return 1;
474
475    unsigned int * icu_address = (unsigned int *) ((char *) &seg_icu_base + 
476                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
477#if USE_XICU
478    unsigned int prio = icu_address[XICU_REG(XICU_PRIO, proc_id)];
479    unsigned int pti_ok = (prio & 0x00000001);
480    unsigned int hwi_ok = (prio & 0x00000002);
481    unsigned int swi_ok = (prio & 0x00000004);
482    unsigned int pti_id = (prio & 0x00001F00) >> 8;
483    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
484    unsigned int swi_id = (prio & 0x1F000000) >> 24;
485    if      (pti_ok) { *buffer = pti_id; }
486    else if (hwi_ok) { *buffer = hwi_id; }
487    else if (swi_ok) { *buffer = swi_id; }
488    else             { *buffer = 32; }
489#else
490    *buffer = icu_address[proc_id * ICU_SPAN + ICU_IT_VECTOR]; 
491#endif
492    return 0;
493}
494
495
496////////////////////////////////////////////////////////////////////////////////
497//     VciGcd driver
498////////////////////////////////////////////////////////////////////////////////
499// The Greater Dommon Divider is a -very- simple hardware coprocessor
500// performing the computation of the GCD of two 32 bits integers.
501// It has no DMA capability.
502////////////////////////////////////////////////////////////////////////////////
503
504////////////////////////////////////////////////////////////////////////////////
505//     _gcd_write()
506// Write a 32-bit word in a memory mapped register of the GCD coprocessor.
507// Returns 0 if success, > 0 if error.
508////////////////////////////////////////////////////////////////////////////////
509unsigned int _gcd_write( unsigned int register_index, 
510                         unsigned int value) 
511{
512    // parameters checking
513    if (register_index >= GCD_END)  return 1; 
514
515    unsigned int * gcd_address = (unsigned int *) &seg_gcd_base;
516
517    gcd_address[register_index] = value; // write word
518    return 0;
519}
520
521
522////////////////////////////////////////////////////////////////////////////////
523//     _gcd_read()
524// Read a 32-bit word in a memory mapped register of the GCD coprocessor.
525// Returns 0 if success, > 0 if error.
526////////////////////////////////////////////////////////////////////////////////
527unsigned int _gcd_read( unsigned int register_index, 
528                        unsigned int * buffer ) 
529{
530    // parameters checking
531    if (register_index >= GCD_END)  return 1;
532
533    unsigned int * gcd_address = (unsigned int *) &seg_gcd_base;
534
535    *buffer = gcd_address[register_index]; // read word
536    return 0;
537}
538
539////////////////////////////////////////////////////////////////////////////////
540// VciBlockDevice driver
541////////////////////////////////////////////////////////////////////////////////
542// The VciBlockDevice is a single channel external storage contrÃŽler.
543//
544// The IOMMU can be activated or not:
545//
546// 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to
547// the IOC peripheral, in the I/O virtual space, and the user buffer is
548// dynamically remapped in the IOMMU page table. The corresponding entry
549// in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable.
550// The number of pages to be unmapped is stored in the _ioc_npages variable.
551// The number of PT2 entries is dynamically computed and stored in the
552// kernel _ioc_iommu_npages variable. It cannot be larger than 512.
553// The user buffer is unmapped by the _ioc_completed() function when
554// the transfer is completed.
555//
556// 2/ If the IOMMU is not used, we check that  the user buffer is mapped to a
557// contiguous physical buffer (this is generally true because the user space
558// page tables are statically constructed to use contiguous physical memory).
559//
560// Finally, the memory buffer must fulfill the following conditions:
561// - The user buffer must be word aligned,
562// - The user buffer must be mapped in user address space,
563// - The user buffer must be writable in case of (to_mem) access,
564// - The total number of physical pages occupied by the user buffer cannot
565//   be larger than 512 pages if the IOMMU is activated,
566// - All physical pages occupied by the user buffer must be contiguous
567//   if the IOMMU is not activated.
568// An error code is returned if these conditions are not verified.
569//
570// As the IOC component can be used by several programs running in parallel,
571// the _ioc_lock variable guaranties exclusive access to the device.  The
572// _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock.
573// and set _ioc_lock to a non zero value.  The _ioc_write() and _ioc_read()
574// functions are blocking, polling the _ioc_lock variable until the device is
575// available.
576// When the tranfer is completed, the ISR routine activated by the IOC IRQ
577// set the _ioc_done variable to a non-zero value. Possible address errors
578// detected by the IOC peripheral are reported by the ISR in the _ioc_status
579// variable.
580// The _ioc_completed() function is polling the _ioc_done variable, waiting for
581// transfer completion. When the completion is signaled, the _ioc_completed()
582// function reset the _ioc_done variable to zero, and releases the _ioc_lock
583// variable.
584//
585// In a multi-processing environment, this polling policy should be replaced by
586// a descheduling policy for the requesting process.
587///////////////////////////////////////////////////////////////////////////////
588
589// IOC global variables
590in_unckdata volatile unsigned int _ioc_status= 0;
591in_unckdata volatile unsigned int _ioc_done = 0;
592in_unckdata unsigned int _ioc_lock = 0;
593in_unckdata unsigned int _ioc_iommu_ix1 = 0;
594in_unckdata unsigned int _ioc_iommu_npages; 
595
596///////////////////////////////////////////////////////////////////////////////
597//      _ioc_access()
598// This function transfer data between a memory buffer and the block device.
599// The buffer lentgth is (count*block_size) bytes.
600// Arguments are:
601// - to_mem     : from external storage to memory when non 0
602// - lba        : first block index on the external storage.
603// - user_vaddr : virtual base address of the memory buffer.
604// - count      : number of blocks to be transfered.
605// Returns 0 if success, > 0 if error.
606///////////////////////////////////////////////////////////////////////////////
607unsigned int _ioc_access( unsigned int to_mem,
608                          unsigned int lba,
609                          unsigned int user_vaddr,
610                          unsigned int count) 
611{
612    unsigned int user_vpn_min;     // first virtuel page index in user space
613    unsigned int user_vpn_max;     // last virtual page index in user space
614    unsigned int vpn;              // current virtual page index in user space
615    unsigned int ppn;              // physical page number
616    unsigned int flags;            // page protection flags
617    unsigned int ix2;              // page index in IOMMU PT1 page table
618    unsigned int ppn_first;        // first physical page number for user buffer
619    unsigned int buf_xaddr = 0;    // user buffer virtual address in IO space (if IOMMU)
620    paddr_t      buf_paddr = 0;    // user buffer physical address (if no IOMMU),
621
622    // check buffer alignment
623    if ((unsigned int) user_vaddr & 0x3)
624    {
625        _get_lock(&_tty_put_lock);
626        _puts("[GIET ERROR] in _ioc_access() : user buffer not word aligned\n");
627        _release_lock(&_tty_put_lock);
628        return 1; 
629    }
630
631    unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;
632
633    unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
634    unsigned int length = count * block_size;
635
636    // get user space page table virtual address
637    unsigned int user_pt_vbase = _get_context_slot(CTX_PTAB_ID);
638
639    user_vpn_min = user_vaddr >> 12;
640    user_vpn_max = (user_vaddr + length - 1) >> 12;
641
642    // loop on all virtual pages covering the user buffer
643    for (vpn = user_vpn_min, ix2 = 0 ; 
644         vpn <= user_vpn_max ; 
645         vpn++, ix2++ ) 
646    {
647        // get ppn and flags for each vpn
648        unsigned int ko = _v2p_translate((page_table_t *) user_pt_vbase,
649                                          vpn,
650                                          &ppn,
651                                          &flags);
652        // check access rights
653        if (ko)
654        {
655            _get_lock(&_tty_put_lock);
656            _puts("[GIET ERROR] in _ioc_access() : user buffer unmapped\n");
657            _release_lock(&_tty_put_lock);
658            return 1; 
659        }
660        if ((flags & PTE_U) == 0) 
661        {
662            _get_lock(&_tty_put_lock);
663            _puts("[GIET ERROR] in _ioc_access() : user buffer not in user space\n");
664            _release_lock(&_tty_put_lock);
665            return 1; 
666        }
667        if (((flags & PTE_W) == 0 ) && to_mem)
668        {
669            _get_lock(&_tty_put_lock);
670            _puts("[GIET ERROR] in _ioc_access() : user buffer not writable\n");
671            _release_lock(&_tty_put_lock);
672            return 1; 
673        }
674
675        // save first ppn value
676        if (ix2 == 0) ppn_first = ppn;
677
678        if ( GIET_USE_IOMMU && USE_IOB ) // user buffer remapped in the I/0 space
679        {
680            // check buffer length < 2 Mbytes
681            if (ix2 > 511) 
682            {
683                _get_lock(&_tty_put_lock);
684                _puts("[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n");
685                _release_lock(&_tty_put_lock);
686                return 1; 
687            }
688
689            // map the physical page in IOMMU page table
690            _iommu_add_pte2( _ioc_iommu_ix1,    // PT1 index
691                             ix2,               // PT2 index
692                             ppn,               // Physical page number   
693                             flags);            // Protection flags
694
695            // compute user buffer virtual adress in IO space
696            buf_xaddr = (_ioc_iommu_ix1) << 21 | (user_vaddr & 0xFFF);
697        }
698        else            // No IOMMU
699        {
700            // check that physical pages are contiguous
701            if ((ppn - ppn_first) != ix2) 
702            {
703                _get_lock(&_tty_put_lock);
704                _puts("[GIET ERROR] in _ioc_access() : split physical user buffer\n");
705                _release_lock(&_tty_put_lock);
706                return 1; 
707            }
708
709            // compute user buffer physical adress
710            buf_paddr = (((paddr_t)ppn_first) << 12) | (user_vaddr & 0xFFF);
711        }
712    } // end for vpn
713
714    // register the number of pages to be unmapped
715    _ioc_iommu_npages = (user_vpn_max - user_vpn_min) + 1;
716
717    // invalidate local data cache in case of memory write
718    if (to_mem) _dcache_buf_invalidate((void *) user_vaddr, length);
719
720#if GIET_DEBUG_IOC_DRIVER
721_get_lock(&_tty_put_lock);
722_puts("\n[GIET DEBUG]  IOC_ACCESS at cycle ");
723_putd( _proctime() );
724_puts("\n - proc_id         = ");
725_putd( _procid() );
726_puts("\n - ioc_vbase       = ");
727_putx( (unsigned int)ioc_address );
728_puts("\n - psched_vbase    = ");
729_putx( (unsigned int)_get_sched() );
730_puts("\n - pt_vbase        = ");
731_putx( user_pt_vbase );
732_puts("\n - user_buf_vbase  = ");
733_putx( user_vaddr );
734_puts("\n - user_buf_length = ");
735_putx( length );
736_puts("\n - user_buf_paddr  = ");
737_putl( buf_paddr );
738_puts("\n - user_buf_xaddr  = ");
739_putx( buf_xaddr );
740_puts("\n");
741_release_lock(&_tty_put_lock);
742#endif
743
744    // Invalidate L2 cache if IO Bridge is used
745    if ( to_mem && USE_IOB ) _memc_inval( buf_paddr, length );
746   
747    // get the lock on ioc device
748    _get_lock(&_ioc_lock);
749
750    // peripheral configuration 
751    if ( GIET_USE_IOMMU && USE_IOB ) 
752    {
753        ioc_address[BLOCK_DEVICE_BUFFER] = buf_xaddr;
754    }
755    else
756    {
757        ioc_address[BLOCK_DEVICE_BUFFER]     = (unsigned int)buf_paddr;
758        ioc_address[BLOCK_DEVICE_BUFFER_EXT] = (unsigned int)(buf_paddr>>32);
759    }
760    ioc_address[BLOCK_DEVICE_COUNT] = count;
761    ioc_address[BLOCK_DEVICE_LBA] = lba;
762    if (to_mem == 0) 
763    {
764        ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
765    }
766    else 
767    {
768        ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
769    }
770    return 0;
771}
772
773/////////////////////////////////////////////////////////////////////////////////
774// _ioc_completed()
775//
776// This function checks completion of an I/O transfer and reports errors.
777// As it is a blocking call, the processor is stalled.
778// If the virtual memory is activated, the pages mapped in the I/O virtual
779// space are unmapped, and the IOB TLB is cleared.
780// Returns 0 if success, > 0 if error.
781/////////////////////////////////////////////////////////////////////////////////
782unsigned int _ioc_completed() 
783{
784    unsigned int ret;
785    unsigned int ix2;
786
787    // busy waiting
788    while (_ioc_done == 0) { asm volatile("nop"); }
789
790#if GIET_DEBUG_IOC_DRIVER
791_get_lock(&_tty_put_lock);
792_puts("\n[GIET DEBUG]  IOC_COMPLETED at cycle ");
793_putd( _proctime() );
794_puts("\n - proc_id         = ");
795_putd( _procid() );
796_puts("\n");
797_release_lock(&_tty_put_lock);
798#endif
799
800    // unmap the buffer from IOMMU page table if IOMMU is activated
801    if ( GIET_USE_IOMMU && USE_IOB ) 
802    {
803        unsigned int * iob_address = (unsigned int *) &seg_iob_base;
804
805        for (ix2 = 0; ix2 < _ioc_iommu_npages; ix2++) 
806        {
807            // unmap the page in IOMMU page table
808            _iommu_inval_pte2(
809                    _ioc_iommu_ix1, // PT1 index
810                    ix2 );          // PT2 index
811
812            // clear IOMMU TLB
813            iob_address[IOB_INVAL_PTE] = (_ioc_iommu_ix1 << 21) | (ix2 << 12); 
814        }
815    }
816
817    // test IOC status
818    if ((_ioc_status != BLOCK_DEVICE_READ_SUCCESS)
819            && (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS)) ret = 1; // error
820    else                                                    ret = 0; // success
821
822    // reset synchronization variables
823    _ioc_done = 0;
824    asm volatile("sync");
825    _ioc_lock = 0;
826
827    return ret;
828}
829
830
831///////////////////////////////////////////////////////////////////////////////
832//     _ioc_read()
833// Transfer data from the block device to a memory buffer in user space.
834// - lba    : first block index on the block device
835// - buffer : base address of the memory buffer (must be word aligned)
836// - count  : number of blocks to be transfered.
837// Returns 0 if success, > 0 if error.
838///////////////////////////////////////////////////////////////////////////////
839unsigned int _ioc_read( unsigned int lba, 
840                        void * buffer, 
841                        unsigned int count) 
842{
843    return _ioc_access(
844            1,        // read access
845            lba,
846            (unsigned int) buffer,
847            count);
848}
849
850
851///////////////////////////////////////////////////////////////////////////////
852//     _ioc_write()
853// Transfer data from a memory buffer in user space to the block device.
854// - lba    : first block index on the block device
855// - buffer : base address of the memory buffer (must be word aligned)
856// - count  : number of blocks to be transfered.
857// Returns 0 if success, > 0 if error.
858///////////////////////////////////////////////////////////////////////////////
859unsigned int _ioc_write( unsigned int lba, 
860                         const void * buffer, 
861                         unsigned int count) 
862{
863    return _ioc_access(
864            0, // write access
865            lba,
866            (unsigned int) buffer,
867            count);
868}
869
870
871///////////////////////////////////////////////////////////////////////////////
872//     _ioc_get_status()
873// This function returns the transfert status, and acknowledge the IRQ.
874// Returns 0 if success, > 0 if error.
875///////////////////////////////////////////////////////////////////////////////
876unsigned int _ioc_get_status(unsigned int * status) 
877{
878    // get IOC base address
879    unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
880
881    *status = ioc_address[BLOCK_DEVICE_STATUS]; // read status & reset IRQ
882    return 0;
883}
884
885
886///////////////////////////////////////////////////////////////////////////////
887//     _ioc_get_block_size()
888// This function returns the block_size with which the IOC has been configured.
889///////////////////////////////////////////////////////////////////////////////
890unsigned int _ioc_get_block_size() 
891{
892    // get IOC base address
893    unsigned int * ioc_address = (unsigned int *) &seg_ioc_base;
894   
895    return  ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
896}
897
898
899//////////////////////////////////////////////////////////////////////////////////
900// VciMultiDma driver
901//////////////////////////////////////////////////////////////////////////////////
902// The DMA controllers are physically distributed in the clusters.
903// There is  (NB_CLUSTERS * NB_DMA_CHANNELS) channels, indexed by a global index:
904//        dma_id = cluster_id * NB_DMA_CHANNELS + loc_id
905//
906// As a DMA channel is a private ressource allocated to a task,
907// there is no lock protecting exclusive access to the channel.
908// The signalisation between the OS and the DMA uses the _dma_done[dma_id]
909// synchronisation variables  (set by the ISR, and reset by the OS).
910// The transfer status is copied by the ISR in the _dma_status[dma_id] variables.
911//////////////////////////////////////////////////////////////////////////////////
912// The (virtual) base address of the associated segment is:
913//
914//       dma_address = seg_dma_base + cluster_id * GIET_CLUSTER_INCREMENT
915//
916// - seg_dma_base  must be defined in the giet_vsegs.ld file
917// - GIET_CLUSTER_INCREMENT  must be defined in the giet_config.h file
918////////////////////////////////////////////////////////////////////////////////
919
920#if NB_DMA_CHANNELS > 0
921
922// in_unckdata unsigned int            _dma_lock[NB_DMA_CHANNELS * NB_CLUSTERS]
923// = { [0 ... (NB_DMA_CHANNELS * NB_CLUSTERS) - 1] = 0 };
924
925in_unckdata volatile unsigned int    _dma_done[NB_DMA_CHANNELS * NB_CLUSTERS] 
926        = { [0 ... (NB_DMA_CHANNELS * NB_CLUSTERS) - 1] = 0 };
927in_unckdata volatile unsigned int _dma_status[NB_DMA_CHANNELS * NB_CLUSTERS];
928in_unckdata unsigned int _dma_iommu_ix1 = 1;
929in_unckdata unsigned int _dma_iommu_npages[NB_DMA_CHANNELS * NB_CLUSTERS];
930#endif
931
932//////////////////////////////////////////////////////////////////////////////////
933// _dma_reset_irq()
934//////////////////////////////////////////////////////////////////////////////////
935unsigned int _dma_reset_irq( unsigned int cluster_id, 
936                             unsigned int channel_id) 
937{
938#if NB_DMA_CHANNELS > 0
939    // parameters checking
940    if (cluster_id >= NB_CLUSTERS)  return 1;
941    if (channel_id >= NB_DMA_CHANNELS)  return 1; 
942
943    // compute DMA base address
944    unsigned int * dma_address = (unsigned int *) ((char *) &seg_dma_base + 
945                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
946
947    dma_address[channel_id * DMA_SPAN + DMA_RESET] = 0;           
948    return 0;
949#else
950    return -1;
951#endif
952}
953
954
955//////////////////////////////////////////////////////////////////////////////////
956// _dma_get_status()
957//////////////////////////////////////////////////////////////////////////////////
958unsigned int _dma_get_status( unsigned int cluster_id, 
959                              unsigned int channel_id, 
960                              unsigned int * status) 
961{
962#if NB_DMA_CHANNELS > 0
963    // parameters checking
964    if (cluster_id >= NB_CLUSTERS)  return 1;
965    if (channel_id >= NB_DMA_CHANNELS)  return 1;
966
967    // compute DMA base address
968    unsigned int * dma_address = (unsigned int *) ((char *) &seg_dma_base + 
969                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
970
971    *status = dma_address[channel_id * DMA_SPAN + DMA_LEN];
972    return 0;
973#else
974    return -1;
975#endif
976}
977
978
979//////////////////////////////////////////////////////////////////////////////////
980// _dma_transfer()
981// Transfer data between a user buffer and a device buffer using DMA.
982// Only one device type is supported: Frame Buffer (dev_type == 0)
983// Arguments are:
984// - dev_type     : device type.
985// - to_user      : from  device buffer to user buffer when true.
986// - offset       : offset (in bytes) in the device buffer.
987// - user_vaddr   : virtual base address of the user buffer.
988// - length       : number of bytes to be transfered.
989//
990// The cluster_id and channel_id are obtained from task context (CTX_DMA_ID).
991// The user buffer must be mapped in user address space and word-aligned.
992// The user buffer length must be multiple of 4 bytes.
993// We compute the physical base addresses for both the device buffer
994// and the user buffer before programming the DMA transfer.
995// The GIET being fully static, we don't need to split the transfer in 4 Kbytes
996// pages, because the user buffer is contiguous in physical space.
997// Returns 0 if success, > 0 if error.
998//////////////////////////////////////////////////////////////////////////////////
999unsigned int _dma_transfer( unsigned int dev_type,
1000                            unsigned int to_user,
1001                            unsigned int offset,
1002                            unsigned int user_vaddr,
1003                            unsigned int length ) 
1004{
1005#if NB_DMA_CHANNELS > 0
1006    unsigned int ko;           // unsuccessfull V2P translation
1007    unsigned int device_vbase; // device buffer vbase address
1008    unsigned int flags;        // protection flags
1009    unsigned int ppn;          // physical page number
1010    paddr_t      user_pbase;   // user buffer pbase address
1011    paddr_t      device_pbase; // frame buffer pbase address
1012
1013    // check user buffer address and length alignment
1014    if ((user_vaddr & 0x3) || (length & 0x3)) 
1015    {
1016        _get_lock(&_tty_put_lock);
1017        _puts("\n[GIET ERROR] in _dma_transfer : user buffer not word aligned\n");
1018        _release_lock(&_tty_put_lock);
1019        return 1;
1020    }
1021
1022    // get DMA channel and compute DMA vbase address
1023    unsigned int dma_id      = _get_context_slot(CTX_DMA_ID);
1024    if ( dma_id == 0xFFFFFFFF )
1025    {
1026        _get_lock(&_tty_put_lock);
1027        _puts("\n[GIET ERROR] in _dma_transfer : no DMA channel allocated\n");
1028        _release_lock(&_tty_put_lock);
1029        return 1;
1030    }
1031    unsigned int cluster_id  = dma_id / NB_DMA_CHANNELS;
1032    unsigned int channel_id  = dma_id % NB_DMA_CHANNELS;
1033    unsigned int * dma_vbase  = (unsigned int *) ((char *) &seg_dma_base + 
1034                                                (cluster_id * GIET_CLUSTER_INCREMENT));
1035    // get page table address
1036    unsigned int user_ptab = _get_context_slot(CTX_PTAB_ID);
1037
1038    // get devic buffer virtual address, depending on peripheral type
1039    if (dev_type == 0) 
1040    {
1041        device_vbase = (unsigned int) &seg_fbf_base + offset;
1042    }
1043    else 
1044    {
1045        _get_lock(&_tty_put_lock);
1046        _puts("\n[GIET ERROR] in _dma_transfer : device type not supported\n");
1047        _release_lock(&_tty_put_lock);
1048        return 1;
1049    }
1050
1051    // get device buffer physical address
1052    ko = _v2p_translate( (page_table_t*) user_ptab, 
1053                         (device_vbase >> 12), 
1054                         &ppn, 
1055                         &flags );
1056    if (ko) 
1057    {
1058        _get_lock(&_tty_put_lock);
1059        _puts("\n[GIET ERROR] in _dma_transfer : device buffer unmapped\n");
1060        _release_lock(&_tty_put_lock);
1061        return 1;
1062    }
1063    device_pbase = ((paddr_t)ppn << 12) | (device_vbase & 0x00000FFF);
1064
1065    // Compute user buffer physical address
1066    ko = _v2p_translate( (page_table_t*) user_ptab, 
1067                         (user_vaddr >> 12), 
1068                         &ppn, 
1069                         &flags );
1070    if (ko) 
1071    {
1072        _get_lock(&_tty_put_lock);
1073        _puts("\n[GIET ERROR] in _dma_transfer() : user buffer unmapped\n");
1074        _release_lock(&_tty_put_lock);
1075        return 1;
1076    } 
1077    if ((flags & PTE_U) == 0) 
1078    {
1079        _get_lock(&_tty_put_lock);
1080        _puts("[GIET ERROR] in _dma_transfer() : user buffer not in user space\n");
1081        _release_lock(&_tty_put_lock);
1082        return 1; 
1083    }
1084    if (((flags & PTE_W) == 0 ) && to_user) 
1085    {
1086        _get_lock(&_tty_put_lock);
1087        _puts("\n[GIET ERROR] in _dma_transfer() : user buffer not writable\n");
1088        _release_lock(&_tty_put_lock);
1089        return 1;
1090    }
1091    user_pbase = (((paddr_t)ppn) << 12) | (user_vaddr & 0x00000FFF);
1092
1093/*  This is a draft for IOMMU support
1094
1095    // loop on all virtual pages covering the user buffer
1096    unsigned int user_vpn_min = user_vaddr >> 12;
1097    unsigned int user_vpn_max = (user_vaddr + length - 1) >> 12;
1098    unsigned int ix2          = 0;
1099    unsigned int ix1          = _dma_iommu_ix1 + dma_id;
1100
1101    for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ )
1102    {
1103    // get ppn and flags for each vpn
1104    unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase,
1105    vpn,
1106    &ppn,
1107    &flags );
1108
1109    // check access rights
1110    if ( ko )                                 return 3;     // unmapped
1111    if ( (flags & PTE_U) == 0 )               return 4;     // not in user space
1112    if ( ( (flags & PTE_W) == 0 ) && to_user ) return 5;     // not writable
1113
1114    // save first ppn value
1115    if ( ix2 == 0 ) ppn_first = ppn;
1116
1117    if ( GIET_USE_IOMMU && USE_IOB )    // user buffer remapped in the I/0 space
1118    {
1119    // check buffer length < 2 Mbytes
1120    if ( ix2 > 511 ) return 2;
1121
1122    // map the physical page in IOMMU page table
1123    _iommu_add_pte2( ix1,        // PT1 index
1124    ix2,        // PT2 index
1125    ppn,        // physical page number
1126    flags );    // protection flags
1127    }
1128    else            // no IOMMU : check that physical pages are contiguous
1129    {
1130    if ( (ppn - ppn_first) != ix2 )       return 6;     // split physical buffer 
1131    }
1132
1133    // increment page index
1134    ix2++;
1135    } // end for vpn
1136
1137    // register the number of pages to be unmapped if iommu activated
1138    _dma_iommu_npages[dma_id] = (user_vpn_max - user_vpn_min) + 1;
1139
1140*/
1141
1142    // invalidate data cache in case of memory write
1143    if (to_user) _dcache_buf_invalidate((void *) user_vaddr, length);
1144
1145// get the lock
1146//  _get_lock(&_dma_lock[dma_id]);
1147
1148#if GIET_DEBUG_DMA_DRIVER
1149_get_lock(&_tty_put_lock);
1150_puts("\n[GIET DEBUG] DMA TRANSFER at cycle ");
1151_putd( _proctime() );
1152_puts("\n - cluster_id       = ");
1153_putx( cluster_id );
1154_puts("\n - channel_id       = ");
1155_putx( channel_id );
1156_puts("\n - dma_vbase        = ");
1157_putx( (unsigned int)dma_vbase );
1158_puts("\n - device_buf_vbase = ");
1159_putx( device_vbase );
1160_puts("\n - device_buf_pbase = ");
1161_putl( device_pbase );
1162_puts("\n - user_buf_vbase   = ");
1163_putx( user_vaddr );
1164_puts("\n - user_buf_pbase   = ");
1165_putl( user_pbase );
1166_puts("\n");
1167_release_lock(&_tty_put_lock);
1168#endif
1169
1170    // DMA configuration
1171    if (to_user) 
1172    {
1173        dma_vbase[channel_id * DMA_SPAN + DMA_SRC]     = (unsigned int)(device_pbase);
1174        dma_vbase[channel_id * DMA_SPAN + DMA_SRC_EXT] = (unsigned int)(device_pbase>>32);
1175        dma_vbase[channel_id * DMA_SPAN + DMA_DST]     = (unsigned int)(user_pbase);
1176        dma_vbase[channel_id * DMA_SPAN + DMA_DST_EXT] = (unsigned int)(user_pbase>>32);
1177    }
1178    else 
1179    {
1180        dma_vbase[channel_id * DMA_SPAN + DMA_SRC]     = (unsigned int)(user_pbase);
1181        dma_vbase[channel_id * DMA_SPAN + DMA_SRC_EXT] = (unsigned int)(user_pbase>>32);
1182        dma_vbase[channel_id * DMA_SPAN + DMA_DST]     = (unsigned int)(device_pbase);
1183        dma_vbase[channel_id * DMA_SPAN + DMA_DST_EXT] = (unsigned int)(device_pbase>>32);
1184    }
1185    dma_vbase[channel_id * DMA_SPAN + DMA_LEN] = (unsigned int) length;
1186
1187    return 0;
1188
1189#else // NB_DMA_CHANNELS == 0
1190    _get_lock(&_tty_put_lock);
1191    _puts("\n[GIET ERROR] in _dma_transfer() : NB_DMA_CHANNELS == 0");
1192    _release_lock(&_tty_put_lock);
1193    return 1;
1194#endif
1195
1196}  // end _dma_transfer() 
1197
1198
1199//////////////////////////////////////////////////////////////////////////////////
1200// _dma_completed()
1201// This function checks completion of a DMA transfer to or from a peripheral
1202// device (Frame Buffer or Multi-Nic).
1203// As it is a blocking call, the processor is busy waiting.
1204// Returns 0 if success, > 0 if error
1205// (1 == read error / 2 == DMA idle error / 3 == write error)
1206//////////////////////////////////////////////////////////////////////////////////
1207unsigned int _dma_completed() 
1208{
1209#if NB_DMA_CHANNELS > 0
1210    unsigned int dma_id  = _get_context_slot(CTX_DMA_ID);
1211    unsigned int dma_ret;
1212
1213    // busy waiting with a pseudo random delay between bus access
1214    while (_dma_done[dma_id] == 0) 
1215    {
1216        unsigned int delay = (( _proctime() ^ _procid() << 4) & 0x3F) + 1;
1217        asm volatile(
1218                "move  $3,   %0                 \n"
1219                "loop_nic_completed:            \n"
1220                "addi  $3,   $3, -1             \n"
1221                "bnez  $3,   loop_nic_completed \n"
1222                "nop                            \n"
1223                :
1224                : "r" (delay)
1225                : "$3"); 
1226    }
1227
1228#if GIET_DEBUG_DMA_DRIVER
1229_get_lock(&_tty_put_lock);
1230_puts("\n[GIET DEBUG] DMA COMPLETED at cycle ");
1231_putd( _proctime() );
1232_puts("\n - cluster_id       = ");
1233_putx( dma_id/NB_DMA_CHANNELS );
1234_puts("\n - channel_id       = ");
1235_putx( dma_id%NB_DMA_CHANNELS );
1236_puts("\n");
1237_release_lock(&_tty_put_lock);
1238#endif
1239
1240    // reset synchronization variables
1241    _dma_done[dma_id] = 0;
1242    dma_ret = _dma_status[dma_id];
1243    asm volatile("sync\n");
1244
1245//    _dma_lock[dma_id] = 0;
1246
1247    return dma_ret;
1248
1249#else // NB_DMA_CHANNELS == 0
1250    return -1;
1251#endif
1252
1253}  // end _dma_completed
1254
1255
1256//////////////////////////////////////////////////////////////////////////////////
1257//     VciFrameBuffer driver
1258//////////////////////////////////////////////////////////////////////////////////
1259// The vci_frame_buffer device can be accessed directly by software with memcpy(),
1260// or it can be accessed through a multi-channels DMA component:
1261// 
1262// The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to
1263// implement the transfer between a data buffer (user space) and the frame
1264// buffer (kernel space). They are blocking until completion of the transfer.
1265//
1266// The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the
1267// VciMultiDma components (distributed in the clusters) to transfer data
1268// between the user buffer and the frame buffer. A DMA channel is
1269// allocated to each task requesting it in the mapping_info data structure.
1270//////////////////////////////////////////////////////////////////////////////////
1271
1272//////////////////////////////////////////////////////////////////////////////////
1273// _fb_sync_write()
1274// Transfer data from an memory buffer to the frame_buffer device using a memcpy.
1275// - offset : offset (in bytes) in the frame buffer.
1276// - buffer : base address of the memory buffer.
1277// - length : number of bytes to be transfered.
1278//////////////////////////////////////////////////////////////////////////////////
1279
1280unsigned int _fb_sync_write(unsigned int offset, 
1281                            const void * buffer, 
1282                            unsigned int length) 
1283{
1284    unsigned char * fb_address = (unsigned char *) &seg_fbf_base + offset;
1285    memcpy((void *) fb_address, (void *) buffer, length);
1286    return 0;
1287}
1288
1289
1290//////////////////////////////////////////////////////////////////////////////////
1291// _fb_sync_read()
1292// Transfer data from the frame_buffer device to a memory buffer using a memcpy.
1293// - offset : offset (in bytes) in the frame buffer.
1294// - buffer : base address of the memory buffer.
1295// - length : number of bytes to be transfered.
1296//////////////////////////////////////////////////////////////////////////////////
1297unsigned int _fb_sync_read( unsigned int   offset, 
1298                            const void*    buffer, 
1299                            unsigned int   length) 
1300{
1301    unsigned char* fb_address = (unsigned char *) &seg_fbf_base + offset;
1302    memcpy((void *) buffer, (void *) fb_address, length);
1303    return 0;
1304}
1305
1306
1307//////////////////////////////////////////////////////////////////////////////////
1308// _fb_write()
1309// Transfer data from a memory buffer to the frame_buffer device using  DMA.
1310// - offset : offset (in bytes) in the frame buffer.
1311// - buffer : base address of the memory buffer.
1312// - length : number of bytes to be transfered.
1313// Returns 0 if success, > 0 if error.
1314//////////////////////////////////////////////////////////////////////////////////
1315unsigned int _fb_write( unsigned int   offset, 
1316                        const void*    buffer, 
1317                        unsigned int   length) 
1318{
1319    return _dma_transfer( 0,             // frame buffer
1320                          0,             // write
1321                          offset,
1322                          (unsigned int) buffer,
1323                          length );
1324}
1325
1326
1327//////////////////////////////////////////////////////////////////////////////////
1328// _fb_read()
1329// Transfer data from the frame_buffer device to a memory buffer using  DMA.
1330// - offset : offset (in bytes) in the frame buffer.
1331// - buffer : base address of the memory buffer.
1332// - length : number of bytes to be transfered.
1333// Returns 0 if success, > 0 if error.
1334//////////////////////////////////////////////////////////////////////////////////
1335unsigned int _fb_read( unsigned int   offset, 
1336                       const void*    buffer, 
1337                       unsigned int   length ) 
1338{
1339    return _dma_transfer( 0,    // frame buffer
1340                          1,    // read
1341                          offset,
1342                          (unsigned int) buffer,
1343                          length );
1344}
1345
1346
1347//////////////////////////////////////////////////////////////////////////////////
1348// _fb_completed()
1349// This function checks completion of a DMA transfer to or fom the frame buffer.
1350// As it is a blocking call, the processor is busy waiting.
1351// Returns 0 if success, > 0 if error
1352// (1 == read error / 2 == DMA idle error / 3 == write error)
1353//////////////////////////////////////////////////////////////////////////////////
1354unsigned int _fb_completed() 
1355{
1356    return _dma_completed();
1357}
1358
1359//////////////////////////////////////////////////////////////////////////////////
1360//     VciMultiNic driver
1361//////////////////////////////////////////////////////////////////////////////////
1362// The VciMultiNic device can be accessed directly by software with memcpy(),
1363// or it can be accessed through a multi-channels DMA component:
1364// 
1365// The '_nic_sync_write' and '_nic_sync_read' functions use a memcpy strategy to
1366// implement the transfer between a data buffer (user space) and the NIC
1367// buffer (kernel space). They are blocking until completion of the transfer.
1368//
1369// The '_nic_write()', '_nic_read()' and '_nic_completed()' functions use the
1370// VciMultiDma components (distributed in the clusters) to transfer data
1371// between the user buffer and the NIC. A  NIDMA channel is allocated to each
1372// task requesting it in the mapping_info data structure.
1373//////////////////////////////////////////////////////////////////////////////////
1374
1375//////////////////////////////////////////////////////////////////////////////////
1376// _nic_sync_write()
1377// Transfer data from an memory buffer to the NIC device using a memcpy.
1378// - offset : offset (in bytes) in the frame buffer.
1379// - buffer : base address of the memory buffer.
1380// - length : number of bytes to be transfered.
1381//////////////////////////////////////////////////////////////////////////////////
1382unsigned int _nic_sync_write( unsigned int   offset, 
1383                              const void*    buffer, 
1384                              unsigned int   length ) 
1385{
1386    unsigned char* nic_address = (unsigned char *) &seg_nic_base + offset;
1387    memcpy((void *) nic_address, (void *) buffer, length);
1388    return 0;
1389}
1390
1391
1392//////////////////////////////////////////////////////////////////////////////////
1393// _nic_sync_read()
1394// Transfer data from the NIC device to a memory buffer using a memcpy.
1395// - offset : offset (in bytes) in the frame buffer.
1396// - buffer : base address of the memory buffer.
1397// - length : number of bytes to be transfered.
1398//////////////////////////////////////////////////////////////////////////////////
1399unsigned int _nic_sync_read(unsigned int offset, const void * buffer, unsigned int length) {
1400    unsigned char *nic_address = (unsigned char *) &seg_nic_base + offset;
1401    memcpy((void *) buffer, (void *) nic_address, length);
1402    return 0;
1403}
1404
1405
1406//////////////////////////////////////////////////////////////////////////////////
1407// _nic_write()
1408// Transfer data from a memory buffer to the NIC device using  DMA.
1409// - offset : offset (in bytes) in the frame buffer.
1410// - buffer : base address of the memory buffer.
1411// - length : number of bytes to be transfered.
1412// Returns 0 if success, > 0 if error.
1413//////////////////////////////////////////////////////////////////////////////////
1414unsigned int _nic_write(unsigned int offset, const void * buffer, unsigned int length) {
1415    return _dma_transfer(
1416            1,            // NIC
1417            0,            // write
1418            offset,
1419            (unsigned int) buffer,
1420            length );   
1421}
1422
1423
1424//////////////////////////////////////////////////////////////////////////////////
1425// _nic_read()
1426// Transfer data from the NIC device to a memory buffer using  DMA.
1427// - offset : offset (in bytes) in the frame buffer.
1428// - buffer : base address of the memory buffer.
1429// - length : number of bytes to be transfered.
1430// Returns 0 if success, > 0 if error.
1431//////////////////////////////////////////////////////////////////////////////////
1432unsigned int _nic_read(unsigned int offset, const void * buffer, unsigned int length) {
1433    return _dma_transfer(
1434            1,            // NIC
1435            1,            // read
1436            offset,
1437            (unsigned int) buffer,
1438            length );   
1439}
1440
1441
1442//////////////////////////////////////////////////////////////////////////////////
1443// _nic_completed()
1444// This function checks completion of a DMA transfer to or fom a NIC channel.
1445// As it is a blocking call, the processor is busy waiting.
1446// Returns 0 if success, > 0 if error
1447// (1 == read error / 2 == DMA idle error / 3 == write error)
1448//////////////////////////////////////////////////////////////////////////////////
1449unsigned int _nic_completed() 
1450{
1451    return _dma_completed();
1452}
1453
1454//////////////////////////////////////////////////////////////////////////////////
1455//     VciMemCache driver
1456//////////////////////////////////////////////////////////////////////////////////
1457// The VciMemCache device can be accessed through a configuration interface.
1458// as a set of uncached, memory mapped registers.
1459///////////////////////////////////////////////////////////////////////////////////
1460
1461///////////////////////////////////////////////////////////////////////////////////
1462// _memc_inval()
1463// This function invalidate all cache lines covering a memory buffer defined
1464// by the physical base address, and the length.
1465// The buffer address MSB are used to compute the cluster index.
1466///////////////////////////////////////////////////////////////////////////////////
1467void _memc_inval( paddr_t      buf_paddr,
1468                  unsigned int buf_length )
1469{
1470    unsigned int cluster_id    = (unsigned int)((buf_paddr>>32)/(256/NB_CLUSTERS));
1471
1472    unsigned int * mmc_address = (unsigned int *) ((char *) &seg_mmc_base + 
1473                                                   (cluster_id * GIET_CLUSTER_INCREMENT));
1474
1475    // get the lock protecting exclusive access to MEMC
1476    while ( mmc_address[MEMC_LOCK] ) { asm volatile("nop"); }
1477
1478    // write inval arguments
1479    mmc_address[MEMC_ADDR_LO]    = (unsigned int)buf_paddr;
1480    mmc_address[MEMC_ADDR_HI]    = (unsigned int)(buf_paddr>>32);
1481    mmc_address[MEMC_BUF_LENGTH] = buf_length;
1482    mmc_address[MEMC_CMD_TYPE]   = MEMC_CMD_INVAL;
1483
1484    // release the lock protecting MEMC
1485    mmc_address[MEMC_LOCK] = 0;
1486}
1487///////////////////////////////////////////////////////////////////////////////////
1488// _heap_info()
1489// This function returns the information associated to a heap (size and vaddr)
1490// It uses the global task index (CTX_GTID_ID, unique for each giet task) and the
1491// vspace index (CTX_VSID_ID) defined in the task context.
1492///////////////////////////////////////////////////////////////////////////////////
1493unsigned int _heap_info( unsigned int* vaddr, 
1494                         unsigned int* size ) 
1495{
1496    mapping_header_t * header  = (mapping_header_t *) (&seg_mapping_base);
1497    mapping_task_t * tasks     = _get_task_base(header);
1498    mapping_vobj_t * vobjs     = _get_vobj_base(header);
1499    mapping_vspace_t * vspaces = _get_vspace_base(header);
1500
1501    unsigned int taskid        = _get_context_slot(CTX_GTID_ID);
1502    unsigned int vspaceid      = _get_context_slot(CTX_VSID_ID);
1503
1504    int heap_local_vobjid      = tasks[taskid].heap_vobjid;
1505    if (heap_local_vobjid != -1) 
1506    {
1507        unsigned int vobjheapid = heap_local_vobjid + vspaces[vspaceid].vobj_offset;
1508        *vaddr                  = vobjs[vobjheapid].vaddr;
1509        *size                   = vobjs[vobjheapid].length;
1510        return 0;
1511    }
1512    else 
1513    {
1514        *vaddr = 0;
1515        *size = 0;
1516        return 0;
1517    }
1518}
1519
1520// Local Variables:
1521// tab-width: 4
1522// c-basic-offset: 4
1523// c-file-offsets:((innamespace . 0)(inline-open . 0))
1524// indent-tabs-mode: nil
1525// End:
1526// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1527
Note: See TracBrowser for help on using the repository browser.