Changeset 169


Ignore:
Timestamp:
Jul 17, 2012, 2:39:10 PM (12 years ago)
Author:
alain
Message:

Introducing support for FBDMA (Frame Buffer using DMA)

Location:
soft/giet_vm
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/apps/display/main.c

    r168 r169  
    99    unsigned char buf_out[128*128];
    1010    unsigned int i;
     11    unsigned int x;
    1112    unsigned int base = 0;
    1213
     
    1819
    1920        /* Phase 1 : lecture image sur le disque et transfert vers buf_in */
    20         if (giet_ioc_read(base, buf_in, NBLOCS))
     21        x = giet_ioc_read(base, buf_in, NBLOCS);
     22        if ( x )
    2123        {
    22             giet_tty_printf("echec giet_ioc_read\n");
     24            giet_tty_printf("echec giet_ioc_read : %d\n", x);
    2325            giet_exit();
    2426        }
    25         else
     27        x = giet_ioc_completed();
     28        if ( x )
    2629        {
    27             giet_ioc_completed();
    28             giet_tty_printf("io_read  completed at date = %d \n", giet_proctime());
     30            giet_tty_printf("echec giet_ioc_completed : %d\n", x);
     31            giet_exit();
    2932        }
     33        giet_tty_printf("io_read  completed at date = %d \n", giet_proctime());
    3034
    3135        /* Phase 2 : transfert de buf_in vers buf_out avec seuillage */
     
    4044
    4145        /* Phase 3 : transfert de buf_out vers le frame buffer par dma */
    42         if (giet_fb_sync_write(0, buf_out, 128 * 128))
     46        x = giet_fb_write(0, buf_out, 128 * 128);
     47        if ( x )
    4348        {
    44             giet_tty_printf("echec giet_fb_write\n");
     49            giet_tty_printf("echec giet_fb_write : %d\n", x);
    4550            giet_exit();
    4651        }
    47         else
     52        x = giet_fb_completed();
     53        if ( x )
    4854        {
    49             giet_tty_printf("transfer completed at date = %d \n", giet_proctime());
     55            giet_tty_printf("echec giet_fb_completed : %d\n", x);
     56            giet_exit();
    5057        }
     58        giet_tty_printf("transfer completed at date = %d \n", giet_proctime());
    5159
    5260        base = base + NBLOCS;
  • soft/giet_vm/boot/boot_handler.c

    r167 r169  
    5151#include "../sys/mips32_registers.h"
    5252#include <boot_handler.h>
     53#include <giet_config.h>
    5354#include <mapping_info.h>
    5455#include <mwmr_channel.h>
     
    612613                    unsigned int        vspace_id )
    613614{
    614     unsigned int        pages;
    615615    unsigned int        vobj_id;
    616616    unsigned int        cur_vaddr;
  • soft/giet_vm/boot/boot_handler.h

    r167 r169  
    66///////////////////////////////////////////////////////////////////////////////////
    77
     8#include <giet_config.h>
     9#include <mapping_info.h>
     10
    811#ifndef     _BOOT_HANDLER_H_
    912#define     _BOOT_HANDLER_H_
    10 
    11 #include    <giet_config.h>
    12 #include    <mapping_info.h>
    1313
    1414/////////////////////////////////////////////////////////////////////////////////////
  • soft/giet_vm/giet_config.h

    r167 r169  
    2727#define NB_TIMERS                   4       /* number of timers per cluster */
    2828#define NB_DMAS                     1       /* total number of DMA channels */
    29 #define NB_TTYS                     8       /* total number of TTY terminals */
     29#define NB_TTYS                     2       /* total number of TTY terminals */
     30#define NB_IOC                      1       /* total number of IOC channels */
    3031
    3132/* software parameters */
  • soft/giet_vm/map.xml

    r167 r169  
    55                clusters = "1"
    66                psegs    = "9"
    7                 ttys     = "8"
    8                 fbs      = "0"
    9                 vspaces  = "4"
     7                ttys     = "2"
     8                fbs      = "1"
     9                vspaces  = "1"
    1010                globals  = "13" >
    1111
    1212        <clusterset>
    1313                <cluster index  = "0"
    14                          procs  = "4" />
     14                         procs  = "2" />
    1515        </clusterset>
    1616
     
    139139                                        <vobj   name    = "tty"
    140140                                                        type    = "PERI"
    141                                                         length  = "0x00001000" />
     141                                                        length  = "0x00000100" />
    142142                                </vseg>
    143143
     
    149149                                        <vobj   name    = "timer"
    150150                                                        type    = "PERI"
    151                                                         length  = "0x00001000" />
     151                                                        length  = "0x00000080" />
    152152                                </vseg>
    153153
     
    169169                                        <vobj   name    = "dma"
    170170                                                        type    = "PERI"
    171                                                         length  = "0x00001000" />
     171                                                        length  = "0x00000100" />
    172172                                </vseg>
    173173
     
    194194
    195195          <vspaceset>
    196                 <vspace name      = "router"
    197                         startname = "seg_data_router" >
    198 
    199                         <vseg   name      = "seg_data_router"
     196                <vspace name      = "display"
     197                        startname = "seg_data_display" >
     198
     199                        <vseg   name      = "seg_data_display"
    200200                                vbase     = "0x00800000"
    201                                 mode      = "__WU"
    202                                 psegname  = "PSEG_RAU" >
    203                                                             <vobj   name        = "seg_data_router"
    204                                                                         type    = "ELF"
    205                                                                         length  = "0x00010000"
    206                                         binpath = "build/router.elf" />
    207                                                 </vseg>
    208 
    209                         <vseg   name      = "seg_code_router"
    210                                 vbase     = "0x00400000"
    211                                 mode      = "CX_U"
    212                                 psegname  = "PSEG_RAU" >
    213                                                             <vobj   name        = "seg_code_router"
     201                                mode      = "C_WU"
     202                                psegname  = "PSEG_RAU" >
     203                                                            <vobj   name        = "seg_data_display"
    214204                                                                        type    = "ELF"
    215205                                                                            length  = "0x00010000"
    216                                         binpath = "build/router.elf" />
    217                                                 </vseg>
    218 
    219                         <vseg   name      = "seg_ptab"
    220                                 vbase     = "0x00300000"
    221                                 mode      = "C___"
    222                                 psegname  = "PSEG_RAU" >
    223                                 <vobj   name    = "ptab_router"
    224                                         type    = "PTAB"
    225                                         length  = "0x00012000"
    226                                         align   = "13" />
    227                         </vseg>
    228 
    229                         <vseg   name      = "seg_stack_producer"
    230                                                 vbase     = "0x00010000"
    231                                 mode      = "C_WU"
    232                                 psegname  = "PSEG_RAU" >
    233                                                             <vobj   name        = "stack_producer"
    234                                                                         type    = "BUFFER"
    235                                                                             length  = "0x00010000" />
    236                                                 </vseg>
    237 
    238                         <vseg   name      = "seg_stack_consumer"
    239                                                 vbase     = "0x00020000"
    240                                 mode      = "C_WU"
    241                                 psegname  = "PSEG_RAU" >
    242                                                             <vobj   name        = "stack_consumer"
    243                                                                         type    = "BUFFER"
    244                                                                             length  = "0x00010000" />
    245                                                 </vseg>
    246 
    247                         <vseg   name      = "seg_stack_router_A"
    248                                                 vbase     = "0x00030000"
    249                                 mode      = "C_WU"
    250                                 psegname  = "PSEG_RAU" >
    251                                                             <vobj   name        = "stack_router_A"
    252                                                                         type    = "BUFFER"
    253                                                                             length  = "0x00010000" />
    254                                                 </vseg>
    255 
    256                         <vseg   name      = "seg_stack_router_B"
    257                                                 vbase     = "0x00040000"
    258                                 mode      = "C_WU"
    259                                 psegname  = "PSEG_RAU" >
    260                                                             <vobj   name        = "stack_router_B"
    261                                                                         type    = "BUFFER"
    262                                                                             length  = "0x00010000" />
    263                                                 </vseg>
    264 
    265                         <vseg   name      = "seg_mwmr_channels"
    266                                 vbase     = "0x00050000"
    267                                 mode      = "__WU"
    268                                 psegname  = "PSEG_RAU" >
    269                                                             <vobj   name        = "mwmr_in"
    270                                                                         type    = "MWMR"
    271                                                                             length  = "0x00000020" />
    272                                                             <vobj   name        = "mwmr_out"
    273                                                                         type    = "MWMR"
    274                                                                             length  = "0x00000020" />
    275                                                 </vseg>
    276 
    277                         <task   name      = "producer"
    278                                 clusterid = "0"
    279                                 proclocid = "0"
    280                                 stackname = "stack_producer"
    281                                 startid   = "0"
    282                                 usetty    = "1" />
    283 
    284                         <task   name      = "consumer"
    285                                 clusterid = "0"
    286                                 proclocid = "1"
    287                                 stackname = "stack_consumer"
    288                                 startid   = "1"
    289                                 usetty    = "1" />
    290 
    291                         <task   name      = "router_A"
    292                                 clusterid = "0"
    293                                 proclocid = "2"
    294                                 stackname = "stack_router_A"
    295                                 startid   = "2"
    296                                 usetty    = "1" />
    297 
    298                         <task   name      = "router_B"
    299                                 clusterid = "0"
    300                                 proclocid = "3"
    301                                 stackname = "stack_router_B"
    302                                 startid   = "2"
    303                                 usetty    = "1" />
    304                 </vspace>
    305 
    306                 <vspace name      = "hello"
    307                         startname = "seg_data_hello" >
    308 
    309                         <vseg   name      = "seg_data_hello"
    310                                 vbase     = "0x00800000"
    311                                 mode      = "C_WU"
    312                                 psegname  = "PSEG_RAU" >
    313                                                             <vobj   name        = "seg_data_hello"
    314                                                                         type    = "ELF"
    315                                                                             length    = "0x00010000"
    316                                         binpath = "build/hello.elf" />
    317                                                 </vseg>
    318 
    319                         <vseg   name      = "seg_code_hello"
    320                                 vbase     = "0x00400000"
    321                                 mode      = "CX_U"
    322                                 psegname  = "PSEG_RAU" >
    323                                                             <vobj   name        = "seg_code_hello"
    324                                                                         type    = "ELF"
    325                                                                             length    = "0x00010000"
    326                                         binpath = "build/hello.elf" />
     206                                        binpath = "build/display.elf" />
    327207                                                </vseg>
    328208
     
    337217                        </vseg>
    338218
    339                         <vseg   name      = "seg_stack"
    340                                 vbase     = "0x00000000"
    341                                 mode      = "C_WU"
    342                                 psegname  = "PSEG_RAU" >
    343                                                             <vobj   name        = "stack"
    344                                                                         type    = "BUFFER"
    345                                                                             length  = "0x00010000" />
    346                                                 </vseg>
    347 
    348 
    349                         <task   name      = "main_hello"
    350                                 clusterid = "0"
    351                                 proclocid = "2"
    352                                 stackname = "stack"
    353                                 startid   = "0"
    354                                 usetty    = "1" />
    355                 </vspace>
    356 
    357                 <vspace name      = "pgcd"
    358                         startname = "seg_data_pgcd" >
    359 
    360                         <vseg   name      = "seg_data_pgcd"
    361                                 vbase     = "0x00800000"
    362                                 mode      = "C_WU"
    363                                 psegname  = "PSEG_RAU" >
    364                                                             <vobj   name        = "seg_data_pgcd"
    365                                                                         type    = "ELF"
    366                                                                             length  = "0x00010000"
    367                                         binpath = "build/pgcd.elf" />
    368                                                 </vseg>
    369 
    370                         <vseg   name      = "seg_ptab"
    371                                 vbase     = "0x00300000"
    372                                 mode      = "C___"
    373                                 psegname  = "PSEG_RAU" >
    374                                 <vobj   name    = "ptab"
    375                                         type    = "PTAB"
    376                                         length  = "0x00012000"
    377                                         align   = "13" />
    378                         </vseg>
    379 
    380                         <vseg   name      = "seg_code_pgcd"
    381                                 vbase     = "0x00400000"
    382                                 mode      = "CX_U"
    383                                 psegname  = "PSEG_RAU" >
    384                                                             <vobj   name        = "seg_code_pgcd"
    385                                                                         type    = "ELF"
    386                                                                             length  = "0x00010000"
    387                                         binpath = "build/pgcd.elf" />
    388                                                 </vseg>
    389 
    390                         <vseg   name      = "seg_stack"
    391                                 vbase     = "0x00000000"
    392                                 mode      = "C_WU"
    393                                 psegname  = "PSEG_RAU" >
    394                                                             <vobj   name        = "stack"
    395                                                                         type    = "BUFFER"
    396                                                                             length  = "0x00010000" />
    397                                                 </vseg>
    398 
    399                         <task   name      = "main_pgcd"
    400                                 clusterid = "0"
    401                                 proclocid = "3"
    402                                 stackname = "stack"
    403                                 startid   = "0"
    404                                 usetty    = "1" />
    405                 </vspace>
    406 
    407                 <vspace name      = "display"
    408                         startname = "seg_data_display" >
    409 
    410                         <vseg   name      = "seg_data_display"
    411                                 vbase     = "0x00800000"
    412                                 mode      = "C_WU"
    413                                 psegname  = "PSEG_RAU" >
    414                                                             <vobj   name        = "seg_data_display"
    415                                                                         type    = "ELF"
    416                                                                             length  = "0x00010000"
    417                                         binpath = "build/display.elf" />
    418                                                 </vseg>
    419 
    420                         <vseg   name      = "seg_ptab_display"
    421                                 vbase     = "0x00300000"
    422                                 mode      = "C___"
    423                                 psegname  = "PSEG_RAU" >
    424                                 <vobj   name    = "ptab"
    425                                         type    = "PTAB"
    426                                         length  = "0x00012000"
    427                                         align   = "13" />
    428                         </vseg>
    429 
    430219                        <vseg   name      = "seg_code_display"
    431220                                vbase     = "0x00400000"
     
    449238                        <task   name      = "main_display"
    450239                                clusterid = "0"
    451                                 proclocid = "3"
     240                                proclocid = "1"
    452241                                stackname = "stack_display"
    453242                                startid   = "0"
    454                                 usetty    = "1" />
     243                                usetty    = "1"
     244                                usefb     = "1" />
    455245                </vspace>
    456246
  • soft/giet_vm/sys/drivers.c

    r167 r169  
    8585#define in_unckdata __attribute__((section (".unckdata")))
    8686
    87 in_unckdata volatile unsigned int  _dma_status[NB_DMAS];
    88 in_unckdata volatile unsigned char _dma_busy[NB_DMAS] = { [0 ... NB_DMAS-1] = 0 };
    89 
     87// IOC variables
    9088in_unckdata volatile unsigned char _ioc_status       = 0;
    9189in_unckdata volatile unsigned char _ioc_done         = 0;
    9290in_unckdata unsigned int                   _ioc_lock         = 0;
    9391in_unckdata unsigned int                   _ioc_iommu_ix1    = 0;
    94 in_unckdata unsigned int                   _ioc_iommu_npages = 0;
    95 
     92in_unckdata unsigned int                   _ioc_iommu_npages;
     93
     94// DMA variables
     95in_unckdata volatile unsigned int  _dma_status[NB_DMAS];
     96in_unckdata volatile unsigned char _dma_busy[NB_DMAS] = { [0 ... NB_DMAS-1] = 0 };
     97in_unckdata volatile unsigned char _dma_iommu_ix1     = 1;
     98in_unckdata volatile unsigned char _dma_iommu_npages[NB_DMAS];
     99
     100// TTY variables
    96101in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS];
    97102in_unckdata volatile unsigned char _tty_get_full[NB_TTYS] = { [0 ... NB_TTYS-1] = 0 };
    98 in_unckdata unsigned int           _tty_put_lock;
     103in_unckdata unsigned int           _tty_put_lock          = 0;
    99104
    100105//////////////////////////////////////////////////////////////////////////////
     
    610615
    611616            // clear IOMMU TLB
    612             iob_address[IOB_INVAL_PTE] = (_ioc_iommu_ix1 << 21) | (ix2) << 12;
     617            iob_address[IOB_INVAL_PTE] = (_ioc_iommu_ix1 << 21) | (ix2 << 12);
    613618        }
    614619    }
     
    668673// implement the transfer between a data buffer (user space) and the frame
    669674// buffer (kernel space). They are blocking until completion of the transfer.
     675//
    670676// The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the DMA
    671677// coprocessor to transfer data between the user buffer and the frame buffer.
    672678// These  functions use a polling policy to test the global variables _dma_busy[i]
    673679// and detect the transfer completion. 
    674 // There is  NB_PROCS DMA channels, that are indexed by the proc_id.
     680// There is  NB_DMA channels, that are indexed by the dma_id stored in the
     681// task context.
    675682// The _dma_busy[i] synchronisation variables (one per channel) are set by the OS,
    676 // and reset by the ISR.
     683// and reset by the DMA ISR.
    677684//////////////////////////////////////////////////////////////////////////////////
    678685
     
    692699    volatile unsigned char *fb_address;
    693700
    694     /* buffer must be in user space */
    695     if (((unsigned int)buffer >= 0x80000000)
    696             || (((unsigned int)buffer + length ) >= 0x80000000 ))
     701    // buffer must be mapped in user space
     702    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
    697703        return 1;
    698704
    699705    fb_address = (unsigned char*)&seg_fb_base + offset;
    700706
    701     /* buffer copy */
     707    // buffer copy
    702708    memcpy((void*)fb_address, (void*)buffer, length);
    703709
     
    720726    volatile unsigned char *fb_address;
    721727
    722     /* parameters checking */
    723     /* buffer must be in user space */
    724     if (((unsigned int)buffer >= 0x80000000)
    725             || (((unsigned int)buffer + length ) >= 0x80000000 ))
     728    // buffer must be mapped in user space
     729    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
    726730        return 1;
    727731
    728732    fb_address = (unsigned char*)&seg_fb_base + offset;
    729733
    730     /* buffer copy */
     734    // buffer copy
    731735    memcpy((void*)buffer, (void*)fb_address, length);
    732736
     
    735739
    736740//////////////////////////////////////////////////////////////////////////////////
     741// _fb_access()
     742// Transfer data between a memory buffer and the frame_buffer device using DMA.
     743// - to_mem     : from frame buffer to memory when true.
     744// - offset     : offset (in bytes) in the frame buffer.
     745// - user_vaddr : virtual base address of the memory buffer.
     746// - length     : number of bytes to be transfered.
     747// The memory buffer must be mapped in user address space and word-aligned.
     748// The user buffer length must be multiple of 4 bytes.
     749// Returns 0 if success, > 0 if error.
     750//////////////////////////////////////////////////////////////////////////////////
     751unsigned int _fb_access( unsigned int   to_mem,
     752                         unsigned int   offset,
     753                         unsigned int   user_vaddr,
     754                         unsigned int   length )
     755{
     756    static_scheduler_t* psched;         // pointer on the current task scheduler
     757    unsigned char*              fb_base;        // frame buffer base address
     758    unsigned int*               dma_base;       // dma component base address
     759    unsigned int                task_id;        // task local index (for scheduler)
     760    unsigned int                dma_id;         // DMA channel index
     761    unsigned int                vpn;            // current virtual page number
     762    unsigned int                flags;          // protection flags
     763    unsigned int                ppn;            // current physical page number
     764    unsigned int                buf_base;       // buffer base address for DMA access
     765    unsigned int                ppn_first;      // first physical page index for user buffer
     766
     767    fb_base  = (unsigned char*)&seg_fb_base + offset;
     768
     769    psched   = &_scheduler[_procid()];
     770    task_id  = psched->current;
     771    dma_id   = psched->context[task_id][CTX_FBDMA_ID];
     772    dma_base = (unsigned int*)&seg_dma_base + (dma_id * DMA_SPAN);
     773
     774    // check buffer address and ength alignment
     775    if ( user_vaddr & 0x3 ) return 1;
     776    if ( length     & 0x3 ) return 1;
     777
     778    // get user space page table virtual address
     779    unsigned int user_ptp = psched->context[task_id][CTX_PTAB_ID];
     780
     781    unsigned int user_vpn_min = user_vaddr >> 12;
     782    unsigned int user_vpn_max = (user_vaddr + length - 1) >> 12;
     783    unsigned int ix2          = 0;
     784    unsigned int ix1          = _dma_iommu_ix1 + dma_id;
     785    unsigned int ko;
     786    unsigned int i;
     787
     788    // loop on all virtual pages covering the user buffer
     789    for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ )
     790    {
     791        // get ppn and flags for each vpn
     792        ko = _v2p_translate( (page_table_t*)user_ptp,
     793                             vpn,
     794                             &ppn,
     795                             &flags );
     796
     797        // check access rights
     798        if ( ko )                                 return 2;     // unmapped
     799        if ( (flags & PTE_U) == 0 )               return 3;     // not in user space
     800        if ( ( (flags & PTE_W) == 0 ) && to_mem ) return 4;     // not writable
     801
     802        // save first ppn value
     803        if ( ix2 == 0 ) ppn_first = ppn;
     804
     805        if ( GIET_IOMMU_ACTIVE )    // the user buffer must be remapped in the I/0 space
     806        {
     807            // check buffer length < 2 Mbytes
     808            if ( ix2 > 511 ) return 2;
     809
     810            // map the physical page in IOMMU page table
     811            _iommu_add_pte2( ix1,               // PT1 index
     812                             ix2,               // PT2 index
     813                             ppn,               // physical page number
     814                             flags );   // protection flags
     815        }
     816        else            // no IOMMU : check that physical pages are contiguous
     817        {
     818            if ( (ppn - ppn_first) != ix2 )       return 5;     // split physical buffer 
     819        }
     820
     821        // increment page index
     822        ix2++;
     823    } // end for vpn
     824
     825    // register the number of pages to be unmapped
     826    _dma_iommu_npages[dma_id] = (user_vpn_max - user_vpn_min) + 1;
     827
     828    // invalidate data cache in case of memory write
     829    if ( to_mem ) _dcache_buf_invalidate( (void*)user_vaddr, length );
     830
     831    // compute buffer base address for DMA depending on IOMMU activation
     832    if ( GIET_IOMMU_ACTIVE ) buf_base = ( ix1 ) << 21 | (user_vaddr & 0xFFF);
     833    else                     buf_base = (ppn_first << 12) | (user_vaddr & 0xFFF);
     834
     835
     836    // waiting until DMA device is available
     837    while (_dma_busy[dma_id] != 0)
     838    {
     839        // busy wait with a pseudo random delay between bus access
     840        unsigned int delay = (_proctime() & 0xF) << 4;
     841        for (i = 0; i < delay; i++)
     842            asm volatile("nop");
     843    }
     844
     845    _dma_busy[dma_id] = 1;
     846
     847    // DMA configuration
     848    dma_base[DMA_IRQ_DISABLE] = 0;
     849    if ( to_mem )
     850    {
     851        dma_base[DMA_SRC] = (unsigned int)fb_base;
     852        dma_base[DMA_DST] = (unsigned int)buf_base;
     853    }
     854    else
     855    {
     856        dma_base[DMA_SRC] = (unsigned int)buf_base;
     857        dma_base[DMA_DST] = (unsigned int)fb_base;
     858    }
     859    dma_base[DMA_LEN] = (unsigned int)length;
     860   
     861    return 0;
     862
     863//////////////////////////////////////////////////////////////////////////////////
    737864// _fb_write()
    738 // Transfer data from an memory buffer to the frame_buffer device using a DMA.
    739 // The source memory buffer must be in user address space.
     865// Transfer data from a memory buffer to the frame_buffer device using  DMA.
    740866// - offset : offset (in bytes) in the frame buffer.
    741867// - buffer : base address of the memory buffer.
     
    744870//////////////////////////////////////////////////////////////////////////////////
    745871unsigned int _fb_write( unsigned int    offset,
    746                         const void*     buffer,
     872                        const void*             buffer,
    747873                        unsigned int    length )
    748874{
    749     volatile unsigned char *fb_address;
    750     volatile unsigned int *dma;
    751 
    752     unsigned int proc_id;
    753     unsigned int delay;
    754     unsigned int i;
    755 
    756     /* buffer must be in user space */
    757     if (((unsigned int)buffer >= 0x80000000)
    758             || (((unsigned int)buffer + length ) >= 0x80000000 ))
    759         return 1;
    760 
    761     proc_id = _procid();
    762     fb_address = (unsigned char*)&seg_fb_base + offset;
    763     dma = (unsigned int*)&seg_dma_base + (proc_id * DMA_SPAN);
    764 
    765     /* waiting until DMA device is available */
    766     while (_dma_busy[proc_id] != 0)
    767     {
    768         /* if the lock failed, busy wait with a pseudo random delay between bus
    769          * accesses */
    770         delay = (_proctime() & 0xF) << 4;
     875    return _fb_access( 0,                                               // write to frame buffer
     876                       offset,
     877                       (unsigned int)buffer,
     878                       length );       
     879}
     880
     881//////////////////////////////////////////////////////////////////////////////////
     882// _fb_read()
     883// Transfer data from the frame_buffer device to a memory buffer using  DMA.
     884// - offset : offset (in bytes) in the frame buffer.
     885// - buffer : base address of the memory buffer.
     886// - length : number of bytes to be transfered.
     887// Returns 0 if success, > 0 if error.
     888//////////////////////////////////////////////////////////////////////////////////
     889unsigned int _fb_read( unsigned int     offset,
     890                       const void*              buffer,
     891                       unsigned int     length )
     892{
     893    return _fb_access( 1,                                               // read from frame buffer
     894                       offset,
     895                       (unsigned int)buffer,
     896                       length );       
     897}
     898
     899//////////////////////////////////////////////////////////////////////////////////
     900// _fb_completed()
     901// This function checks completion of a DMA transfer to or fom the frame buffer.
     902// As it is a blocking call, the processor is busy waiting.
     903// Returns 0 if success, > 0 if error
     904// (1 == read error / 2 == DMA idle error / 3 == write error)
     905//////////////////////////////////////////////////////////////////////////////////
     906unsigned int _fb_completed()
     907{
     908    static_scheduler_t* psched  = &_scheduler[_procid()];
     909    unsigned int        task_id = psched->current;
     910
     911    volatile unsigned int   dma_id  = psched->context[task_id][CTX_FBDMA_ID];
     912
     913    // busy waiting with a pseudo random delay between bus access
     914    while (_dma_busy[dma_id] != 0)
     915    {
     916            unsigned int i;
     917        unsigned int delay = (_proctime() & 0xF) << 4;
    771918        for (i = 0; i < delay; i++)
    772919            asm volatile("nop");
    773920    }
    774     _dma_busy[proc_id] = 1;
    775 
    776     /* DMA configuration for write transfer */
    777     dma[DMA_IRQ_DISABLE] = 0;
    778     dma[DMA_SRC] = (unsigned int)buffer;
    779     dma[DMA_DST] = (unsigned int)fb_address;
    780     dma[DMA_LEN] = (unsigned int)length;
    781     return 0;
    782 }
    783 
    784 //////////////////////////////////////////////////////////////////////////////////
    785 // _fb_read()
    786 // Transfer data from the frame_buffer device to an memory buffer using a DMA.
    787 // The destination memory buffer must be in user address space.
    788 // - offset : offset (in bytes) in the frame buffer.
    789 // - buffer : base address of the memory buffer.
    790 // - length : number of bytes to be transfered.
    791 // All cache lines corresponding to the the target buffer are invalidated
    792 // for cache coherence.
    793 // Returns 0 if success, > 0 if error.
    794 //////////////////////////////////////////////////////////////////////////////////
    795 unsigned int _fb_read( unsigned int     offset,
    796                        const void*      buffer,
    797                        unsigned int     length )
    798 {
    799     volatile unsigned char *fb_address;
    800     volatile unsigned int *dma;
    801 
    802     unsigned int proc_id;
    803     unsigned int delay;
    804     unsigned int i;
    805 
    806     /* buffer must be in user space */
    807     if (((unsigned int)buffer >= 0x80000000)
    808             || (((unsigned int)buffer + length ) >= 0x80000000 ))
    809         return 1;
    810 
    811     proc_id = _procid();
    812     fb_address = (unsigned char*)&seg_fb_base + offset;
    813     dma = (unsigned int*)&seg_dma_base + (proc_id * DMA_SPAN);
    814 
    815     /* waiting until DMA device is available */
    816     while (_dma_busy[proc_id] != 0)
    817     {
    818         /* if the lock failed, busy wait with a pseudo random delay between bus
    819          * accesses */
    820         delay = (_proctime() & 0xF) << 4;
    821         for (i = 0; i < delay; i++)
    822             asm volatile("nop");
     921   
     922    // unmap the buffer from IOMMU page table if IOMMU is activated
     923    if ( GIET_IOMMU_ACTIVE )
     924    {
     925        unsigned int* iob_address = (unsigned int*)&seg_iob_base;
     926        unsigned int  ix1         = _dma_iommu_ix1 + dma_id;
     927        unsigned int  ix2;
     928
     929        for ( ix2 = 0 ; ix2 < _dma_iommu_npages[dma_id] ; ix2++ )
     930        {
     931            // unmap the page in IOMMU page table
     932            _iommu_inval_pte2( ix1,             // PT1 index
     933                               ix2 );   // PT2 index
     934
     935            // clear IOMMU TLB
     936            iob_address[IOB_INVAL_PTE] = (ix1 << 21) | (ix2 << 12);
     937        }
    823938    }
    824     _dma_busy[proc_id] = 1;
    825 
    826     /* DMA configuration for write transfer */
    827     dma[DMA_IRQ_DISABLE] = 0;
    828     dma[DMA_SRC] = (unsigned int)fb_address;
    829     dma[DMA_DST] = (unsigned int)buffer;
    830     dma[DMA_LEN] = (unsigned int)length;
    831 
    832     /* invalidation of data cache */
    833     _dcache_buf_invalidate(buffer, length);
    834 
    835     return 0;
    836 }
    837 
    838 //////////////////////////////////////////////////////////////////////////////////
    839 // _fb_completed()
    840 // This function checks completion of a DMA transfer to or fom the frame buffer.
    841 // As it is a blocking call, the processor is stalled until the next interrupt.
    842 // Returns 0 if success, > 0 if error.
    843 //////////////////////////////////////////////////////////////////////////////////
    844 unsigned int _fb_completed()
    845 {
    846     unsigned int proc_id;
    847 
    848     proc_id = _procid();
    849 
    850     while (_dma_busy[proc_id] != 0)
    851         asm volatile("nop");
    852 
    853     if (_dma_status[proc_id] != 0)
    854         return 1;
    855 
    856     return 0;
    857 }
    858 
     939
     940    return _dma_status[dma_id];
     941}
     942
  • soft/giet_vm/sys/irq_handler.c

    r167 r169  
    8686    volatile unsigned int* dma_address;
    8787
     88    // compute DMA channel address
    8889    dma_address = (unsigned int*)&seg_dma_base + (dma_id * DMA_SPAN);
    8990
     91    // save DMA channel status 
     92    _dma_status[dma_id] = dma_address[DMA_LEN]; /* save status */
     93
     94    // reset DMA channel
    9095    dma_address[DMA_RESET] = 0;                                 /* reset IRQ */
    9196
    92     _dma_status[dma_id] = dma_address[DMA_LEN]; /* save status */
     97    // release DMA channel
    9398    _dma_busy[dma_id] = 0;                      /* release DMA */
    9499}
  • soft/giet_vm/sys/kernel_init.c

    r167 r169  
    542542in_kinit void _kernel_peripherals_init()
    543543{
    544     // IOC peripheral initialisation
     544    /////////////////////
     545    // IOC peripheral
    545546    // we simply activate the IOC interrupts...
    546     unsigned int*       ioc_address = (unsigned int*)&seg_ioc_base;
    547 
    548     ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
     547    if ( NB_IOC )
     548    {
     549        unsigned int*   ioc_address = (unsigned int*)&seg_ioc_base;
     550        ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1;
     551    }
    549552   
     553    /////////////////////
     554    // FBDMA peripheral
     555    // we simply activate the DMA interrupts...
     556    if ( NB_DMAS )
     557    {
     558        unsigned int*   dma_address = (unsigned int*)&seg_dma_base;
     559        dma_address[DMA_IRQ_DISABLE] = 0;
     560    }
     561
     562    /////////////////////
    550563    // IOB peripheral
     564    // must be initialised in case of IOMMU
    551565    if ( GIET_IOMMU_ACTIVE )
    552566    {
     
    560574        // activate IOMMU
    561575        iob_address[IOB_IOMMU_ACTIVE] = 1;   
    562     }
     576    } 
    563577
    564578    _puts("\n[INIT] Peripherals initialisation completed at cycle ");
Note: See TracChangeset for help on using the changeset viewer.