mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 12:07:31 +00:00 
			
		
		
		
	 907b5105f1
			
		
	
	
		907b5105f1
		
	
	
	
	
		
			
			Since commit a2ce7dbd91 ("meson: convert tests/qtest to meson"),
libqtest.h is under libqos/ directory, while libqtest.c is still in
qtest/. Move back to its original location to avoid mixing with libqos/.
Suggested-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
		
	
			
		
			
				
	
	
		
			117 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * MMC Host Controller Commands
 | |
|  *
 | |
|  * Copyright (c) 2021 Google LLC
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms of the GNU General Public License as published by the
 | |
|  * Free Software Foundation; either version 2 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful, but WITHOUT
 | |
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 | |
|  * for more details.
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "sdhci-cmd.h"
 | |
| #include "../libqtest.h"
 | |
| 
 | |
| static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count)
 | |
| {
 | |
|     uint32_t mask = 0xff;
 | |
|     size_t index = 0;
 | |
|     uint32_t msg_frag;
 | |
|     int size;
 | |
|     while (index < count) {
 | |
|         size = count - index;
 | |
|         if (size > 4) {
 | |
|             size = 4;
 | |
|         }
 | |
|         msg_frag = qtest_readl(qts, reg);
 | |
|         while (size > 0) {
 | |
|             msg[index] = msg_frag & mask;
 | |
|             if (msg[index++] == 0) {
 | |
|                 return index;
 | |
|             }
 | |
|             msg_frag >>= 8;
 | |
|             --size;
 | |
|         }
 | |
|     }
 | |
|     return index;
 | |
| }
 | |
| 
 | |
| static void write_fifo(QTestState *qts, uint64_t reg, const char *msg,
 | |
|                        size_t count)
 | |
| {
 | |
|     size_t index = 0;
 | |
|     uint32_t msg_frag;
 | |
|     int size;
 | |
|     int frag_i;
 | |
|     while (index < count) {
 | |
|         size = count - index;
 | |
|         if (size > 4) {
 | |
|             size = 4;
 | |
|         }
 | |
|         msg_frag = 0;
 | |
|         frag_i = 0;
 | |
|         while (frag_i < size) {
 | |
|             msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8);
 | |
|             ++frag_i;
 | |
|         }
 | |
|         qtest_writel(qts, reg, msg_frag);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void fill_block(QTestState *qts, uint64_t reg, int count)
 | |
| {
 | |
|     while (--count >= 0) {
 | |
|         qtest_writel(qts, reg, 0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,
 | |
|                     uint16_t blkcnt, uint32_t argument, uint16_t trnmod,
 | |
|                     uint16_t cmdreg)
 | |
| {
 | |
|     qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize);
 | |
|     qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt);
 | |
|     qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument);
 | |
|     qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod);
 | |
|     qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg);
 | |
| }
 | |
| 
 | |
| ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,
 | |
|                        size_t count)
 | |
| {
 | |
|     sdhci_cmd_regs(qts, base_addr, count, 1, 0,
 | |
|                    SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
 | |
|                    SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
 | |
| 
 | |
|     /* read sd fifo_buffer */
 | |
|     ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count);
 | |
| 
 | |
|     sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
 | |
|                    SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
 | |
|                    SDHC_STOP_TRANSMISSION);
 | |
| 
 | |
|     return bytes_read;
 | |
| }
 | |
| 
 | |
| void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,
 | |
|                      size_t count, size_t blksize)
 | |
| {
 | |
|     sdhci_cmd_regs(qts, base_addr, blksize, 1, 0,
 | |
|                    SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
 | |
|                    SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
 | |
| 
 | |
|     /* write to sd fifo_buffer */
 | |
|     write_fifo(qts, base_addr + SDHC_BDATA, msg, count);
 | |
|     fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4);
 | |
| 
 | |
|     sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
 | |
|                    SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
 | |
|                    SDHC_STOP_TRANSMISSION);
 | |
| }
 |