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

Last change on this file since 213 was 213, checked in by karaoui, 12 years ago

fixing the case where NB_DMA_MAX==0
updating the libsrl.

File size: 42.7 KB
RevLine 
[158]1///////////////////////////////////////////////////////////////////////////////////
2// File     : drivers.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
[189]7// The drivers.c and drivers.h files are part ot the GIET-VM nano kernel.
[158]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
[203]13// - vci_xicu & vci_multi_icu
[158]14// - vci_gcd
15// - vci_frame_buffer
16// - vci_block_device
17//
18// The following global parameters must be defined in the giet_config.h file:
[204]19// - CLUSTER_IO_ID
20// - CLUSTER_SIZE
[189]21// - NB_CLUSTERS   
22// - NB_PROCS_MAX 
23// - NB_TIMERS_MAX   
24// - NB_DMAS_MAX     
25// - NB_TTYS   
[158]26//
[204]27// The following virtual base addresses must be defined in the giet.ld file:
[158]28// - seg_icu_base
[203]29// - seg_tim_base
[158]30// - seg_tty_base
31// - seg_gcd_base
32// - seg_dma_base
[203]33// - seg_fbf_base
[158]34// - seg_ioc_base
[204]35// As some peripherals can be replicated in the clusters (ICU, TIMER, DMA)
36// These addresses must be completed by an offset depending on the cluster index
37//    full_base_address = seg_***_base + cluster_id * CLUSTER_SIZE
[158]38///////////////////////////////////////////////////////////////////////////////////
39
[166]40#include <vm_handler.h>
[158]41#include <sys_handler.h>
42#include <giet_config.h>
43#include <drivers.h>
44#include <common.h>
45#include <hwr_mapping.h>
46#include <mips32_registers.h>
47#include <ctx_handler.h>
48
49#if !defined(NB_CLUSTERS)
[189]50# error: You must define NB_CLUSTERS in 'giet_config.h' file
[158]51#endif
[189]52
53#if !defined(NB_PROCS_MAX)
54# error: You must define NB_PROCS_MAX in 'giet_config.h' file
55#endif
56
57#if (NB_PROCS_MAX > 8)
58# error: NB_PROCS_MAX cannot be larger than 8!
59#endif
60
[204]61#if !defined(CLUSTER_SIZE)
62# error: You must define CLUSTER_SIZE in 'giet_config.h' file
[158]63#endif
[189]64
[158]65#if !defined(NB_TTYS)
[189]66# error: You must define NB_TTYS in 'giet_config.h' file
[158]67#endif
68
[165]69#if (NB_TTYS < 1)
70# error: NB_TTYS cannot be smaller than 1!
71#endif
72
[189]73#if !defined(NB_DMAS_MAX)
[205]74#define NB_DMAS_MAX 0
[165]75#endif
76
[189]77#if !defined(NB_TIMERS_MAX)
[205]78#define NB_TIMERS_MAX 0
[165]79#endif
80
[189]81#if ( (NB_TIMERS_MAX + NB_PROCS_MAX) > 32 )
82# error: NB_TIMERS_MAX + NB_PROCS_MAX cannot be larger than 32
83#endif
[165]84
[189]85#if !defined(NB_IOCS)
86# error: You must define NB_IOCS in 'giet_config.h' file
87#endif
[158]88
[189]89#if ( NB_IOCS > 1 )
90# error: NB_IOCS cannot be larger than 1
91#endif
[158]92
93
[189]94#define in_unckdata __attribute__((section (".unckdata")))
[169]95
[158]96//////////////////////////////////////////////////////////////////////////////
[203]97//      Timers driver
[158]98//////////////////////////////////////////////////////////////////////////////
[203]99// The timers can be implemented in a vci_timer component or in a vci_xicu
100// component (depending on the GIET_USE_XICU parameter).
101// There is one timer (or xicu) component per cluster.
[189]102// There is two types of timers:
103// - "system" timers : one per processor, used for context switch.
104//   local_id in [0, NB_PROCS_MAX-1],
105// - "user" timers : requested by the task in the mapping_info data structure.
[203]106//   local_id in [NB_PROC_MAX, NB_PROCS_MAX + NB_TIMERS_MAX - 1]
107//   For each user timer, the timer_id is stored in the context of the task.
108// The global index is cluster_id * (NB_PROCS_MAX+NB_TIMERS_MAX) + local_id
[158]109//////////////////////////////////////////////////////////////////////////////
110
[189]111// User Timer signaling variables
112
113#if (NB_TIMERS_MAX > 0)
114in_unckdata volatile unsigned char _user_timer_event[NB_CLUSTERS*NB_TIMERS_MAX] 
115         = { [0 ... ((NB_CLUSTERS*NB_TIMERS_MAX)-1)] = 0 };
116#endif
117
[158]118//////////////////////////////////////////////////////////////////////////////
[203]119//     _timer_start()
120// This function activates a timer in the vci_timer (or vci_xicu) component
121// by writing in the proper register the period value.
122// It can be used by both the kernel to initialise a "system" timer,
[189]123// or by a task (through a system call) to configure an "user" timer.
[158]124// Returns 0 if success, > 0 if error.
125//////////////////////////////////////////////////////////////////////////////
[203]126unsigned int _timer_start( unsigned int cluster_id,
127                           unsigned int local_id,
128                           unsigned int period )
[158]129{
[165]130    // parameters checking
[189]131    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
132    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
[158]133
[189]134#if GIET_USE_XICU
[204]135    unsigned int* timer_address = (unsigned int*)((char*)&seg_icu_base +
136                                  (cluster_id * CLUSTER_SIZE) );
[158]137
[203]138    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = period;
[189]139#else
[204]140    unsigned int* timer_address = (unsigned int*)((char*)&seg_tim_base + 
141                                  (cluster_id * CLUSTER_SIZE) );
[189]142
[203]143    timer_address[local_id * TIMER_SPAN + TIMER_PERIOD] = period;
144    timer_address[local_id * TIMER_SPAN + TIMER_MODE]   = 0x3;
[189]145#endif
146
[158]147    return 0;
148}
[189]149//////////////////////////////////////////////////////////////////////////////
[203]150//     _timer_stop()
151// This function desactivates a timer in the vci_timer (or vci_xicu) component
152// by writing in the proper register.
[189]153// Returns 0 if success, > 0 if error.
154//////////////////////////////////////////////////////////////////////////////
[203]155unsigned int _timer_stop( unsigned int  cluster_id,
156                          unsigned int  local_id )
[189]157{
[203]158    // parameters checking
159    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
160    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
[158]161
[203]162#if GIET_USE_XICU
[204]163    unsigned int* timer_address = (unsigned int*)((char*)&seg_icu_base +
164                                  (cluster_id * CLUSTER_SIZE) );
[203]165
166    timer_address[XICU_REG(XICU_PTI_PER, local_id)] = 0;
167#else
[204]168    unsigned int* timer_address = (unsigned int*)((char*)&seg_tim_base + 
169                                  (cluster_id * CLUSTER_SIZE) );
[203]170
171    timer_address[local_id * TIMER_SPAN + TIMER_MODE] = 0;
172#endif
173
174    return 0;
[189]175}
[158]176//////////////////////////////////////////////////////////////////////////////
[203]177//     _timer_reset_irq()
178// This function acknowlegge a timer interrupt in the vci_timer (or vci_xicu)
[204]179// component by reading/writing in the proper register.
[203]180// It can be used by both the isr_switch() for a "system" timer,
181// or by the _isr_timer() for an "user" timer.
[158]182// Returns 0 if success, > 0 if error.
183//////////////////////////////////////////////////////////////////////////////
[203]184unsigned int _timer_reset_irq( unsigned int     cluster_id,
185                               unsigned int     local_id )
[158]186{
[203]187    // parameters checking
188    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
189    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
[158]190
[203]191#if GIET_USE_XICU
[204]192    unsigned int* timer_address = (unsigned int*)((char*)&seg_icu_base +
193                                  (cluster_id * (unsigned)CLUSTER_SIZE) );
[203]194
195    unsigned int bloup = timer_address[XICU_REG(XICU_PTI_ACK, local_id)];
[204]196    bloup++;    // to avoid a warning
[203]197#else
[204]198    unsigned int* timer_address = (unsigned int*)((char*)&seg_tim_base + 
199                                  (cluster_id * CLUSTER_SIZE) );
[203]200
201    timer_address[local_id * TIMER_SPAN + TIMER_RESETIRQ] = 0;
202#endif
203
204    return 0;
[158]205}
206
207/////////////////////////////////////////////////////////////////////////////////
208//      VciMultiTty driver
209/////////////////////////////////////////////////////////////////////////////////
[189]210// There is only one multi_tty controler in the architecture.
[158]211// The total number of TTYs is defined by the configuration parameter NB_TTYS.
[189]212// The "system" terminal is TTY[0].
213// The "user" TTYs are allocated to applications by the GIET in the boot phase,
214// as defined in the mapping_info data structure. The corresponding tty_id must
215// be stored in the context of the task by the boot code.
216// The TTY address is : seg_tty_base + tty_id*TTY_SPAN
217/////////////////////////////////////////////////////////////////////////////////
[158]218
[189]219// TTY variables
220in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS];
221in_unckdata volatile unsigned char _tty_get_full[NB_TTYS] = { [0 ... NB_TTYS-1] = 0 };
222in_unckdata unsigned int           _tty_put_lock = 0;  // protect kernel TTY[0]
223
224////////////////////////////////////////////////////////////////////////////////
225//      _tty_error()
226////////////////////////////////////////////////////////////////////////////////
[199]227void _tty_error( unsigned int task_id )
[189]228{
229    unsigned int proc_id = _procid();
230
231    _get_lock(&_tty_put_lock);
232    _puts("\n[GIET ERROR] TTY index too large for task ");
[207]233    _putd( task_id );
[189]234    _puts(" on processor ");
[207]235    _putd( proc_id );
[189]236    _puts("\n");
237    _release_lock(&_tty_put_lock);
238}
239/////////////////////////////////////////////////////////////////////////////////
240//      _tty_write()
[158]241// Write one or several characters directly from a fixed-length user buffer to
242// the TTY_WRITE register of the TTY controler.
243// It doesn't use the TTY_PUT_IRQ interrupt and the associated kernel buffer.
244// This is a non blocking call: it tests the TTY_STATUS register, and stops
245// the transfer as soon as the TTY_STATUS[WRITE] bit is set.
246// The function returns  the number of characters that have been written.
[189]247/////////////////////////////////////////////////////////////////////////////////
[165]248unsigned int _tty_write( const char             *buffer, 
249                         unsigned int   length)
[158]250{
[189]251    unsigned int        nwritten;
[158]252
[199]253    unsigned int task_id  = _get_current_task_id();
254    unsigned int tty_id   = _get_context_slot(task_id, CTX_TTY_ID);
255
[189]256    if ( tty_id >= NB_TTYS )
257    {
[199]258        _tty_error( task_id );
[189]259        return 0;
260    }
[158]261
[204]262    unsigned int*       tty_address = (unsigned int*)( (char*)&seg_tty_base + 
263                                  (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) ); 
[158]264
265    for (nwritten = 0; nwritten < length; nwritten++)
266    {
[165]267        // check tty's status
[204]268        if ((tty_address[tty_id*TTY_SPAN + TTY_STATUS] & 0x2) == 0x2)
[158]269            break;
270        else
[165]271            // write character
[204]272            tty_address[tty_id*TTY_SPAN + TTY_WRITE] = (unsigned int)buffer[nwritten];
[158]273    }
274    return nwritten;
275}
276//////////////////////////////////////////////////////////////////////////////
[204]277//      _tty_read()
[158]278// This non-blocking function uses the TTY_GET_IRQ[tty_id] interrupt and
[165]279// the associated kernel buffer, that has been written by the ISR.
[204]280// It get the TTY terminal index from the context of the current task.
[158]281// It fetches one single character from the _tty_get_buf[tty_id] kernel
282// buffer, writes this character to the user buffer, and resets the
283// _tty_get_full[tty_id] buffer.
[204]284// The length argument is not used.
[158]285// Returns 0 if the kernel buffer is empty, 1 if the buffer is full.
286//////////////////////////////////////////////////////////////////////////////
[204]287unsigned int _tty_read( char                    *buffer, 
288                        unsigned int    length)
[158]289{
[199]290    unsigned int task_id  = _get_current_task_id();
291    unsigned int tty_id   = _get_context_slot(task_id, CTX_TTY_ID);
[158]292
[189]293    if ( tty_id >= NB_TTYS )
294    {
[199]295        _tty_error( task_id );
[189]296        return 0;
297    }
[158]298
299    if (_tty_get_full[tty_id] == 0) 
300    {
[189]301        return 0;
[158]302    }
303    else
304    {
305        *buffer = _tty_get_buf[tty_id];
306        _tty_get_full[tty_id] = 0;
[189]307        return 1;
[158]308    }
[189]309} 
[158]310////////////////////////////////////////////////////////////////////////////////
[204]311//     _tty_get_char()
312// This function is used by the _isr_tty to read a character in the TTY
313// terminal defined by the tty_id argument. The character is stored
314// in requested buffer, and the IRQ is acknowledged.
315// Returns 0 if success, 1 if tty_id too large.
[158]316////////////////////////////////////////////////////////////////////////////////
[204]317unsigned int _tty_get_char( unsigned int        tty_id,
[207]318                            unsigned char*  buffer )
[158]319{
[204]320    // checking argument
321    if ( tty_id >= NB_TTYS ) return 1;
[199]322
[204]323    // compute terminal base address
324    unsigned int *tty_address = (unsigned int*)( (char*)&seg_tty_base + 
325                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
[158]326
[204]327    *buffer = (unsigned char)tty_address[tty_id*TTY_SPAN + TTY_READ];
328    return 0;
[158]329}
330
331////////////////////////////////////////////////////////////////////////////////
[189]332//      VciMultiIcu and VciXicu drivers
[158]333////////////////////////////////////////////////////////////////////////////////
[203]334// There is one vci_multi_icu (or vci_xicu) component per cluster,
335// and the number of independant ICUs is equal to NB_PROCS_MAX,
336// because there is one private interrupr controler per processor.
[158]337////////////////////////////////////////////////////////////////////////////////
338
339////////////////////////////////////////////////////////////////////////////////
[203]340//     _icu_set_mask()
341// This function can be used with both the vci_xicu & vci_multi_icu components.
342// It set the mask register for the ICU channel identified by the cluster index
343// and the processor index: all '1' bits are set / all '0' bits are not modified.
[158]344// Returns 0 if success, > 0 if error.
345////////////////////////////////////////////////////////////////////////////////
[203]346unsigned int _icu_set_mask( unsigned int cluster_id,
347                            unsigned int proc_id,
348                            unsigned int value,
349                            unsigned int is_timer )
[158]350{
[203]351    // parameters checking
352    if ( cluster_id >= NB_CLUSTERS)             return 1;
353    if ( proc_id    >= NB_PROCS_MAX )   return 1;
354
[204]355    unsigned int* icu_address = (unsigned int*)( (char*)&seg_icu_base + 
356                                (cluster_id * (unsigned)CLUSTER_SIZE) );
[189]357#if GIET_USE_XICU
[203]358    if ( is_timer ) icu_address[XICU_REG(XICU_MSK_PTI_ENABLE, proc_id)] = value;
359    else            icu_address[XICU_REG(XICU_MSK_HWI_ENABLE, proc_id)] = value;
[189]360#else
[203]361    icu_address[proc_id * ICU_SPAN + ICU_MASK_SET] = value; 
362#endif
[189]363
[158]364    return 0;
365}
366////////////////////////////////////////////////////////////////////////////////
[203]367//     _icu_get_index()
368// This function can be used with both the vci_xicu & vci_multi_icu components.
369// It returns the index of the highest priority (smaller index) active HWI.
370// The ICU channel is identified by the cluster index and the processor index.
[158]371// Returns 0 if success, > 0 if error.
372////////////////////////////////////////////////////////////////////////////////
[203]373unsigned int _icu_get_index(  unsigned int cluster_id,
374                              unsigned int proc_id,
375                              unsigned int* buffer )
[158]376{
[203]377    // parameters checking
378    if ( cluster_id >= NB_CLUSTERS)             return 1;
379    if ( proc_id    >= NB_PROCS_MAX )   return 1;
380
[204]381    unsigned int* icu_address = (unsigned int*)( (char*)&seg_icu_base + 
382                                (cluster_id * (unsigned)CLUSTER_SIZE) );
[189]383#if GIET_USE_XICU
[203]384    unsigned int prio   = icu_address[XICU_REG(XICU_PRIO, proc_id)];
385    unsigned int pti_ok = (prio & 0x00000001);
386    unsigned int hwi_ok = (prio & 0x00000002);
387    unsigned int swi_ok = (prio & 0x00000004);
388    unsigned int pti_id = (prio & 0x00001F00) >> 8;
389    unsigned int hwi_id = (prio & 0x001F0000) >> 16;
390    unsigned int swi_id = (prio & 0x1F000000) >> 24;
391    if      (pti_ok)    *buffer = pti_id;
392    else if (hwi_ok)    *buffer = hwi_id;
393    else if (swi_ok)    *buffer = swi_id;
394    else                *buffer = 32;
[189]395#else
[203]396    *buffer = icu_address[proc_id * ICU_SPAN + ICU_IT_VECTOR]; 
397#endif
[189]398
[158]399    return 0;
400}
401
402////////////////////////////////////////////////////////////////////////////////
403//      VciGcd driver
404////////////////////////////////////////////////////////////////////////////////
405// The Greater Dommon Divider is a -very- simple hardware coprocessor
[165]406// performing the computation of the GCD of two 32 bits integers.
[158]407// It has no DMA capability.
408////////////////////////////////////////////////////////////////////////////////
409
410////////////////////////////////////////////////////////////////////////////////
[189]411//     _gcd_write()
[158]412// Write a 32-bit word in a memory mapped register of the GCD coprocessor.
413// Returns 0 if success, > 0 if error.
414////////////////////////////////////////////////////////////////////////////////
[165]415unsigned int _gcd_write( unsigned int register_index, 
416                         unsigned int value)
[158]417{
[165]418    // parameters checking
[158]419    if (register_index >= GCD_END)
420        return 1;
421
[204]422    unsigned int* gcd_address = (unsigned int*)( (char*)&seg_gcd_base +
423                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
[165]424
425    gcd_address[register_index] = value; // write word
[158]426    return 0;
427}
428////////////////////////////////////////////////////////////////////////////////
[189]429//     _gcd_read()
[158]430// Read a 32-bit word in a memory mapped register of the GCD coprocessor.
431// Returns 0 if success, > 0 if error.
432////////////////////////////////////////////////////////////////////////////////
[165]433unsigned int _gcd_read( unsigned int register_index, 
434                        unsigned int *buffer)
[158]435{
[165]436    // parameters checking
[158]437    if (register_index >= GCD_END)
438        return 1;
439
[204]440    unsigned int* gcd_address = (unsigned int*)( (char*)&seg_gcd_base +
441                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
[165]442
443    *buffer = gcd_address[register_index]; // read word
[158]444    return 0;
445}
446
447////////////////////////////////////////////////////////////////////////////////
448// VciBlockDevice driver
449////////////////////////////////////////////////////////////////////////////////
[165]450// The VciBlockDevice is a single channel external storage contrÃŽler.
[166]451//
452// The IOMMU can be activated or not:
453//
454// 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to
455// the IOC peripheral, in the I/O virtual space, and the user buffer is
456// dynamically remapped in the IOMMU page table. The corresponding entry
457// in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable.
458// The number of pages to be unmapped is stored in the _ioc_npages variable.
459// The number of PT2 entries is dynamically computed and stored in the
460// kernel _ioc_iommu_npages variable. It cannot be larger than 512.
461// The user buffer is unmapped by the _ioc_completed() function when
462// the transfer is completed.
463//
464// 2/ If the IOMMU is not used, we check that  the user buffer is mapped to a
465// contiguous physical buffer (this is generally true because the user space
466// page tables are statically constructed to use contiguous physical memory).
467//
468// Finally, the memory buffer must fulfill the following conditions:
469// - The user buffer must be word aligned,
470// - The user buffer must be mapped in user address space,
471// - The user buffer must be writable in case of (to_mem) access,
472// - The total number of physical pages occupied by the user buffer cannot
473//   be larger than 512 pages if the IOMMU is activated,
474// - All physical pages occupied by the user buffer must be contiguous
475//   if the IOMMU is not activated.
476// An error code is returned if these conditions are not verified.
477//
[158]478// As the IOC component can be used by several programs running in parallel,
479// the _ioc_lock variable guaranties exclusive access to the device.  The
480// _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock.
481// and set _ioc_lock to a non zero value.  The _ioc_write() and _ioc_read()
482// functions are blocking, polling the _ioc_lock variable until the device is
483// available.
484// When the tranfer is completed, the ISR routine activated by the IOC IRQ
485// set the _ioc_done variable to a non-zero value. Possible address errors
486// detected by the IOC peripheral are reported by the ISR in the _ioc_status
487// variable.
488// The _ioc_completed() function is polling the _ioc_done variable, waiting for
[166]489// transfer completion. When the completion is signaled, the _ioc_completed()
[158]490// function reset the _ioc_done variable to zero, and releases the _ioc_lock
491// variable.
492//
493// In a multi-processing environment, this polling policy should be replaced by
494// a descheduling policy for the requesting process.
495///////////////////////////////////////////////////////////////////////////////
496
[189]497// IOC global variables
498in_unckdata volatile unsigned int       _ioc_status       = 0;
499in_unckdata volatile unsigned int       _ioc_done         = 0;
500in_unckdata unsigned int                        _ioc_lock         = 0;
501in_unckdata unsigned int                        _ioc_iommu_ix1    = 0;
502in_unckdata unsigned int                        _ioc_iommu_npages; 
[158]503
504///////////////////////////////////////////////////////////////////////////////
[189]505//      _ioc_access()
[166]506// This function transfer data between a memory buffer and the block device.
507// The buffer lentgth is (count*block_size) bytes.
508// Arguments are:
509// - to_mem     : from external storage to memory when non 0
510// - lba        : first block index on the external storage.
511// - user_vaddr : virtual base address of the memory buffer.
512// - count      : number of blocks to be transfered.
[158]513// Returns 0 if success, > 0 if error.
514///////////////////////////////////////////////////////////////////////////////
[166]515unsigned int _ioc_access( unsigned int  to_mem,
516                          unsigned int  lba,
517                          unsigned int  user_vaddr,
518                          unsigned int  count )
[158]519{
[167]520    unsigned int                user_vpn_min;   // first virtuel page index in user space
521    unsigned int                user_vpn_max;   // last virtual page index in user space
522    unsigned int                vpn;                    // current virtual page index in user space
523    unsigned int                ppn;                    // physical page number
524    unsigned int                flags;                  // page protection flags
525    unsigned int                ix2;                    // page index in IOMMU PT1 page table
526    unsigned int                addr;                   // buffer address for IOC peripheral
527    unsigned int                ppn_first;              // first physical page number for user buffer
[166]528       
529    // check buffer alignment
530    if ( (unsigned int)user_vaddr & 0x3 ) return 1;
[158]531
[204]532    unsigned int*       ioc_address = (unsigned int*)( (char*)&seg_ioc_base +
533                                  (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
534
[166]535    unsigned int        block_size   = ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
536    unsigned int        length       = count*block_size;
[158]537
[167]538    // get user space page table virtual address
[199]539    unsigned int task_id       = _get_current_task_id();
540    unsigned int user_pt_vbase = _get_context_slot( task_id, CTX_PTAB_ID );
[166]541   
542    user_vpn_min = user_vaddr >> 12;
543    user_vpn_max = (user_vaddr + length - 1) >> 12;
544    ix2          = 0;
[158]545
[166]546    // loop on all virtual pages covering the user buffer
547    for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ )
548    {
549        // get ppn and flags for each vpn
[189]550        unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase,
551                                           vpn,
552                                           &ppn,
553                                           &flags );
[158]554
[166]555        // check access rights
556        if ( ko )                                                                 return 2;             // unmapped
557        if ( (flags & PTE_U) == 0 )                               return 3;             // not in user space
558        if ( ( (flags & PTE_W) == 0 ) && to_mem ) return 4;             // not writable
[158]559
[166]560        // save first ppn value
561        if ( ix2 == 0 ) ppn_first = ppn;
[158]562
[166]563        if ( GIET_IOMMU_ACTIVE )    // the user buffer must be remapped in the I/0 space
564        {
565            // check buffer length < 2 Mbytes
566            if ( ix2 > 511 ) return 2;
[158]567
[166]568            // map the physical page in IOMMU page table
569            _iommu_add_pte2( _ioc_iommu_ix1,    // PT1 index
570                             ix2,                               // PT2 index
571                                                 ppn,                           // Physical page number
572                             flags );                   // Protection flags
573        }
574        else                    // no IOMMU : check that physical pages are contiguous
575        {
576            if ( (ppn - ppn_first) != ix2 )           return 5;         // split physical buffer 
577        }
578       
579        // increment page index
580        ix2++;
581    } // end for vpn
[158]582
[166]583    // register the number of pages to be unmapped
584    _ioc_iommu_npages = (user_vpn_max - user_vpn_min) + 1;
[158]585
[166]586    // invalidate data cache in case of memory write
587    if ( to_mem ) _dcache_buf_invalidate( (void*)user_vaddr, length );
[158]588
[166]589    // compute buffer base address for IOC depending on IOMMU activation
590    if ( GIET_IOMMU_ACTIVE ) addr = (_ioc_iommu_ix1) << 21 | (user_vaddr & 0xFFF);
[167]591    else                     addr = (ppn_first << 12) | (user_vaddr & 0xFFF);
[166]592
593    // get the lock on ioc device
[189]594    _get_lock( &_ioc_lock );
[158]595
[166]596    // peripheral configuration 
597    ioc_address[BLOCK_DEVICE_BUFFER]     = addr;
598    ioc_address[BLOCK_DEVICE_COUNT]      = count;
599    ioc_address[BLOCK_DEVICE_LBA]        = lba;
600    if ( to_mem == 0 ) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
601    else               ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
[158]602
603    return 0;
604}
605/////////////////////////////////////////////////////////////////////////////////
606// _ioc_completed()
607//
608// This function checks completion of an I/O transfer and reports errors.
[166]609// As it is a blocking call, the processor is stalled.
610// If the virtual memory is activated, the pages mapped in the I/O virtual
611// space are unmapped, and the IOB TLB is cleared.
[158]612// Returns 0 if success, > 0 if error.
613/////////////////////////////////////////////////////////////////////////////////
614unsigned int _ioc_completed()
615{
[166]616    unsigned int        ret;
617    unsigned int        ix2;
[158]618
[166]619    // busy waiting
[158]620    while (_ioc_done == 0)
621        asm volatile("nop");
622
[166]623    // unmap the buffer from IOMMU page table if IOMMU is activated
624    if ( GIET_IOMMU_ACTIVE )
625    {
[204]626        unsigned int* iob_address = (unsigned int*)( (char*)&seg_iob_base +
627                                    (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
[166]628
629        for ( ix2 = 0 ; ix2 < _ioc_iommu_npages ; ix2++ )
630        {
631            // unmap the page in IOMMU page table
632            _iommu_inval_pte2( _ioc_iommu_ix1,  // PT1 index
633                              ix2 );                    // PT2 index
634
635            // clear IOMMU TLB
[169]636            iob_address[IOB_INVAL_PTE] = (_ioc_iommu_ix1 << 21) | (ix2 << 12); 
[166]637        }
638    }
639
640    // test IOC status
[158]641    if ((_ioc_status != BLOCK_DEVICE_READ_SUCCESS)
[166]642            && (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS)) ret = 1;    // error
643    else                                                    ret = 0;    // success
[158]644
[166]645    // reset synchronization variables
[158]646    _ioc_lock =0;
647    _ioc_done =0;
648
649    return ret;
650}
[166]651///////////////////////////////////////////////////////////////////////////////
[189]652//     _ioc_read()
[166]653// Transfer data from the block device to a memory buffer in user space.
654// - lba    : first block index on the block device
655// - buffer : base address of the memory buffer (must be word aligned)
656// - count  : number of blocks to be transfered.
657// Returns 0 if success, > 0 if error.
658///////////////////////////////////////////////////////////////////////////////
659unsigned int _ioc_read( unsigned int    lba, 
660                        void*               buffer, 
661                        unsigned int    count )
662{
[189]663    return _ioc_access( 1,              // read access
[166]664                        lba,
665                        (unsigned int)buffer,
666                        count );
667}
668///////////////////////////////////////////////////////////////////////////////
[189]669//     _ioc_write()
[166]670// Transfer data from a memory buffer in user space to the block device.
671// - lba    : first block index on the block device
672// - buffer : base address of the memory buffer (must be word aligned)
673// - count  : number of blocks to be transfered.
674// Returns 0 if success, > 0 if error.
675///////////////////////////////////////////////////////////////////////////////
676unsigned int _ioc_write( unsigned int   lba, 
677                         const void*    buffer, 
678                         unsigned int   count )
679{
[189]680    return _ioc_access( 0,              // write access
[166]681                        lba,
682                        (unsigned int)buffer,
683                        count );
684}
[204]685///////////////////////////////////////////////////////////////////////////////
686//     _ioc_get_status()
687// This function returns the transfert status, and acknowledge the IRQ.
688// Returns 0 if success, > 0 if error.
689///////////////////////////////////////////////////////////////////////////////
690unsigned int _ioc_get_status(unsigned int* status)
691{
692    // get IOC base address
693    unsigned int* ioc_address = (unsigned int*)( (char*)&seg_ioc_base +
694                                (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
[166]695
[204]696    *status = ioc_address[BLOCK_DEVICE_STATUS]; // read status & reset IRQ
697    return 0;
698}
699
[158]700//////////////////////////////////////////////////////////////////////////////////
[189]701// VciMultiDma driver
702//////////////////////////////////////////////////////////////////////////////////
703// The DMA controllers are physically distributed in the clusters.
704// There is  (NB_CLUSTERS * NB_DMAS_MAX) channels, indexed by a global index:
705//        dma_id = cluster_id * NB_DMA_MAX + loc_id
706//
707// As a DMA channel can be used by several tasks, each DMA channel is protected
708// by a specific lock: _dma_lock[dma_id]
709// The signalisation between the OS and the DMA uses the _dma_done[dma_id]
710// synchronisation variables  (set by the ISR, and reset by the OS).
711// The transfer status is copied by the ISR in the _dma_status[dma_id] variables.
712//
713// These DMA channels can be used by the FB driver, or by the NIC driver.
714//////////////////////////////////////////////////////////////////////////////////
715
[205]716//+1: for the case where the NB_DMAS_MAX == 0
[213]717#if NB_DMAS_MAX > 0
718in_unckdata unsigned int                        _dma_lock[NB_DMAS_MAX * NB_CLUSTERS]
719                                       = { [0 ... ((NB_DMAS_MAX) * NB_CLUSTERS)-1] = 0 };
[189]720
[213]721in_unckdata volatile unsigned int       _dma_done[NB_DMAS_MAX * NB_CLUSTERS]
722                                       = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 };
[189]723
[213]724in_unckdata volatile unsigned int       _dma_status[NB_DMAS_MAX * NB_CLUSTERS];
[189]725
726in_unckdata unsigned int                        _dma_iommu_ix1 = 1;
727
[213]728in_unckdata unsigned int            _dma_iommu_npages[NB_DMAS_MAX * NB_CLUSTERS];
729#endif
[189]730
731//////////////////////////////////////////////////////////////////////////////////
[204]732// _dma_reset_irq()
733//////////////////////////////////////////////////////////////////////////////////
734unsigned int _dma_reset_irq( unsigned int       cluster_id,
[207]735                             unsigned int       channel_id )
[204]736{
[213]737#if NB_DMAS_MAX > 0
[204]738    // parameters checking
739    if ( cluster_id >= NB_CLUSTERS ) return 1;
[207]740    if ( channel_id >= NB_DMAS_MAX ) return 1;
[204]741
742    // compute DMA base address
743    unsigned int*       dma_address = (unsigned int*)( (char*)&seg_dma_base + 
744                                  (cluster_id * (unsigned)CLUSTER_SIZE) );
745
[207]746    dma_address[channel_id*DMA_SPAN + DMA_RESET] = 0;                   
[204]747    return 0;
[213]748#else
749    return -1;
750#endif
[204]751}
752//////////////////////////////////////////////////////////////////////////////////
753// _dma_get_status()
754//////////////////////////////////////////////////////////////////////////////////
755unsigned int _dma_get_status( unsigned int      cluster_id,
[207]756                              unsigned int      channel_id,
[204]757                              unsigned int* status )
758{
[213]759#if NB_DMAS_MAX > 0
[204]760    // parameters checking
761    if ( cluster_id >= NB_CLUSTERS ) return 1;
[207]762    if ( channel_id >= NB_DMAS_MAX ) return 1;
[204]763
764    // compute DMA base address
765    unsigned int*       dma_address = (unsigned int*)( (char*)&seg_dma_base + 
766                                  (cluster_id * (unsigned)CLUSTER_SIZE) );
[207]767
768    *status = dma_address[channel_id*DMA_SPAN + DMA_LEN];
[204]769    return 0;
[213]770#else
771    return -1;
772#endif
[204]773}
774
775//////////////////////////////////////////////////////////////////////////////////
[158]776//      VciFrameBuffer driver
777//////////////////////////////////////////////////////////////////////////////////
[189]778// The vci_frame_buffer device can be accessed directly by software with memcpy(),
779// or it can be accessed through a multi-channels DMA component:
780// 
[158]781// The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to
782// implement the transfer between a data buffer (user space) and the frame
783// buffer (kernel space). They are blocking until completion of the transfer.
[169]784//
[158]785// The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the DMA
[189]786// controlers (distributed in the clusters) to transfer data
787// between the user buffer and the frame buffer. A  DMA channel is
788// allocated to each task requesting it in the mapping_info data structure.
[158]789//////////////////////////////////////////////////////////////////////////////////
790
791//////////////////////////////////////////////////////////////////////////////////
792// _fb_sync_write()
793// Transfer data from an memory buffer to the frame_buffer device using
794// a memcpy. The source memory buffer must be in user address space.
795// - offset : offset (in bytes) in the frame buffer.
796// - buffer : base address of the memory buffer.
797// - length : number of bytes to be transfered.
798// Returns 0 if success, > 0 if error.
799//////////////////////////////////////////////////////////////////////////////////
800unsigned int _fb_sync_write( unsigned int       offset, 
801                             const void*        buffer, 
802                             unsigned int       length )
803{
804
[169]805    // buffer must be mapped in user space
806    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
[189]807    {
[158]808        return 1;
[189]809    }
810    else
811    {
[203]812        unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
[189]813        memcpy((void*)fb_address, (void*)buffer, length);
814        return 0;
815    }
[158]816}
817
818//////////////////////////////////////////////////////////////////////////////////
819// _fb_sync_read()
820// Transfer data from the frame_buffer device to a memory buffer using
821// a memcpy. The destination memory buffer must be in user address space.
822// - offset : offset (in bytes) in the frame buffer.
823// - buffer : base address of the memory buffer.
824// - length : number of bytes to be transfered.
825// Returns 0 if success, > 0 if error.
826//////////////////////////////////////////////////////////////////////////////////
827unsigned int _fb_sync_read( unsigned int        offset, 
828                            const void*         buffer, 
829                            unsigned int        length )
830{
[169]831    // buffer must be mapped in user space
832    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
[189]833    {
[158]834        return 1;
[189]835    }
836    else
837    {
[203]838        unsigned char *fb_address = (unsigned char*)&seg_fbf_base + offset;
[189]839        memcpy((void*)buffer, (void*)fb_address, length);
840        return 0;
841    }
[158]842}
843
844//////////////////////////////////////////////////////////////////////////////////
[189]845// _fb_dma_access()
846// Transfer data between a user buffer and the frame_buffer using DMA.
847// - to_user    : from frame buffer to user buffer when true.
[169]848// - offset     : offset (in bytes) in the frame buffer.
849// - user_vaddr : virtual base address of the memory buffer.
850// - length     : number of bytes to be transfered.
[207]851// The user buffer must be mapped in user address space and word-aligned.
[169]852// The user buffer length must be multiple of 4 bytes.
[189]853// Me must compute the physical base addresses for both the frame buffer
854// and the user buffer before programming the DMA transfer.
[207]855// The GIET being fully static, we don't need to split the transfer in 4 Kbytes
[189]856// pages, because the user buffer is contiguous in physical space.
[158]857// Returns 0 if success, > 0 if error.
858//////////////////////////////////////////////////////////////////////////////////
[189]859unsigned int _fb_dma_access( unsigned int       to_user,
860                             unsigned int   offset,
861                             unsigned int   user_vaddr,
862                             unsigned int   length )
[158]863{
[213]864#if NB_DMAS_MAX > 0
[189]865    unsigned int        ko;                             // unsuccessfull V2P translation
866    unsigned int        flags;                  // protection flags
867    unsigned int        ppn;                    // physical page number
868    unsigned int    user_pbase;         // user buffer pbase address
869    unsigned int    fb_pbase;           // frame buffer pbase address
[158]870
[189]871    // get DMA channel and compute DMA vbase address
[199]872    unsigned int        task_id    = _get_current_task_id();
873    unsigned int        dma_id     = _get_context_slot( task_id, CTX_FBDMA_ID );
[189]874    unsigned int    cluster_id = dma_id / NB_DMAS_MAX;
875    unsigned int    loc_id     = dma_id % NB_DMAS_MAX;
[169]876
[204]877    unsigned int*       dma_base   = (unsigned int*)( (char*)&seg_dma_base +
878                                 (cluster_id * (unsigned)CLUSTER_SIZE) );
879 
[189]880    // check user buffer address and length alignment
881    if ( (user_vaddr & 0x3) || (length & 0x3) )
882    {
[203]883        _get_lock(&_tty_put_lock);
[207]884        _puts("\n[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n");
[203]885        _release_lock(&_tty_put_lock);
[189]886        return 1;
887    }
[169]888
889    // get user space page table virtual address
[199]890    unsigned int        user_ptab = _get_context_slot( task_id, CTX_PTAB_ID );
[169]891
[189]892    // compute frame buffer pbase address
[207]893    unsigned int fb_vaddr = (unsigned int)&seg_fbf_base + 
894                            (CLUSTER_IO_ID * (unsigned int)CLUSTER_SIZE) + offset;
[189]895
896    ko = _v2p_translate( (page_table_t*)user_ptab,
897                         (fb_vaddr >> 12),
898                         &ppn,
899                         &flags );
900    fb_pbase = (ppn << 12) | (fb_vaddr & 0x00000FFF);
901
902    if ( ko )
903    {
[203]904        _get_lock(&_tty_put_lock);
[207]905        _puts("\n[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n");
[203]906        _release_lock(&_tty_put_lock);
[189]907        return 2;
908    }
909
910    // Compute user buffer pbase address
911    ko = _v2p_translate( (page_table_t*)user_ptab,
912                         (user_vaddr >> 12),
913                         &ppn,
914                         &flags );
915    user_pbase = (ppn << 12) | (user_vaddr & 0x00000FFF);
916
917    if ( ko )
918    {
[203]919        _get_lock(&_tty_put_lock);
[207]920        _puts("\n[GIET ERROR] in _fbdma_access() : user buffer unmapped\n");
[203]921        _release_lock(&_tty_put_lock);
[189]922        return 3;
923    } 
924    if ( (flags & PTE_U) == 0 )
925    {
[203]926        _get_lock(&_tty_put_lock);
[189]927        _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n");
[203]928        _release_lock(&_tty_put_lock);
[189]929        return 4; 
930    }
931    if ( ( (flags & PTE_W) == 0 ) && to_user ) 
932    {
[203]933        _get_lock(&_tty_put_lock);
[207]934        _puts("\n[GIET ERROR] in _fbdma_access() : user buffer not writable\n");
[203]935        _release_lock(&_tty_put_lock);
[189]936        return 5;
937    }
938
939
940
941/*
942    // loop on all virtual pages covering the user buffer
[169]943    unsigned int user_vpn_min = user_vaddr >> 12;
944    unsigned int user_vpn_max = (user_vaddr + length - 1) >> 12;
945    unsigned int ix2          = 0;
946    unsigned int ix1          = _dma_iommu_ix1 + dma_id;
[158]947
[169]948    for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ )
949    {
950        // get ppn and flags for each vpn
[189]951        unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase,
952                                          vpn,
953                                          &ppn,
954                                          &flags );
[158]955
[169]956        // check access rights
[189]957        if ( ko )                                 return 3;     // unmapped
958        if ( (flags & PTE_U) == 0 )               return 4;     // not in user space
959        if ( ( (flags & PTE_W) == 0 ) && to_user ) return 5;     // not writable
[158]960
[169]961        // save first ppn value
962        if ( ix2 == 0 ) ppn_first = ppn;
963
964        if ( GIET_IOMMU_ACTIVE )    // the user buffer must be remapped in the I/0 space
965        {
966            // check buffer length < 2 Mbytes
967            if ( ix2 > 511 ) return 2;
968
969            // map the physical page in IOMMU page table
970            _iommu_add_pte2( ix1,               // PT1 index
971                             ix2,               // PT2 index
972                             ppn,               // physical page number
973                             flags );   // protection flags
974        }
975        else            // no IOMMU : check that physical pages are contiguous
976        {
[189]977            if ( (ppn - ppn_first) != ix2 )       return 6;     // split physical buffer 
[169]978        }
979
980        // increment page index
981        ix2++;
982    } // end for vpn
983
[189]984    // register the number of pages to be unmapped if iommu activated
[169]985    _dma_iommu_npages[dma_id] = (user_vpn_max - user_vpn_min) + 1;
986
[189]987*/
[204]988
[169]989    // invalidate data cache in case of memory write
[189]990    if ( to_user ) _dcache_buf_invalidate( (void*)user_vaddr, length );
[169]991
[189]992    // get the lock
993    _get_lock( &_dma_lock[dma_id] );
[169]994
995    // DMA configuration
[189]996    if ( to_user )
[169]997    {
[204]998        dma_base[loc_id*DMA_SPAN + DMA_SRC] = (unsigned int)fb_pbase;
999        dma_base[loc_id*DMA_SPAN + DMA_DST] = (unsigned int)user_pbase;
[169]1000    }
1001    else
1002    {
[204]1003        dma_base[loc_id*DMA_SPAN + DMA_SRC] = (unsigned int)user_pbase;
1004        dma_base[loc_id*DMA_SPAN + DMA_DST] = (unsigned int)fb_pbase;
[169]1005    }
[204]1006    dma_base[loc_id*DMA_SPAN + DMA_LEN] = (unsigned int)length;
[169]1007   
[158]1008    return 0;
[213]1009
1010#else //NB_DMAS_MAX == 0
1011    return -1;
1012#endif
[169]1013} 
1014//////////////////////////////////////////////////////////////////////////////////
1015// _fb_write()
1016// Transfer data from a memory buffer to the frame_buffer device using  DMA.
1017// - offset : offset (in bytes) in the frame buffer.
1018// - buffer : base address of the memory buffer.
1019// - length : number of bytes to be transfered.
1020// Returns 0 if success, > 0 if error.
1021//////////////////////////////////////////////////////////////////////////////////
1022unsigned int _fb_write( unsigned int    offset, 
1023                        const void*             buffer, 
1024                        unsigned int    length )
1025{
[189]1026    return _fb_dma_access( 0,                                           // write to frame buffer
1027                           offset,
1028                           (unsigned int)buffer,
1029                           length );   
[158]1030}
1031
1032//////////////////////////////////////////////////////////////////////////////////
1033// _fb_read()
[169]1034// Transfer data from the frame_buffer device to a memory buffer using  DMA.
[158]1035// - offset : offset (in bytes) in the frame buffer.
1036// - buffer : base address of the memory buffer.
1037// - length : number of bytes to be transfered.
1038// Returns 0 if success, > 0 if error.
1039//////////////////////////////////////////////////////////////////////////////////
1040unsigned int _fb_read( unsigned int     offset, 
[169]1041                       const void*              buffer, 
[158]1042                       unsigned int     length )
1043{
[189]1044    return _fb_dma_access( 1,                                           // read from frame buffer
1045                           offset,
1046                           (unsigned int)buffer,
1047                           length );   
[158]1048}
1049
1050//////////////////////////////////////////////////////////////////////////////////
1051// _fb_completed()
1052// This function checks completion of a DMA transfer to or fom the frame buffer.
[169]1053// As it is a blocking call, the processor is busy waiting.
1054// Returns 0 if success, > 0 if error
1055// (1 == read error / 2 == DMA idle error / 3 == write error)
[158]1056//////////////////////////////////////////////////////////////////////////////////
1057unsigned int _fb_completed()
1058{
[213]1059#if NB_DMAS_MAX > 0
[199]1060    unsigned int task_id = _get_current_task_id();
1061    unsigned int dma_id  = _get_context_slot( task_id, CTX_FBDMA_ID );
[158]1062
[169]1063    // busy waiting with a pseudo random delay between bus access
[189]1064    while (_dma_done[dma_id] == 0)
[169]1065    {
1066            unsigned int i;
[189]1067        unsigned int delay = ( _proctime() ^ _procid()<<4 ) & 0xFF;
[169]1068        for (i = 0; i < delay; i++)
1069            asm volatile("nop");
1070    }
1071   
1072    // unmap the buffer from IOMMU page table if IOMMU is activated
1073    if ( GIET_IOMMU_ACTIVE )
1074    {
[204]1075        unsigned int* iob_address = (unsigned int*)( (char*)&seg_iob_base +
1076                                    (CLUSTER_IO_ID * (unsigned)CLUSTER_SIZE) );
1077
[169]1078        unsigned int  ix1         = _dma_iommu_ix1 + dma_id;
1079        unsigned int  ix2;
[158]1080
[169]1081        for ( ix2 = 0 ; ix2 < _dma_iommu_npages[dma_id] ; ix2++ )
1082        {
1083            // unmap the page in IOMMU page table
1084            _iommu_inval_pte2( ix1,             // PT1 index
1085                               ix2 );   // PT2 index
[158]1086
[169]1087            // clear IOMMU TLB
1088            iob_address[IOB_INVAL_PTE] = (ix1 << 21) | (ix2 << 12);
1089        }
1090    }
1091
[189]1092    // reset synchronization variables
1093    _dma_lock[dma_id] = 0;
1094    _dma_done[dma_id] = 0;
1095
[169]1096    return _dma_status[dma_id];
[213]1097
1098#else //NB_DMAS_MAX == 0
1099
1100    return -1;
1101
1102#endif
[158]1103}
1104
Note: See TracBrowser for help on using the repository browser.