Changeset 289 for soft/giet_vm
- Timestamp:
- Feb 4, 2014, 2:16:37 AM (11 years ago)
- Location:
- soft/giet_vm
- Files:
-
- 18 edited
- 7 copied
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/Makefile
r272 r289 14 14 15 15 ### Objects to be linked for kernel.elf 16 KERNEL_OBJS = build/common/utils.o 17 build/common/vmem.o 16 KERNEL_OBJS = build/common/utils.o \ 17 build/common/vmem.o \ 18 18 build/fat32/fat32.o \ 19 19 build/drivers/dma_driver.o \ … … 22 22 build/drivers/icu_driver.o \ 23 23 build/drivers/ioc_driver.o \ 24 build/drivers/bdv_driver.o \ 25 build/drivers/hba_driver.o \ 26 build/drivers/sdc_driver.o \ 27 build/drivers/spi_driver.o \ 24 28 build/drivers/iob_driver.o \ 25 29 build/drivers/mmc_driver.o \ … … 37 41 38 42 ### Objects to be linked for boot.elf 39 BOOT_OBJS = build/common/utils.o 40 build/common/vmem.o 43 BOOT_OBJS = build/common/utils.o \ 44 build/common/vmem.o \ 41 45 build/fat32/fat32.o \ 42 46 build/drivers/tty_driver.o \ … … 45 49 build/drivers/mwr_driver.o \ 46 50 build/drivers/ioc_driver.o \ 51 build/drivers/bdv_driver.o \ 52 build/drivers/hba_driver.o \ 53 build/drivers/sdc_driver.o \ 54 build/drivers/spi_driver.o \ 47 55 build/drivers/nic_driver.o \ 48 56 build/drivers/mmc_driver.o \ … … 90 98 91 99 CFLAGS = -Wall -ffreestanding -mno-gpopt -mips32 100 92 101 93 102 GIET_INCLUDE = -Igiet_boot \ … … 183 192 $(CC) $(GIET_INCLUDE) $(CFLAGS) -c -o $@ $< 184 193 194 build/drivers/bdv_driver.o: giet_drivers/bdv_driver.c \ 195 giet_drivers/bdv_driver.h \ 196 giet_config.h \ 197 $(MAP_XML) 198 $(CC) $(GIET_INCLUDE) $(CFLAGS) -c -o $@ $< 199 200 build/drivers/hba_driver.o: giet_drivers/hba_driver.c \ 201 giet_drivers/hba_driver.h \ 202 giet_config.h \ 203 $(MAP_XML) 204 $(CC) $(GIET_INCLUDE) $(CFLAGS) -c -o $@ $< 205 206 build/drivers/sdc_driver.o: giet_drivers/sdc_driver.c \ 207 giet_drivers/sdc_driver.h \ 208 giet_config.h \ 209 $(MAP_XML) 210 $(CC) $(GIET_INCLUDE) $(CFLAGS) -c -o $@ $< 211 212 build/drivers/spi_driver.o: giet_drivers/spi_driver.c \ 213 giet_drivers/spi_driver.h \ 214 giet_config.h \ 215 $(MAP_XML) 216 $(CC) $(GIET_INCLUDE) $(CFLAGS) -c -o $@ $< 217 185 218 build/drivers/iob_driver.o: giet_drivers/iob_driver.c \ 186 219 giet_drivers/iob_driver.h \ … … 248 281 giet_common/utils.h \ 249 282 giet_fat32/fat32.h \ 250 giet_common/vmem.h 283 giet_common/vmem.h \ 251 284 giet_drivers/tty_driver.h \ 252 285 giet_drivers/ioc_driver.h \ -
soft/giet_vm/giet_boot/boot.c
r276 r289 1169 1169 unsigned int alloc_tim_channel[X_SIZE*Y_SIZE]; // user TIMER allocators 1170 1170 1171 if ( !GIET_MONO_TTY) alloc_tty_channel++;1171 if (NB_TTY_CHANNELS > 1) alloc_tty_channel++; 1172 1172 1173 1173 ///////////////////////////////////////////////////////////////////////// … … 1372 1372 } 1373 1373 ctx_tty = alloc_tty_channel; 1374 if ( !GIET_MONO_TTY) alloc_tty_channel++;1374 if (NB_TTY_CHANNELS > 1) alloc_tty_channel++; 1375 1375 } 1376 1376 // ctx_nic : NIC channel global index provided by the global allocator … … 1561 1561 void boot_mapping_init() 1562 1562 { 1563 // Initializing the FAT descriptor and files descriptor array 1564 if ( _fat_init( IOC_BOOT_PA_MODE ) ) 1565 { 1566 _puts("[BOOT ERROR] Cannot initialize FAT descriptor fom Boot Sector\n"); 1567 _exit(); 1568 } 1569 1570 #if BOOT_DEBUG_MAPPING 1571 _puts("\n[BOOT] FAT initialisation completed at cycle "); 1572 _putd(_get_proctime()); 1573 _puts("\n"); 1574 _fat_print(); 1575 #endif 1563 _ioc_init( 0 ); 1576 1564 1577 1565 int fd_id = _fat_open( IOC_BOOT_PA_MODE, … … 1746 1734 { 1747 1735 unsigned int i; 1748 for( i = seg_filesz ; i < seg_memsz ; i++ ) boot_buffer[i] = 0;1736 for( i = seg_filesz ; i < seg_memsz ; i++ ) boot_buffer[i+seg_offset] = 0; 1749 1737 } 1750 1738 … … 1927 1915 case PERIPH_TYPE_IOC: // vci_block_device component 1928 1916 { 1929 _ioc_init(); 1917 // initialize all channels except channel 0 because it has been 1918 // initialize during mapping_info loading 1919 for (channel_id = 1; channel_id < channels; channel_id++) 1920 { 1921 _ioc_init( channel_id ); 1922 } 1930 1923 #if BOOT_DEBUG_PERI 1931 1924 _puts("- IOC / channels = "); … … 1953 1946 #if BOOT_DEBUG_PERI 1954 1947 _puts("- FBF / channels = "); 1955 _putd(channels);1956 _puts("\n");1957 #endif1958 break;1959 }1960 case PERIPH_TYPE_HBA: // vci_multi_ahci component1961 {1962 for (channel_id = 0; channel_id < channels; channel_id++)1963 {1964 // TODO1965 }1966 #if BOOT_DEBUG_PERI1967 _puts("- HBA / channels = ");1968 1948 _putd(channels); 1969 1949 _puts("\n"); -
soft/giet_vm/giet_common/io.h
r288 r289 1 /** 2 * \file io.h 3 * \date 5 September 2012 4 * \author Cesar Fuguet 5 * 6 * Utility functions to write or read memory mapped hardware registers 7 */ 1 /////////////////////////////////////////////////////////////////////////////////// 2 // File : io.h 3 // Date : 05/09/2012 4 // Author : cesar fuguet 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////////// 7 // Utility functions to write or read memory mapped hardware registers 8 /////////////////////////////////////////////////////////////////////////////////// 8 9 #ifndef IO_H 9 10 #define IO_H 10 11 11 / **12 *Read an 32 bits memory mapped hardware register13 */12 /////////////////////////////////////////////////////////////////////////////////// 13 // Read an 32 bits memory mapped hardware register 14 /////////////////////////////////////////////////////////////////////////////////// 14 15 static inline unsigned int ioread32(void * addr) 15 16 { … … 17 18 } 18 19 19 / **20 *Read an 16 bits memory mapped hardware register21 */20 /////////////////////////////////////////////////////////////////////////////////// 21 // Read an 16 bits memory mapped hardware register 22 /////////////////////////////////////////////////////////////////////////////////// 22 23 static inline unsigned short ioread16(void * addr) 23 24 { … … 25 26 } 26 27 27 / **28 *Read an 8 bits memory mapped hardware register29 */28 /////////////////////////////////////////////////////////////////////////////////// 29 // Read an 8 bits memory mapped hardware register 30 /////////////////////////////////////////////////////////////////////////////////// 30 31 static inline unsigned char ioread8(void * addr) 31 32 { … … 33 34 } 34 35 35 / **36 *Write an 32 bits memory mapped hardware register37 */36 /////////////////////////////////////////////////////////////////////////////////// 37 // Write an 32 bits memory mapped hardware register 38 /////////////////////////////////////////////////////////////////////////////////// 38 39 static inline void iowrite32(void * addr, unsigned int value) 39 40 { … … 42 43 } 43 44 44 / **45 *Write an 16 bits memory mapped hardware register46 */45 /////////////////////////////////////////////////////////////////////////////////// 46 // Write an 16 bits memory mapped hardware register 47 /////////////////////////////////////////////////////////////////////////////////// 47 48 static inline void iowrite16(void * addr, unsigned short value) 48 49 { … … 51 52 } 52 53 53 / **54 *Write an 8 bits memory mapped hardware register55 */54 /////////////////////////////////////////////////////////////////////////////////// 55 // Write an 8 bits memory mapped hardware register 56 /////////////////////////////////////////////////////////////////////////////////// 56 57 static inline void iowrite8(void * addr, unsigned char value) 57 58 { -
soft/giet_vm/giet_config.h
r267 r289 37 37 #define GIET_IDLE_TASK_VERBOSITY 1 38 38 39 #define GIET_MONO_TTY 0 /* Only one terminal is used */40 41 39 #define GIET_MAX_ELF_FILES 20 /* max .elf files loaded by boot-loader */ 42 40 #define GIET_OPEN_FILES_MAX 16 /* max simultaneously open files */ -
soft/giet_vm/giet_drivers/bdv_driver.c
r288 r289 64 64 // Arguments are: 65 65 // - to_mem : from external storage to memory when non 0. 66 // - kernel : kernel buffer with identity mapping when non 0.66 // - mode : BOOT / KERNEL / USER 67 67 // - lba : first block index on the external storage. 68 // - buf_ vaddr : virtual base address of the memory buffer.68 // - buf_paddr : physical base address of the memory buffer. 69 69 // - count : number of blocks to be transfered. 70 70 // Returns 0 if success, > 0 if error. … … 109 109 ioc_address[BLOCK_DEVICE_LBA] = lba; 110 110 111 // There istwo policies for transfer completion111 // There are two policies for transfer completion 112 112 // detection, depending on the mode argument: 113 113 … … 120 120 121 121 unsigned int status; 122 if ( _bdv_get_status(0, &status) ) return 1; 123 124 while( (status != BLOCK_DEVICE_READ_SUCCESS) && 125 (status != BLOCK_DEVICE_READ_ERROR) && 126 (status != BLOCK_DEVICE_WRITE_SUCCESS) && 127 (status != BLOCK_DEVICE_WRITE_ERROR) ) 122 do 128 123 { 129 if ( _bdv_get_status( 0, &status) ) return 1;124 if ( _bdv_get_status( 0, &status ) ) return 1; 130 125 131 126 #if GIET_DEBUG_IOC_DRIVER … … 134 129 _tty_release_lock( 0 ); 135 130 #endif 136 137 131 } 132 while( (status != BLOCK_DEVICE_READ_SUCCESS) && 133 (status != BLOCK_DEVICE_READ_ERROR) && 134 (status != BLOCK_DEVICE_WRITE_SUCCESS) && 135 (status != BLOCK_DEVICE_WRITE_ERROR) ); 136 138 137 // analyse status 139 138 error = ( (status == BLOCK_DEVICE_READ_ERROR) || -
soft/giet_vm/giet_drivers/hba_driver.c
r258 r289 77 77 #include <ctx_handler.h> 78 78 #include <mmc_driver.h> 79 #include <hba_driver.h> 79 80 #include <vmem.h> 80 81 … … 124 125 { 125 126 volatile unsigned int* hba_address; 126 hba_address = (unsigned int*)(&seg_ hba_base) + (HBA_SPAN*channel);127 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel); 127 128 128 129 if( channel >= NB_HBA_CHANNELS ) 129 130 { 130 _ get_lock(&_tty_put_lock);131 _tty_get_lock( 0 ); 131 132 _puts("\n[GIET ERROR] in _hba_get_status() : illegal channel\n"); 132 _ release_lock(&_tty_put_lock);133 _tty_release_lock( 0 ); 133 134 return 1; 134 135 } … … 146 147 { 147 148 volatile unsigned int* hba_address; 148 hba_address = (unsigned int*)(&seg_ hba_base) + (HBA_SPAN*channel);149 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN*channel); 149 150 150 151 if( channel >= NB_HBA_CHANNELS ) 151 152 { 152 _ get_lock(&_tty_put_lock);153 _tty_get_lock( 0 ); 153 154 _puts("\n[GIET ERROR] in _hba_reset_status() : illegal channel\n"); 154 _ release_lock(&_tty_put_lock);155 _tty_release_lock( 0 ); 155 156 return 1; 156 157 } … … 191 192 hba_cmd_table_t* cmd_table; // command table pointer 192 193 193 // TODO The block size must be obtained from the hardware... 194 block_size = 512; 194 block_size = _hba_get_block_size(); 195 195 196 196 // check buffer alignment 197 197 if( buf_vaddr & (block_size-1) ) 198 198 { 199 _ get_lock(&_tty_put_lock);199 _tty_get_lock( 0 ); 200 200 _puts("\n[GIET ERROR] in _hba_set_cmd() : user buffer not block aligned\n"); 201 _ release_lock(&_tty_put_lock);201 _tty_release_lock( 0 ); 202 202 return 1; 203 203 } … … 207 207 if ( channel_id == 0xFFFFFFFF ) 208 208 { 209 _ get_lock(&_tty_put_lock);209 _tty_get_lock( 0 ); 210 210 _puts("\n[GIET ERROR] in _hba_set_cmd() : no HBA channel allocated\n"); 211 _ release_lock(&_tty_put_lock);211 _tty_release_lock( 0 ); 212 212 return 1; 213 213 } 214 214 215 215 // get hba device address 216 hba_address = (unsigned int*)(&seg_ hba_base) + (HBA_SPAN * channel_id);216 hba_address = (unsigned int*)(&seg_ioc_base) + (HBA_SPAN * channel_id); 217 217 218 218 // get command list status … … 223 223 if( pxci & (1<<cmd_id ) ) 224 224 { 225 _ get_lock(&_tty_put_lock);225 _tty_get_lock( 0 ); 226 226 _puts("\n[GIET ERROR] in _hba_set_cmd() : command list full in channel \n"); 227 227 _putd( channel_id ); 228 228 _puts("\n"); 229 _ release_lock(&_tty_put_lock);229 _tty_release_lock( 0 ); 230 230 return 1; 231 231 } … … 262 262 if ( ko ) 263 263 { 264 _ get_lock(&_tty_put_lock);264 _tty_get_lock( 0 ); 265 265 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer unmapped\n"); 266 _ release_lock(&_tty_put_lock);266 _tty_release_lock( 0 ); 267 267 return 1; 268 268 } 269 269 if ((flags & PTE_U) == 0) 270 270 { 271 _ get_lock(&_tty_put_lock);271 _tty_get_lock( 0 ); 272 272 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not in user space\n"); 273 _ release_lock(&_tty_put_lock);273 _tty_release_lock( 0 ); 274 274 return 1; 275 275 } 276 276 if (((flags & PTE_W) == 0 ) && (is_read == 0) ) 277 277 { 278 _ get_lock(&_tty_put_lock);278 _tty_get_lock( 0 ); 279 279 _puts("[GIET ERROR] in _hba_set_cmd() : user buffer not writable\n"); 280 _ release_lock(&_tty_put_lock);280 _tty_release_lock( 0 ); 281 281 return 1; 282 282 } … … 285 285 if( buf_id > 245 ) 286 286 { 287 _ get_lock(&_tty_put_lock);287 _tty_get_lock( 0 ); 288 288 _puts("[GIET ERROR] in _hba_set_cmd() : max number of buffers is 248\n"); 289 _ release_lock(&_tty_put_lock);289 _tty_release_lock( 0 ); 290 290 return 1; 291 291 } … … 415 415 // Returns 0 if success, > 0 if error. 416 416 /////////////////////////////////////////////////////////////////// 417 unsigned int _hba_write( unsigned int lba, 417 unsigned int _hba_write( unsigned int mode, 418 unsigned int lba, 418 419 void* buffer, 419 420 unsigned int count ) … … 427 428 // Returns 0 if success, > 0 if error. 428 429 /////////////////////////////////////////////////////////////////// 429 unsigned int _hba_read( unsigned int lba, 430 unsigned int _hba_read( unsigned int mode, 431 unsigned int lba, 430 432 void* buffer, 431 433 unsigned int count ) … … 434 436 } 435 437 ////////////////////////////////////////////////////////////////// 436 // This function initializes for a given channel (k)438 // This function initializes for a given channel 437 439 // - the HBA hardware registers, 438 440 // - the command list pointer, … … 440 442 // - the command tables physical addresses array, 441 443 ////////////////////////////////////////////////////////////////// 442 void _hba_init( unsigned int k ) // k == channel_index 444 unsigned int _hba_init( unsigned int channel ) 443 445 { 444 446 unsigned int ppn; … … 452 454 453 455 // HBA registers 454 unsigned int* hba_address = (unsigned int*)(&seg_hba_base) + (HBA_SPAN*k);455 hba_address = (unsigned int*)&seg_ hba_base + HBA_SPAN * k;456 457 hba_address[HBA_PXCLB] = (unsigned int)(&hba_cmd_list[ k]);456 unsigned int* hba_address; 457 hba_address = (unsigned int*)&seg_ioc_base + HBA_SPAN * channel; 458 459 hba_address[HBA_PXCLB] = (unsigned int)(&hba_cmd_list[channel]); 458 460 hba_address[HBA_PXCLBU] = 0; 459 461 hba_address[HBA_PXIE] = 0x40000001; … … 463 465 464 466 // command list pointer 465 hba_cmd_slot[ k] = 0;467 hba_cmd_slot[channel] = 0; 466 468 467 469 // Command list physical addresse 468 vbase = (unsigned int)(&hba_cmd_list[ k]);470 vbase = (unsigned int)(&hba_cmd_list[channel]); 469 471 fail = _v2p_translate( (page_table_t*)pt, 470 472 vbase>>12, … … 473 475 if ( fail ) 474 476 { 475 _ get_lock(&_tty_put_lock);477 _tty_get_lock( 0 ); 476 478 _puts("[GIET ERROR] in _hba_init() : command list unmapped\n"); 477 _ release_lock(&_tty_put_lock);478 _exit();479 } 480 hba_cmd_list_paddr[ k] = ((paddr_t)ppn) | (vbase & 0xFFF);479 _tty_release_lock( 0 ); 480 return 1; 481 } 482 hba_cmd_list_paddr[channel] = ((paddr_t)ppn) | (vbase & 0xFFF); 481 483 482 484 // Command tables physical addresses 483 485 for( c=0 ; c<32 ; c++ ) 484 486 { 485 vbase = (unsigned int)(&hba_cmd_table[ k][c]);487 vbase = (unsigned int)(&hba_cmd_table[channel][c]); 486 488 fail = _v2p_translate( (page_table_t*)pt, 487 489 vbase>>12, … … 490 492 if ( fail ) 491 493 { 492 _ get_lock(&_tty_put_lock);494 _tty_get_lock( 0 ); 493 495 _puts("[GIET ERROR] in _hba_init() : command table unmapped\n"); 494 _release_lock(&_tty_put_lock); 495 _exit(); 496 } 497 hba_cmd_table_paddr[k][c] = ((paddr_t)ppn) | (vbase & 0xFFF); 498 } 496 _tty_release_lock( 0 ); 497 return 1; 498 } 499 hba_cmd_table_paddr[channel][c] = ((paddr_t)ppn) | (vbase & 0xFFF); 500 } 501 502 return 0; 499 503 } 500 504 505 /////////////////////////////////////////////////////////////////////////////// 506 // _hba_get_block_size() 507 // This function returns the block_size of HBA controller 508 /////////////////////////////////////////////////////////////////////////////// 509 unsigned int _hba_get_block_size() 510 { 511 // TODO The block size must be obtained from the hardware... 512 return 512; 513 } 501 514 502 515 -
soft/giet_vm/giet_drivers/hba_driver.h
r258 r289 94 94 95 95 /////////////////////////////////////////////////////////////////////////////////// 96 // HBA device access functions (vci_ multi_nic)96 // HBA device access functions (vci_hba) 97 97 /////////////////////////////////////////////////////////////////////////////////// 98 98 99 unsigned int _hba_write( unsigned int lba, // logic bloc address on device 99 unsigned int _hba_write( unsigned int mode, 100 unsigned int lba, // logic bloc address on device 100 101 void* buffer, // memory buffer base address 101 102 unsigned int count ); // number of blocs 102 103 103 unsigned int _hba_read ( unsigned int lba, // logic bloc address on device 104 unsigned int _hba_read ( unsigned int mode, 105 unsigned int lba, // logic bloc address on device 104 106 void* buffer, // memory buffer base address 105 107 unsigned int count ); // number of blocks 106 108 107 void _hba_init();109 unsigned int _hba_init ( unsigned int channel ); 108 110 109 111 unsigned int _hba_get_status( unsigned int channel, … … 111 113 112 114 unsigned int _hba_reset_status( unsigned int channel ); 115 116 unsigned int _hba_get_block_size (); 113 117 114 118 -
soft/giet_vm/giet_drivers/ioc_driver.c
r279 r289 1 1 /////////////////////////////////////////////////////////////////////////////////// 2 // File : ioc_driver.c 3 // Date : 23/05/2013 4 // Author : alain greiner 2 // File : ioc_driver.c 3 // Date : 23/05/2013 4 // Author : alain greiner 5 // Maintainer : cesar fuguet 5 6 // Copyright (c) UPMC-LIP6 6 7 /////////////////////////////////////////////////////////////////////////////////// … … 12 13 // 13 14 // The _ioc_read() and _ioc_write() functions use the _ioc_access() function, 14 // that is always blocking , but can be called in 4 modes:15 // 16 // - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address17 // as a physical address (as the page tables are not build) and use a polling18 // policy on the IOC_STATUS register to detect transfer completion, as19 // hardware interrupts are not activated. This mode is used by the20 // boot code to load the map.bin file into memory.15 // that is always blocking. The _ioc_access function will call the read or 16 // write function in the driver of the choosen IOC peripheral, which can be for 17 // now: BDV, HBA and SPI. This function can be called in 4 modes: 18 // 19 // - In BOOT_PA mode, the _ioc_access() function use the buffer virtual address 20 // as a physical address (as the page tables are not build). This mode is 21 // used by the boot code to load the map.bin file into memory. 21 22 // 22 23 // - In BOOT_VA mode, the _ioc_access() function makes a V2P translation to 23 // compute the buffer physical address, and use a polling policy on IOC_STATUS 24 // register to detect transfer completion. This mode is used by the boot code 25 // to load the various .elf files into memory. 24 // compute the buffer physical address. This mode is used by the boot code to 25 // load the various .elf files into memory. 26 26 // 27 27 // - In KERNEL mode, the _ioc_access() function makes a V2P translation to 28 // compute the buffer physical address, and use a descheduling strategy: 29 // The ISR executed when transfer completes should restart the calling task. 30 // There is no checking of user access right to the memory buffer. 31 // This mode must be used to access IOC, for an "open" system call. 28 // compute the buffer physical address. There is no checking of user access 29 // right to the memory buffer. This mode must be used to access IOC, for an 30 // "open" system call. 32 31 // 33 32 // - In USER mode, the _ioc_access() function makes a V2P translation to 34 // compute the buffer physical address, and use a descheduling strategy: 35 // The ISR executed when transfer completes should restart the calling task, 36 // The user access right to the memory buffer must be checked. 37 // This mode must be used to access IOC, for a "read/write" system call. 38 // 39 // As the IOC component can be used by several programs running in parallel, 40 // the _ioc_lock variable guaranties exclusive access to the device. The 41 // _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock. 33 // compute the buffer physical address. The user access right to the memory 34 // buffer must be checked. This mode must be used to access IOC, for a 35 // "read/write" system call. 42 36 // 43 37 // The IOMMU can be activated or not: … … 87 81 #endif 88 82 83 #if (USE_BDV + USE_SPI + USE_HBA) != 1 84 # error: You must use only one IOC controller (BDV or SPI or HBA) 85 #endif 86 87 #if USE_BDV 88 # include <bdv_driver.h> 89 #endif 90 91 #if USE_SPI 92 # include <sdc_driver.h> 93 #endif 94 95 #if USE_HBA 96 # include <hba_driver.h> 97 #endif 98 99 89 100 #define in_unckdata __attribute__((section (".unckdata"))) 90 101 91 102 ///////////////////// IOC global variables 92 103 93 in_unckdata unsigned int 94 in_unckdata volatileunsigned int _ioc_status = 0;104 in_unckdata unsigned int _ioc_lock = 0; 105 in_unckdata unsigned int _ioc_status = 0; 95 106 in_unckdata volatile unsigned int _ioc_gtid; 96 107 in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0; … … 155 166 } 156 167 157 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ;158 159 168 unsigned int length = count << 9; // count * 512 bytes 160 169 … … 269 278 } 270 279 271 // get the lock protecting IOC 272 _get_lock(&_ioc_lock); 273 274 // set the _ioc_status polling variable 275 _ioc_status = BLOCK_DEVICE_BUSY; 276 277 #if GIET_DEBUG_IOC_DRIVER 278 _tty_get_lock( 0 ); 279 _puts("\n[IOC DEBUG] _ioc_access() : configure IOC\n"); 280 _puts(" - buf_paddr = "); 281 _putl( buf_paddr ); 282 _puts("\n"); 283 _puts(" - count = "); 284 _putd( count ); 285 _puts("\n"); 286 _puts(" - lba = "); 287 _putx( lba ); 288 _puts("\n"); 289 _tty_release_lock( 0 ); 290 #endif 291 292 // send command to IOC 293 if ( GIET_USE_IOMMU ) 294 { 295 ioc_address[BLOCK_DEVICE_BUFFER] = buf_xaddr; 296 ioc_address[BLOCK_DEVICE_COUNT] = count; 297 ioc_address[BLOCK_DEVICE_LBA] = lba; 298 } 299 else 300 { 301 ioc_address[BLOCK_DEVICE_BUFFER] = (unsigned int)buf_paddr; 302 ioc_address[BLOCK_DEVICE_BUFFER_EXT] = (unsigned int)(buf_paddr>>32); 303 ioc_address[BLOCK_DEVICE_COUNT] = count; 304 ioc_address[BLOCK_DEVICE_LBA] = lba; 305 } 306 307 // There is two policies for transfer completion 308 // detection, depending on the mode argument: 309 310 if ( (mode == IOC_BOOT_PA_MODE) || // We poll directly the IOC_STATUS register 311 (mode == IOC_BOOT_VA_MODE) ) // as IRQs are masked. 312 { 313 // Launch transfert 314 if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE; 315 else ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ; 316 317 unsigned int status; 318 if ( _ioc_get_status(0, &status) ) return 1; 319 320 while( (status != BLOCK_DEVICE_READ_SUCCESS) && 321 (status != BLOCK_DEVICE_READ_ERROR) && 322 (status != BLOCK_DEVICE_WRITE_SUCCESS) && 323 (status != BLOCK_DEVICE_WRITE_ERROR) ) 324 { 325 if ( _ioc_get_status(0, &status) ) return 1; 326 327 #if GIET_DEBUG_IOC_DRIVER 328 _tty_get_lock( 0 ); 329 _puts("\n[IOC DEBUG] _ioc_access() : ... waiting on IOC_STATUS register ...\n"); 330 _tty_release_lock( 0 ); 331 #endif 332 333 } 334 // analyse status 335 error = ( (status == BLOCK_DEVICE_READ_ERROR) || 336 (status == BLOCK_DEVICE_WRITE_ERROR) ); 337 338 // release lock 339 _release_lock(&_ioc_lock); 340 } 341 else // in USER or KERNEL mode, we deschedule the task. 342 // When the task is rescheduled by the ISR, we reset 343 // the _ioc_status variable, and release the lock 344 { 345 // We need a critical section, because we must reset the RUN bit 346 // before to launch the transfer, and we want to avoid to be descheduled 347 // between these two operations. 348 349 // Enter critical section 350 _it_disable(); 351 352 // set _ioc_gtid and reset runnable 353 unsigned int ltid = _get_proc_task_id(); 354 unsigned int pid = _get_procid(); 355 _ioc_gtid = (pid<<16) + ltid; 356 _set_task_slot( pid, ltid, CTX_RUN_ID, 0 ); 357 358 // Launch transfert 359 if (to_mem == 0) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE; 360 else ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ; 361 362 // deschedule task 363 _ctx_switch(); 364 365 // analyse status 366 error = ( (_ioc_status == BLOCK_DEVICE_READ_ERROR) || 367 (_ioc_status == BLOCK_DEVICE_WRITE_ERROR) ); 368 369 // reset _ioc_status and release lock 370 _ioc_status = BLOCK_DEVICE_IDLE; 371 _release_lock(&_ioc_lock); 372 } 373 374 #if GIET_DEBUG_IOC_DRIVER 375 _tty_get_lock( 0 ); 376 _puts("\n[IOC DEBUG] _ioc_access completed at cycle "); 377 _putd( _get_proctime() ); 378 _puts(" for processor "); 379 _putd( _get_procid() ); 380 _puts(" : error = "); 381 _putd( (unsigned int)error ); 382 _puts("\n"); 383 _tty_release_lock( 0 ); 280 if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr; 281 282 #if USE_BDV 283 if (to_mem) error = _bdv_read (mode, lba, buf_paddr, count); 284 else error = _bdv_write(mode, lba, buf_paddr, count); 285 #elif USE_SPI 286 if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count); 287 else error = _sdc_write(mode, lba, buf_paddr, count); 288 #elif USE_HBA 289 if (to_mem) error = _hba_read (mode, lba, buf_paddr, count); 290 else error = _hba_write(mode, lba, buf_paddr, count); 384 291 #endif 385 292 … … 392 299 // Return 0 for success. 393 300 /////////////////////////////////////////////////////////////////////////////// 394 unsigned int _ioc_init() 395 { 396 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base ; 397 398 if ( ioc_address[BLOCK_DEVICE_BLOCK_SIZE] != 512 ) 399 { 400 _puts("\n[GIET ERROR] in _ioc_init() : block size must be 512 bytes\n"); 401 _exit(); 402 } 403 404 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1; 405 return 0; 301 unsigned int _ioc_init( unsigned int channel ) 302 { 303 #if USE_BDV 304 return _bdv_init( channel ); 305 #elif USE_SPI 306 return _sdc_init( channel ); 307 #elif USE_HBA 308 return _hba_init( channel ); 309 #endif 406 310 } 407 311 … … 457 361 unsigned int* status ) 458 362 { 459 if ( channel != 0 ) 460 { 461 _tty_get_lock( 0 ); 462 _puts("\n[GIET ERROR] in _ioc_get_status : illegal channel\n"); 463 _tty_release_lock( 0 ); 464 465 return 1; 466 } 467 468 // get IOC base address 469 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base; 470 *status = ioc_address[BLOCK_DEVICE_STATUS]; 471 472 return 0; 363 #if USE_BDV 364 return _bdv_get_status(channel, status); 365 #elif USE_SPI 366 return _sdc_get_status(channel, status); 367 #elif USE_HBA 368 return _hba_get_status(channel, status); 369 #endif 473 370 } 474 371 … … 479 376 unsigned int _ioc_get_block_size() 480 377 { 481 // get IOC base address 482 volatile unsigned int * ioc_address = (unsigned int *) &seg_ioc_base; 483 484 return ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 378 #if USE_BDV 379 return _bdv_get_block_size(); 380 #elif USE_SPI 381 return _sdc_get_block_size(); 382 #elif USE_HBA 383 return _hba_get_block_size(); 384 #endif 485 385 } 486 386 -
soft/giet_vm/giet_drivers/ioc_driver.h
r279 r289 6 6 /////////////////////////////////////////////////////////////////////////////////// 7 7 8 #ifndef _GIET_IOC_DRIVER S_H_9 #define _GIET_IOC_DRIVER S_H_8 #ifndef _GIET_IOC_DRIVER_H_ 9 #define _GIET_IOC_DRIVER_H_ 10 10 11 11 /////////////////////////////////////////////////////////////////////////////////// … … 53 53 /////////////////////////////////////////////////////////////////////////////////// 54 54 55 extern unsigned int 56 extern volatileunsigned int _ioc_status;55 extern unsigned int _ioc_lock; 56 extern unsigned int _ioc_status; 57 57 extern volatile unsigned int _ioc_gtid; 58 58 extern volatile unsigned int _ioc_iommu_ix1; 59 59 extern volatile unsigned int _ioc_iommu_npages; 60 60 61 extern unsigned int _ioc_init( );61 extern unsigned int _ioc_init( unsigned int channel ); 62 62 63 63 extern unsigned int _ioc_write( unsigned int mode, -
soft/giet_vm/giet_fat32/fat32.c
r273 r289 871 871 if( fat.initialised != FAT_INITIALISED ) 872 872 { 873 _fat_init( mode ); 873 if ( _fat_init( mode ) ) 874 { 875 _puts("[FAT ERROR] Cannot initialize FAT descriptor fom Boot Sector\n"); 876 _exit(); 877 } 878 879 #if GIET_DEBUG_FAT 880 _tty_get_lock( 0 ); 881 _puts("\n[FAT DEBUG] FAT initialisation completed at cycle "); 882 _putd(_get_proctime()); 883 _puts("\n"); 884 _fat_print(); 885 _tty_release_lock( 0 ); 886 #endif 874 887 } 875 888 -
soft/giet_vm/giet_kernel/kernel_init.c
r281 r289 64 64 65 65 //////////////////////////////////////////////////////////////////////////////////// 66 // staks for the "idle" tasks ( 256bytes for each processor)66 // staks for the "idle" tasks (512 bytes for each processor) 67 67 //////////////////////////////////////////////////////////////////////////////////// 68 68 69 69 __attribute__((section (".kdata"))) 70 unsigned int _idle_stack[X_SIZE *Y_SIZE * NB_PROCS_MAX * 128];70 unsigned int _idle_stack[X_SIZE * Y_SIZE * NB_PROCS_MAX * 128 ]; 71 71 72 72 //////////////////////////////////////////////////////////////////////////////////// … … 343 343 // step 5 : each processor updates the idle_task context: 344 344 // (only CTX_SP, CTX_RA, CTX_EPC). 345 // The stack size is 256bytes, reserved in seg_kdata.345 // The stack size is 512 bytes, reserved in seg_kdata. 346 346 // The PTPR register, the CTX_PTPR and CTX_PTAB slots 347 347 // have been initialised in boot code. 348 348 349 unsigned int stack = (unsigned int)_idle_stack + ((global_pid + 1)<<9); 349 unsigned int x = cluster_xy >> Y_WIDTH; 350 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 351 unsigned int p = ((x * Y_SIZE) + y) * NB_PROCS_MAX + local_pid; 352 353 unsigned int stack = (unsigned int)_idle_stack + ((p + 1)<<9); 350 354 351 355 _set_task_slot( global_pid, IDLE_TASK_INDEX, CTX_SP_ID, stack); -
soft/giet_vm/giet_libs/stdio.c
r271 r289 298 298 unsigned int ret; 299 299 300 if ( GIET_MONO_TTY)300 if (NB_TTY_CHANNELS == 1) 301 301 { 302 302 ret = sys_call(SYSCALL_TTY_LOCK, 0, 0, 0, 0); // Get TTY lock … … 328 328 } 329 329 330 if ( GIET_MONO_TTY)330 if (NB_TTY_CHANNELS == 1) 331 331 { 332 332 ret = sys_call(SYSCALL_TTY_LOCK, 1, 0, 0, 0); // Release TTY lock … … 412 412 413 413 return_error: 414 if ( GIET_MONO_TTY)414 if (NB_TTY_CHANNELS == 1) 415 415 { 416 416 ret = sys_call(SYSCALL_TTY_LOCK, 1, 0, 0, 0); // Release TTY lock -
soft/giet_vm/giet_xml/mapping_info.h
r287 r289 104 104 PERIPH_TYPE_DMA = 1, 105 105 PERIPH_TYPE_FBF = 2, 106 PERIPH_TYPE_HBA = 3, 107 PERIPH_TYPE_ICU = 4, 108 PERIPH_TYPE_IOB = 5, 109 PERIPH_TYPE_IOC = 6, 110 PERIPH_TYPE_MMC = 7, 111 PERIPH_TYPE_MWR = 8, 112 PERIPH_TYPE_NIC = 9, 113 PERIPH_TYPE_ROM = 10, 114 PERIPH_TYPE_SIM = 11, 115 PERIPH_TYPE_TIM = 12, 116 PERIPH_TYPE_TTY = 13, 117 PERIPH_TYPE_XCU = 14, 118 119 PERIPH_TYPE_MAX_VALUE = 15, 120 }; 121 106 PERIPH_TYPE_ICU = 3, 107 PERIPH_TYPE_IOB = 4, 108 PERIPH_TYPE_IOC = 5, 109 PERIPH_TYPE_MMC = 6, 110 PERIPH_TYPE_MWR = 7, 111 PERIPH_TYPE_NIC = 8, 112 PERIPH_TYPE_ROM = 9, 113 PERIPH_TYPE_SIM = 10, 114 PERIPH_TYPE_TIM = 11, 115 PERIPH_TYPE_TTY = 12, 116 PERIPH_TYPE_XCU = 13, 117 118 PERIPH_TYPE_MAX_VALUE = 14, 119 }; 120 121 enum periphSubtype 122 { 123 PERIPH_SUBTYPE_BDV = 0, 124 PERIPH_SUBTYPE_HBA = 1, 125 PERIPH_SUBTYPE_SPI = 2, 126 127 PERIPH_SUBTYPE_MAX_VALUE = 3, 128 }; 122 129 123 130 enum mwmrPortDirection … … 146 153 unsigned int fbf_cluster; // index of cluster containing FBF controler 147 154 unsigned int fbf_cluster_bis; // index of cluster containing second FBF controler 148 149 unsigned int hba_cluster; // index of cluster containing HBA controler150 unsigned int hba_cluster_bis; // index of cluster containing second HBA controler151 155 152 156 unsigned int iob_cluster; // index of cluster containing IOB controler … … 320 324 { 321 325 unsigned int type; 326 unsigned int subtype; // periph specialization 322 327 unsigned int psegid; // pseg index in cluster 323 328 unsigned int channels; // number of channels -
soft/giet_vm/giet_xml/xml_driver.c
r287 r289 63 63 "DMA", 64 64 "FBF", 65 "HBA",66 65 "ICU", 67 66 "IOB", … … 75 74 "TTY", 76 75 "XCU", 76 }; 77 78 const char * periph_subtype[] = 79 { 80 "BDV", 81 "HBA", 82 "SPI", 77 83 }; 78 84 … … 308 314 { 309 315 fprintf(fpout, " <periph type = \"%s\" ", periph_type[periph[periph_id].type]); 316 317 if (periph[periph_id].subtype < PERIPH_SUBTYPE_MAX_VALUE) 318 fprintf(fpout, " subtype = \"%s\" ", periph_subtype[periph[periph_id].subtype]); 319 310 320 fprintf(fpout, " psegname = \"%s\" ", pseg[periph[periph_id].psegid].name); 311 321 fprintf(fpout, " channels = \"%d\" />\n", periph[periph_id].channels); -
soft/giet_vm/giet_xml/xml_parser.c
r287 r289 123 123 unsigned int use_iob = 0; // using IOB component 124 124 unsigned int use_xcu = 0; // using XCU (not ICU) 125 126 // These variables define the IOC peripheral subtype 125 127 unsigned int use_hba = 0; // using HBA 128 unsigned int use_bdv = 0; // using SoCLIB block device 129 unsigned int use_spi = 0; // using SD Card-SPI 126 130 127 131 //////////////////////////////////////////////////////////////// … … 1252 1256 unsigned int error = 0; 1253 1257 1258 // initialize peripheral subtype 1259 periph[periph_index]->subtype = 0xFFFFFFFF; 1260 1254 1261 // The CMA, FBF, HBA, IOB, IOC, NIC, ROM, SIM, TTY, peripherals are not 1255 1262 // replicated in all clusters but can be replicated in two clusters (fault tolerance) … … 1294 1301 } 1295 1302 ///////////////////////////////// 1296 else if (strcmp(str, "HBA") == 0)1297 {1298 periph[periph_index]->type = PERIPH_TYPE_HBA;1299 use_hba = 1;1300 if (header->hba_cluster == 0xFFFFFFFF)1301 {1302 header->hba_cluster = cluster_index;1303 hba_channels = periph[periph_index]->channels;1304 }1305 else if (header->hba_cluster_bis == 0xFFFFFFFF)1306 {1307 header->hba_cluster_bis = cluster_index;1308 assert( (hba_channels == periph[periph_index]->channels) &&1309 "[XML ERROR] unconsistent non replicated peripheral");1310 }1311 else1312 {1313 error = 1;1314 }1315 }1316 /////////////////////////////////1317 1303 else if (strcmp(str, "IOB") == 0) 1318 1304 { … … 1346 1332 else 1347 1333 { 1348 error = 1; 1334 printf("[XML ERROR] At most two copies for non replicated " 1335 "peripheral\n"); 1336 exit(1); 1337 } 1338 1339 str = getStringValue(reader, "subtype", &ok); 1340 1341 if (!ok) 1342 { 1343 printf("[XML ERROR] IOC peripheral needs a subtype parameter: " 1344 "BDV, HBA or SPI\n"); 1345 exit(1); 1346 } 1347 1348 if (strcmp(str, "BDV") == 0) 1349 { 1350 periph[periph_index]->subtype = PERIPH_SUBTYPE_BDV; 1351 use_bdv = 1; 1352 } 1353 else if (strcmp(str, "HBA") == 0) 1354 { 1355 periph[periph_index]->subtype = PERIPH_SUBTYPE_HBA; 1356 1357 if (use_hba == 0) 1358 { 1359 use_hba = 1; 1360 hba_channels = periph[periph_index]->channels; 1361 } 1362 else 1363 { 1364 assert( (hba_channels == periph[periph_index]->channels) && 1365 "[XML ERROR] unconsistent non replicated peripheral"); 1366 } 1367 } 1368 else if (strcmp(str, "SPI") == 0) 1369 { 1370 periph[periph_index]->subtype = PERIPH_SUBTYPE_SPI; 1371 use_spi = 1; 1372 } 1373 else 1374 { 1375 printf("[XML ERROR] illegal subtype for IOC peripheral\n"); 1376 exit(1); 1349 1377 } 1350 1378 } … … 2325 2353 header->fbf_cluster = 0xFFFFFFFF; 2326 2354 header->fbf_cluster_bis = 0xFFFFFFFF; 2327 2328 header->hba_cluster = 0xFFFFFFFF;2329 header->hba_cluster_bis = 0xFFFFFFFF;2330 2355 2331 2356 header->iob_cluster = 0xFFFFFFFF; … … 2589 2614 def_int_write(fdout, "USE_IOB ", use_iob); 2590 2615 def_int_write(fdout, "USE_HBA ", use_hba); 2616 def_int_write(fdout, "USE_BDV ", use_bdv); 2617 def_int_write(fdout, "USE_SPI ", use_spi); 2591 2618 2592 2619 file_write(fdout, "\n"); … … 2720 2747 ld_write(fdout, "seg_cma_base ", periph_vbase_array[PERIPH_TYPE_CMA]); 2721 2748 ld_write(fdout, "seg_fbf_base ", periph_vbase_array[PERIPH_TYPE_FBF]); 2722 ld_write(fdout, "seg_hba_base ", periph_vbase_array[PERIPH_TYPE_HBA]);2723 2749 ld_write(fdout, "seg_iob_base ", periph_vbase_array[PERIPH_TYPE_IOB]); 2724 2750 ld_write(fdout, "seg_ioc_base ", periph_vbase_array[PERIPH_TYPE_IOC]); -
soft/giet_vm/mappings/4c_1p_four.xml
r287 r289 53 53 <periph type = "XCU" psegname = "PSEG_XCU" channels = "4" /> 54 54 <periph type = "MMC" psegname = "PSEG_MMC" channels = "1" /> 55 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" />55 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" subtype = "BDV" /> 56 56 <periph type = "TTY" psegname = "PSEG_TTY" channels = "8" /> 57 57 <periph type = "NIC" psegname = "PSEG_NIC" channels = "2" /> -
soft/giet_vm/mappings/4c_1p_iob_four.xml
r287 r289 72 72 <periph type = "XCU" psegname = "PSEG_XCU" channels = "1" /> 73 73 <periph type = "MMC" psegname = "PSEG_MMC" channels = "1" /> 74 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" />74 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" subtype = "BDV" /> 75 75 <periph type = "TTY" psegname = "PSEG_TTY" channels = "8" /> 76 76 <periph type = "NIC" psegname = "PSEG_NIC" channels = "2" /> -
soft/giet_vm/mappings/4c_1p_iob_sort.xml
r287 r289 72 72 <periph type = "XCU" psegname = "PSEG_XCU" channels = "1" /> 73 73 <periph type = "MMC" psegname = "PSEG_MMC" channels = "1" /> 74 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" />75 <periph type = "TTY" psegname = "PSEG_TTY" channels = "5" />74 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" subtype = "BDV" /> 75 <periph type = "TTY" psegname = "PSEG_TTY" channels = "5" /> 76 76 <periph type = "NIC" psegname = "PSEG_NIC" channels = "2" /> 77 77 <periph type = "CMA" psegname = "PSEG_CMA" channels = "4" /> -
soft/giet_vm/mappings/4c_1p_sort.xml
r287 r289 50 50 <periph type = "XCU" psegname = "PSEG_XCU" channels = "1" /> 51 51 <periph type = "MMC" psegname = "PSEG_MMC" channels = "1" /> 52 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" />53 <periph type = "TTY" psegname = "PSEG_TTY" channels = " 5"/>52 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" subtype = "BDV" /> 53 <periph type = "TTY" psegname = "PSEG_TTY" channels = "9" /> 54 54 <periph type = "NIC" psegname = "PSEG_NIC" channels = "2" /> 55 55 <periph type = "CMA" psegname = "PSEG_CMA" channels = "4" /> … … 126 126 </vseg> 127 127 <vseg name = "seg_boot_buffer" vbase = "0x00040000" mode = "C_W_" x = "0" y = "0" psegname = "PSEG_RAM" ident = "1" > 128 <vobj name = "boot_buffer" type = "BUFFER" length = "0x000 20000" />129 </vseg> 130 <vseg name = "seg_boot_stack" vbase = "0x000 60000" mode = "C_W_" x = "0" y = "0" psegname = "PSEG_RAM" ident = "1" >128 <vobj name = "boot_buffer" type = "BUFFER" length = "0x00080000" /> 129 </vseg> 130 <vseg name = "seg_boot_stack" vbase = "0x000C0000" mode = "C_W_" x = "0" y = "0" psegname = "PSEG_RAM" ident = "1" > 131 131 <vobj name = "boot_stack" type = "BUFFER" length = "0x00090000" /> 132 132 </vseg> -
soft/giet_vm/mappings/4c_1p_sort_chiplet.xml
r287 r289 38 38 <periph type = "XCU" psegname = "PSEG_XCU" channels = "4" /> 39 39 <periph type = "MMC" psegname = "PSEG_MMC" channels = "1" /> 40 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" />40 <periph type = "IOC" psegname = "PSEG_IOC" channels = "1" subtype = "SPI" /> 41 41 <periph type = "TTY" psegname = "PSEG_TTY" channels = "1" /> 42 42 <periph type = "ROM" psegname = "PSEG_ROM" channels = "1" />
Note: See TracChangeset
for help on using the changeset viewer.