Changeset 166 for soft/giet_vm/sys/drivers.c
- Timestamp:
- Jul 6, 2012, 10:13:16 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/sys/drivers.c
r165 r166 34 34 /////////////////////////////////////////////////////////////////////////////////// 35 35 36 #include <vm_handler.h> 36 37 #include <sys_handler.h> 37 38 #include <giet_config.h> … … 87 88 in_unckdata volatile unsigned char _dma_busy[NB_DMAS] = { [0 ... NB_DMAS-1] = 0 }; 88 89 89 in_unckdata volatile unsigned char _ioc_status; 90 in_unckdata volatile unsigned char _ioc_done = 0; 91 in_unckdata volatile unsigned int _ioc_lock = 0; 90 in_unckdata volatile unsigned char _ioc_status = 0; 91 in_unckdata volatile unsigned char _ioc_done = 0; 92 in_unckdata unsigned int _ioc_lock = 0; 93 in_unckdata unsigned int _ioc_iommu_ix1 = 0; 94 in_unckdata unsigned int _ioc_iommu_npages = 0; 92 95 93 96 in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS]; … … 394 397 //////////////////////////////////////////////////////////////////////////////// 395 398 // The VciBlockDevice is a single channel external storage contrÃŽler. 396 // The three functions below use the three variables _ioc_lock _ioc_done, and 397 // _ioc_status for synchronisation. 399 // 400 // The IOMMU can be activated or not: 401 // 402 // 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to 403 // the IOC peripheral, in the I/O virtual space, and the user buffer is 404 // dynamically remapped in the IOMMU page table. The corresponding entry 405 // in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable. 406 // The number of pages to be unmapped is stored in the _ioc_npages variable. 407 // The number of PT2 entries is dynamically computed and stored in the 408 // kernel _ioc_iommu_npages variable. It cannot be larger than 512. 409 // The user buffer is unmapped by the _ioc_completed() function when 410 // the transfer is completed. 411 // 412 // 2/ If the IOMMU is not used, we check that the user buffer is mapped to a 413 // contiguous physical buffer (this is generally true because the user space 414 // page tables are statically constructed to use contiguous physical memory). 415 // 416 // Finally, the memory buffer must fulfill the following conditions: 417 // - The user buffer must be word aligned, 418 // - The user buffer must be mapped in user address space, 419 // - The user buffer must be writable in case of (to_mem) access, 420 // - The total number of physical pages occupied by the user buffer cannot 421 // be larger than 512 pages if the IOMMU is activated, 422 // - All physical pages occupied by the user buffer must be contiguous 423 // if the IOMMU is not activated. 424 // An error code is returned if these conditions are not verified. 425 // 398 426 // As the IOC component can be used by several programs running in parallel, 399 427 // the _ioc_lock variable guaranties exclusive access to the device. The … … 407 435 // variable. 408 436 // The _ioc_completed() function is polling the _ioc_done variable, waiting for 409 // tran fer conpletion. When the completion is signaled, the _ioc_completed()437 // transfer completion. When the completion is signaled, the _ioc_completed() 410 438 // function reset the _ioc_done variable to zero, and releases the _ioc_lock 411 439 // variable. … … 447 475 448 476 /////////////////////////////////////////////////////////////////////////////// 449 // _ioc_write() 450 // 451 // Transfer data from a memory buffer to a file on the block_device. 452 // The source memory buffer must be in user address space. 453 // - lba : first block index on the disk. 454 // - buffer : base address of the memory buffer. 477 // _ioc_access() 478 // This function transfer data between a memory buffer and the block device. 479 // The buffer lentgth is (count*block_size) bytes. 480 // 481 // Arguments are: 482 // - to_mem : from external storage to memory when non 0 483 // - lba : first block index on the external storage. 484 // - user_vaddr : virtual base address of the memory buffer. 485 // - count : number of blocks to be transfered. 486 // Returns 0 if success, > 0 if error. 487 /////////////////////////////////////////////////////////////////////////////// 488 unsigned int _ioc_access( unsigned int to_mem, 489 unsigned int lba, 490 unsigned int user_vaddr, 491 unsigned int count ) 492 { 493 unsigned int user_vpn_min; 494 unsigned int user_vpn_max; 495 unsigned int vpn; // virtual page number in user space 496 unsigned int ppn; // physical page number 497 unsigned int flags; // page protection flags 498 unsigned int ix2; // Page index (for IOMMU page table) 499 unsigned int addr; // buffer address for IOC 500 page_table_t* user_ptp; // user page table pointer 501 unsigned int ko; // bool returned by _v2p_translate() 502 unsigned int ppn_first; // first physical page number for user buffer 503 504 // check buffer alignment 505 if ( (unsigned int)user_vaddr & 0x3 ) return 1; 506 507 unsigned int* ioc_address = (unsigned int*)&seg_ioc_base; 508 unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 509 unsigned int length = count*block_size; 510 511 // get user space page table base address 512 user_ptp = (page_table_t*)(_get_ptpr() << 13); 513 514 user_vpn_min = user_vaddr >> 12; 515 user_vpn_max = (user_vaddr + length - 1) >> 12; 516 ix2 = 0; 517 518 // loop on all virtual pages covering the user buffer 519 for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ ) 520 { 521 // get ppn and flags for each vpn 522 ko = _v2p_translate( user_ptp, // user page table pointer 523 vpn, // virtual page number 524 &ppn, // physical page number 525 &flags ); // protection flags 526 527 // check access rights 528 if ( ko ) return 2; // unmapped 529 if ( (flags & PTE_U) == 0 ) return 3; // not in user space 530 if ( ( (flags & PTE_W) == 0 ) && to_mem ) return 4; // not writable 531 532 // save first ppn value 533 if ( ix2 == 0 ) ppn_first = ppn; 534 535 if ( GIET_IOMMU_ACTIVE ) // the user buffer must be remapped in the I/0 space 536 { 537 // check buffer length < 2 Mbytes 538 if ( ix2 > 511 ) return 2; 539 540 // map the physical page in IOMMU page table 541 _iommu_add_pte2( _ioc_iommu_ix1, // PT1 index 542 ix2, // PT2 index 543 ppn, // Physical page number 544 flags ); // Protection flags 545 546 // buffer base address for IOC with IOMMU 547 } 548 else // no IOMMU : check that physical pages are contiguous 549 { 550 if ( (ppn - ppn_first) != ix2 ) return 5; // split physical buffer 551 } 552 553 // increment page index 554 ix2++; 555 } // end for vpn 556 557 // register the number of pages to be unmapped 558 _ioc_iommu_npages = (user_vpn_max - user_vpn_min) + 1; 559 560 // invalidate data cache in case of memory write 561 if ( to_mem ) _dcache_buf_invalidate( (void*)user_vaddr, length ); 562 563 // compute buffer base address for IOC depending on IOMMU activation 564 if ( GIET_IOMMU_ACTIVE ) addr = (_ioc_iommu_ix1) << 21 | (user_vaddr & 0xFFF); 565 else addr = ppn_first | (user_vaddr & 0xFFF); 566 567 // get the lock on ioc device 568 _ioc_get_lock(); 569 570 // peripheral configuration 571 ioc_address[BLOCK_DEVICE_BUFFER] = addr; 572 ioc_address[BLOCK_DEVICE_COUNT] = count; 573 ioc_address[BLOCK_DEVICE_LBA] = lba; 574 if ( to_mem == 0 ) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE; 575 else ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ; 576 577 return 0; 578 } 579 580 ///////////////////////////////////////////////////////////////////////////////// 581 // _ioc_completed() 582 // 583 // This function checks completion of an I/O transfer and reports errors. 584 // As it is a blocking call, the processor is stalled. 585 // If the virtual memory is activated, the pages mapped in the I/O virtual 586 // space are unmapped, and the IOB TLB is cleared. 587 // Returns 0 if success, > 0 if error. 588 ///////////////////////////////////////////////////////////////////////////////// 589 unsigned int _ioc_completed() 590 { 591 unsigned int ret; 592 unsigned int ix2; 593 594 // busy waiting 595 while (_ioc_done == 0) 596 asm volatile("nop"); 597 598 // unmap the buffer from IOMMU page table if IOMMU is activated 599 if ( GIET_IOMMU_ACTIVE ) 600 { 601 unsigned int* iob_address = (unsigned int*)&seg_iob_base; 602 603 for ( ix2 = 0 ; ix2 < _ioc_iommu_npages ; ix2++ ) 604 { 605 // unmap the page in IOMMU page table 606 _iommu_inval_pte2( _ioc_iommu_ix1, // PT1 index 607 ix2 ); // PT2 index 608 609 // clear IOMMU TLB 610 iob_address[IOB_INVAL_PTE] = (_ioc_iommu_ix1 << 21) | (ix2) << 12; 611 } 612 } 613 614 // test IOC status 615 if ((_ioc_status != BLOCK_DEVICE_READ_SUCCESS) 616 && (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS)) ret = 1; // error 617 else ret = 0; // success 618 619 // reset synchronization variables 620 _ioc_lock =0; 621 _ioc_done =0; 622 623 return ret; 624 } 625 626 /////////////////////////////////////////////////////////////////////////////// 627 // _ioc_read() 628 // Transfer data from the block device to a memory buffer in user space. 629 // - lba : first block index on the block device 630 // - buffer : base address of the memory buffer (must be word aligned) 631 // - count : number of blocks to be transfered. 632 // Returns 0 if success, > 0 if error. 633 /////////////////////////////////////////////////////////////////////////////// 634 unsigned int _ioc_read( unsigned int lba, 635 void* buffer, 636 unsigned int count ) 637 { 638 return _ioc_access( 1, // read 639 lba, 640 (unsigned int)buffer, 641 count ); 642 } 643 644 /////////////////////////////////////////////////////////////////////////////// 645 // _ioc_write() 646 // Transfer data from a memory buffer in user space to the block device. 647 // - lba : first block index on the block device 648 // - buffer : base address of the memory buffer (must be word aligned) 455 649 // - count : number of blocks to be transfered. 456 650 // Returns 0 if success, > 0 if error. … … 458 652 unsigned int _ioc_write( unsigned int lba, 459 653 const void* buffer, 460 unsigned int count) 461 { 462 volatile unsigned int *ioc_address; 463 464 ioc_address = (unsigned int*)&seg_ioc_base; 465 466 /* buffer must be in user space */ 467 unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 468 469 if (((unsigned int)buffer >= 0x80000000) 470 || (((unsigned int)buffer + block_size*count) >= 0x80000000)) 471 return 1; 472 473 /* get the lock on ioc device */ 474 _ioc_get_lock(); 475 476 /* block_device configuration for the write transfer */ 477 ioc_address[BLOCK_DEVICE_BUFFER] = (unsigned int)buffer; 478 ioc_address[BLOCK_DEVICE_COUNT] = count; 479 ioc_address[BLOCK_DEVICE_LBA] = lba; 480 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1; 481 ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE; 482 483 return 0; 484 } 485 486 /////////////////////////////////////////////////////////////////////////////// 487 // _ioc_read() 488 // 489 // Transfer data from a file on the block device to a memory buffer. 490 // The destination memory buffer must be in user address space. 491 // - lba : first block index on the disk. 492 // - buffer : base address of the memory buffer. 493 // - count : number of blocks to be transfered. 494 // All cache lines corresponding to the the target buffer are invalidated 495 // for cache coherence. 496 // Returns 0 if success, > 0 if error. 497 /////////////////////////////////////////////////////////////////////////////// 498 unsigned int _ioc_read( unsigned int lba, 499 void* buffer, 500 unsigned int count ) 501 { 502 volatile unsigned int *ioc_address; 503 504 ioc_address = (unsigned int*)&seg_ioc_base; 505 506 /* buffer must be in user space */ 507 unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 508 509 if (((unsigned int)buffer >= 0x80000000) 510 || (((unsigned int)buffer + block_size*count) >= 0x80000000)) 511 return 1; 512 513 /* get the lock on ioc device */ 514 _ioc_get_lock(); 515 516 /* block_device configuration for the read transfer */ 517 ioc_address[BLOCK_DEVICE_BUFFER] = (unsigned int)buffer; 518 ioc_address[BLOCK_DEVICE_COUNT] = count; 519 ioc_address[BLOCK_DEVICE_LBA] = lba; 520 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1; 521 ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ; 522 523 /* invalidation of data cache */ 524 _dcache_buf_invalidate(buffer, block_size*count); 525 526 return 0; 527 } 528 529 ///////////////////////////////////////////////////////////////////////////////// 530 // _ioc_completed() 531 // 532 // This function checks completion of an I/O transfer and reports errors. 533 // As it is a blocking call, the processor is stalled until the next interrupt. 534 // Returns 0 if success, > 0 if error. 535 ///////////////////////////////////////////////////////////////////////////////// 536 unsigned int _ioc_completed() 537 { 538 unsigned int ret; 539 540 /* busy waiting */ 541 while (_ioc_done == 0) 542 asm volatile("nop"); 543 544 /* test IOC status */ 545 if ((_ioc_status != BLOCK_DEVICE_READ_SUCCESS) 546 && (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS)) ret = 1; /* error */ 547 else ret = 0; /* success */ 548 549 /* reset synchronization variables */ 550 _ioc_lock =0; 551 _ioc_done =0; 552 553 return ret; 654 unsigned int count ) 655 { 656 return _ioc_access( 0, // write 657 lba, 658 (unsigned int)buffer, 659 count ); 554 660 } 555 661
Note: See TracChangeset
for help on using the changeset viewer.