* Mark Nios II as orphan

* Many s390x emulation fixes
 * Disable flaky complete_in_standby blockjob unit test
 * White space cleanups in various files
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmQYVEoRHHRodXRoQHJl
 ZGhhdC5jb20ACgkQLtnXdP5wLbWu/A//QdVG7wS66lhdkPPu/GN+eDNaNsTzPPZd
 YwH0bpy2YoopInwa1ggZ1zPatmbSOVUcKjUfNYLcQzUBQnmeFtpuAF+4IGDhYfa+
 agkjWvmrCrIww4Wn+OLdLReW1+GtRlKZKu7xbYKkeLyqr9SHUD2lNUZ5RXj2t9Lw
 BXkPDXkMFqfVDzHtAxyXL7Z7yk3UTnZKBjDxiwE3tZ4S+N4r7m/TvNHiopI2bTVg
 JeDTxN40ylbOlBfOLC/qhlLUVnyBsDalIfKffIdLZ5Qn+FnKfZhkt9km4i7OL+ZX
 1wKnTh/J8OCYqHOyhJdZGT8QxZH79qDm12/nKXzIQkxtJoKuz6Fm5FY3ZJNrb+IJ
 ybxSpAFBJB/8sUjbzl8ZjGxbZecIyEBKT518+oBoqjNcy3n8/m2BhBFr6f6F4cJC
 kdTnRS0XYKGLbJLz0+VBARE7hoHNckYsup/DGscppyYKNA6rFXbq/MI3+oMGAnPw
 Ua/+gXU/hwq8TPg97A7O0hS4TKSKMtdZFEDmAGzkejVHvm/3BvcYrVoKDljnUAQV
 SaERp/Elefbt3EufkuZp77AwLU8RcEFscitEIACmLbmwm3aKpqS+R2u1EJ4ZcoFT
 dHUBkokXW1/i+FtNRmjEKV9z398cNYXGEDLPfMnFbknHwbS53pqeQqqlvUidltGk
 LWviyiqKihk=
 =tYCc
 -----END PGP SIGNATURE-----

Merge tag 'pull-request-2023-03-20' of https://gitlab.com/thuth/qemu into staging

* Mark Nios II as orphan
* Many s390x emulation fixes
* Disable flaky complete_in_standby blockjob unit test
* White space cleanups in various files

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCAAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmQYVEoRHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbWu/A//QdVG7wS66lhdkPPu/GN+eDNaNsTzPPZd
# YwH0bpy2YoopInwa1ggZ1zPatmbSOVUcKjUfNYLcQzUBQnmeFtpuAF+4IGDhYfa+
# agkjWvmrCrIww4Wn+OLdLReW1+GtRlKZKu7xbYKkeLyqr9SHUD2lNUZ5RXj2t9Lw
# BXkPDXkMFqfVDzHtAxyXL7Z7yk3UTnZKBjDxiwE3tZ4S+N4r7m/TvNHiopI2bTVg
# JeDTxN40ylbOlBfOLC/qhlLUVnyBsDalIfKffIdLZ5Qn+FnKfZhkt9km4i7OL+ZX
# 1wKnTh/J8OCYqHOyhJdZGT8QxZH79qDm12/nKXzIQkxtJoKuz6Fm5FY3ZJNrb+IJ
# ybxSpAFBJB/8sUjbzl8ZjGxbZecIyEBKT518+oBoqjNcy3n8/m2BhBFr6f6F4cJC
# kdTnRS0XYKGLbJLz0+VBARE7hoHNckYsup/DGscppyYKNA6rFXbq/MI3+oMGAnPw
# Ua/+gXU/hwq8TPg97A7O0hS4TKSKMtdZFEDmAGzkejVHvm/3BvcYrVoKDljnUAQV
# SaERp/Elefbt3EufkuZp77AwLU8RcEFscitEIACmLbmwm3aKpqS+R2u1EJ4ZcoFT
# dHUBkokXW1/i+FtNRmjEKV9z398cNYXGEDLPfMnFbknHwbS53pqeQqqlvUidltGk
# LWviyiqKihk=
# =tYCc
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 20 Mar 2023 12:40:42 GMT
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [full]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [full]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3  EAB9 2ED9 D774 FE70 2DB5

* tag 'pull-request-2023-03-20' of https://gitlab.com/thuth/qemu: (24 commits)
  replace TABs with spaces
  qemu/osdep: Switch position of "extern" and "G_NORETURN"
  tests/unit/test-blockjob: Disable complete_in_standby test
  target/s390x/tcg/mem_helper: Remove bad assert() statement
  tests/tcg/s390x: Test unaligned accesses
  target/s390x: Update do_unaligned_access() comment
  target/s390x: Handle STGRL to non-aligned addresses
  target/s390x: Handle STRL to non-aligned addresses
  target/s390x: Handle CLRL and CLGFRL with non-aligned addresses
  target/s390x: Handle CGRL and CLGRL with non-aligned addresses
  target/s390x: Handle CRL and CGFRL with non-aligned addresses
  target/s390x: Handle LLGFRL from non-aligned addresses
  target/s390x: Handle LRL and LGFRL from non-aligned addresses
  target/s390x: Handle LGRL from non-aligned addresses
  target/s390x: Handle EXECUTE of odd addresses
  target/s390x: Handle branching to odd addresses
  tests/tcg/s390x: Add ex-relative-long.c
  target/s390x: Fix EXECUTE of relative long instructions
  tests/tcg/s390x: Add rxsbg.c
  target/s390x: Fix R[NOX]SBG with T=1
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2023-03-20 13:43:14 +00:00
commit 4c6f44644d
65 changed files with 2890 additions and 2078 deletions

View File

@ -257,9 +257,9 @@ F: docs/system/cpu-models-mips.rst.inc
F: tests/tcg/mips/ F: tests/tcg/mips/
NiosII TCG CPUs NiosII TCG CPUs
M: Chris Wulff <crwulff@gmail.com> R: Chris Wulff <crwulff@gmail.com>
M: Marek Vasut <marex@denx.de> R: Marek Vasut <marex@denx.de>
S: Maintained S: Orphan
F: target/nios2/ F: target/nios2/
F: hw/nios2/ F: hw/nios2/
F: disas/nios2.c F: disas/nios2.c

View File

@ -44,39 +44,39 @@
#define ESC 0x1B #define ESC 0x1B
#define BAUM_REQ_DisplayData 0x01 #define BAUM_REQ_DisplayData 0x01
#define BAUM_REQ_GetVersionNumber 0x05 #define BAUM_REQ_GetVersionNumber 0x05
#define BAUM_REQ_GetKeys 0x08 #define BAUM_REQ_GetKeys 0x08
#define BAUM_REQ_SetMode 0x12 #define BAUM_REQ_SetMode 0x12
#define BAUM_REQ_SetProtocol 0x15 #define BAUM_REQ_SetProtocol 0x15
#define BAUM_REQ_GetDeviceIdentity 0x84 #define BAUM_REQ_GetDeviceIdentity 0x84
#define BAUM_REQ_GetSerialNumber 0x8A #define BAUM_REQ_GetSerialNumber 0x8A
#define BAUM_RSP_CellCount 0x01 #define BAUM_RSP_CellCount 0x01
#define BAUM_RSP_VersionNumber 0x05 #define BAUM_RSP_VersionNumber 0x05
#define BAUM_RSP_ModeSetting 0x11 #define BAUM_RSP_ModeSetting 0x11
#define BAUM_RSP_CommunicationChannel 0x16 #define BAUM_RSP_CommunicationChannel 0x16
#define BAUM_RSP_PowerdownSignal 0x17 #define BAUM_RSP_PowerdownSignal 0x17
#define BAUM_RSP_HorizontalSensors 0x20 #define BAUM_RSP_HorizontalSensors 0x20
#define BAUM_RSP_VerticalSensors 0x21 #define BAUM_RSP_VerticalSensors 0x21
#define BAUM_RSP_RoutingKeys 0x22 #define BAUM_RSP_RoutingKeys 0x22
#define BAUM_RSP_Switches 0x23 #define BAUM_RSP_Switches 0x23
#define BAUM_RSP_TopKeys 0x24 #define BAUM_RSP_TopKeys 0x24
#define BAUM_RSP_HorizontalSensor 0x25 #define BAUM_RSP_HorizontalSensor 0x25
#define BAUM_RSP_VerticalSensor 0x26 #define BAUM_RSP_VerticalSensor 0x26
#define BAUM_RSP_RoutingKey 0x27 #define BAUM_RSP_RoutingKey 0x27
#define BAUM_RSP_FrontKeys6 0x28 #define BAUM_RSP_FrontKeys6 0x28
#define BAUM_RSP_BackKeys6 0x29 #define BAUM_RSP_BackKeys6 0x29
#define BAUM_RSP_CommandKeys 0x2B #define BAUM_RSP_CommandKeys 0x2B
#define BAUM_RSP_FrontKeys10 0x2C #define BAUM_RSP_FrontKeys10 0x2C
#define BAUM_RSP_BackKeys10 0x2D #define BAUM_RSP_BackKeys10 0x2D
#define BAUM_RSP_EntryKeys 0x33 #define BAUM_RSP_EntryKeys 0x33
#define BAUM_RSP_JoyStick 0x34 #define BAUM_RSP_JoyStick 0x34
#define BAUM_RSP_ErrorCode 0x40 #define BAUM_RSP_ErrorCode 0x40
#define BAUM_RSP_InfoBlock 0x42 #define BAUM_RSP_InfoBlock 0x42
#define BAUM_RSP_DeviceIdentity 0x84 #define BAUM_RSP_DeviceIdentity 0x84
#define BAUM_RSP_SerialNumber 0x8A #define BAUM_RSP_SerialNumber 0x8A
#define BAUM_RSP_BluetoothName 0x8C #define BAUM_RSP_BluetoothName 0x8C
#define BAUM_TL1 0x01 #define BAUM_TL1 0x01
#define BAUM_TL2 0x02 #define BAUM_TL2 0x02

View File

@ -57,22 +57,22 @@
/* /*
* These are the definitions for the Printer Status Register * These are the definitions for the Printer Status Register
*/ */
#define PARA_STS_BUSY 0x80 /* Busy complement */ #define PARA_STS_BUSY 0x80 /* Busy complement */
#define PARA_STS_ACK 0x40 /* Acknowledge */ #define PARA_STS_ACK 0x40 /* Acknowledge */
#define PARA_STS_PAPER 0x20 /* Out of paper */ #define PARA_STS_PAPER 0x20 /* Out of paper */
#define PARA_STS_ONLINE 0x10 /* Online */ #define PARA_STS_ONLINE 0x10 /* Online */
#define PARA_STS_ERROR 0x08 /* Error complement */ #define PARA_STS_ERROR 0x08 /* Error complement */
#define PARA_STS_TMOUT 0x01 /* EPP timeout */ #define PARA_STS_TMOUT 0x01 /* EPP timeout */
/* /*
* These are the definitions for the Printer Control Register * These are the definitions for the Printer Control Register
*/ */
#define PARA_CTR_DIR 0x20 /* Direction (1=read, 0=write) */ #define PARA_CTR_DIR 0x20 /* Direction (1=read, 0=write) */
#define PARA_CTR_INTEN 0x10 /* IRQ Enable */ #define PARA_CTR_INTEN 0x10 /* IRQ Enable */
#define PARA_CTR_SELECT 0x08 /* Select In complement */ #define PARA_CTR_SELECT 0x08 /* Select In complement */
#define PARA_CTR_INIT 0x04 /* Initialize Printer complement */ #define PARA_CTR_INIT 0x04 /* Initialize Printer complement */
#define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */ #define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */
#define PARA_CTR_STROBE 0x01 /* Strobe complement */ #define PARA_CTR_STROBE 0x01 /* Strobe complement */
#define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE) #define PARA_CTR_SIGNAL (PARA_CTR_SELECT|PARA_CTR_INIT|PARA_CTR_AUTOLF|PARA_CTR_STROBE)

View File

@ -38,20 +38,20 @@
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h" #include "hw/qdev-properties-system.h"
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ #define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ #define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ #define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ #define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ #define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ #define UART_IIR_NO_INT 0x01 /* No interrupts pending */
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ #define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
#define UART_IIR_MSI 0x00 /* Modem status interrupt */ #define UART_IIR_MSI 0x00 /* Modem status interrupt */
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ #define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ #define UART_IIR_RDI 0x04 /* Receiver data interrupt */
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
#define UART_IIR_CTI 0x0C /* Character Timeout Indication */ #define UART_IIR_CTI 0x0C /* Character Timeout Indication */
#define UART_IIR_FENF 0x80 /* Fifo enabled, but not functionning */ #define UART_IIR_FENF 0x80 /* Fifo enabled, but not functionning */
@ -60,33 +60,33 @@
/* /*
* These are the definitions for the Modem Control Register * These are the definitions for the Modem Control Register
*/ */
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ #define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
#define UART_MCR_OUT2 0x08 /* Out2 complement */ #define UART_MCR_OUT2 0x08 /* Out2 complement */
#define UART_MCR_OUT1 0x04 /* Out1 complement */ #define UART_MCR_OUT1 0x04 /* Out1 complement */
#define UART_MCR_RTS 0x02 /* RTS complement */ #define UART_MCR_RTS 0x02 /* RTS complement */
#define UART_MCR_DTR 0x01 /* DTR complement */ #define UART_MCR_DTR 0x01 /* DTR complement */
/* /*
* These are the definitions for the Modem Status Register * These are the definitions for the Modem Status Register
*/ */
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ #define UART_MSR_DCD 0x80 /* Data Carrier Detect */
#define UART_MSR_RI 0x40 /* Ring Indicator */ #define UART_MSR_RI 0x40 /* Ring Indicator */
#define UART_MSR_DSR 0x20 /* Data Set Ready */ #define UART_MSR_DSR 0x20 /* Data Set Ready */
#define UART_MSR_CTS 0x10 /* Clear to Send */ #define UART_MSR_CTS 0x10 /* Clear to Send */
#define UART_MSR_DDCD 0x08 /* Delta DCD */ #define UART_MSR_DDCD 0x08 /* Delta DCD */
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ #define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
#define UART_MSR_DDSR 0x02 /* Delta DSR */ #define UART_MSR_DDSR 0x02 /* Delta DSR */
#define UART_MSR_DCTS 0x01 /* Delta CTS */ #define UART_MSR_DCTS 0x01 /* Delta CTS */
#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ #define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
#define UART_LSR_TEMT 0x40 /* Transmitter empty */ #define UART_LSR_TEMT 0x40 /* Transmitter empty */
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define UART_LSR_BI 0x10 /* Break interrupt indicator */ #define UART_LSR_BI 0x10 /* Break interrupt indicator */
#define UART_LSR_FE 0x08 /* Frame error indicator */ #define UART_LSR_FE 0x08 /* Frame error indicator */
#define UART_LSR_PE 0x04 /* Parity error indicator */ #define UART_LSR_PE 0x04 /* Parity error indicator */
#define UART_LSR_OE 0x02 /* Overrun error indicator */ #define UART_LSR_OE 0x02 /* Overrun error indicator */
#define UART_LSR_DR 0x01 /* Receiver data ready */ #define UART_LSR_DR 0x01 /* Receiver data ready */
#define UART_LSR_INT_ANY 0x1E /* Any of the lsr-interrupt-triggering status bits */ #define UART_LSR_INT_ANY 0x1E /* Any of the lsr-interrupt-triggering status bits */
/* Interrupt trigger levels. The byte-counts are for 16550A - in newer UARTs the byte-count for each ITL is higher. */ /* Interrupt trigger levels. The byte-counts are for 16550A - in newer UARTs the byte-count for each ITL is higher. */

View File

@ -35,7 +35,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
@ -210,8 +210,8 @@ static void bswap_ahdr(struct exec *e)
#define ZMAGIC 0413 #define ZMAGIC 0413
#define QMAGIC 0314 #define QMAGIC 0314
#define _N_HDROFF(x) (1024 - sizeof (struct exec)) #define _N_HDROFF(x) (1024 - sizeof (struct exec))
#define N_TXTOFF(x) \ #define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
(N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec))) (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
#define N_TXTADDR(x, target_page_size) (N_MAGIC(x) == QMAGIC ? target_page_size : 0) #define N_TXTADDR(x, target_page_size) (N_MAGIC(x) == QMAGIC ? target_page_size : 0)
#define _N_SEGMENT_ROUND(x, target_page_size) (((x) + target_page_size - 1) & ~(target_page_size - 1)) #define _N_SEGMENT_ROUND(x, target_page_size) (((x) + target_page_size - 1) & ~(target_page_size - 1))
@ -300,10 +300,10 @@ static void *load_at(int fd, off_t offset, size_t size)
#define ELF_CLASS ELFCLASS32 #define ELF_CLASS ELFCLASS32
#include "elf.h" #include "elf.h"
#define SZ 32 #define SZ 32
#define elf_word uint32_t #define elf_word uint32_t
#define elf_sword int32_t #define elf_sword int32_t
#define bswapSZs bswap32s #define bswapSZs bswap32s
#include "hw/elf_ops.h" #include "hw/elf_ops.h"
#undef elfhdr #undef elfhdr
@ -316,16 +316,16 @@ static void *load_at(int fd, off_t offset, size_t size)
#undef elf_sword #undef elf_sword
#undef bswapSZs #undef bswapSZs
#undef SZ #undef SZ
#define elfhdr elf64_hdr #define elfhdr elf64_hdr
#define elf_phdr elf64_phdr #define elf_phdr elf64_phdr
#define elf_note elf64_note #define elf_note elf64_note
#define elf_shdr elf64_shdr #define elf_shdr elf64_shdr
#define elf_sym elf64_sym #define elf_sym elf64_sym
#define elf_rela elf64_rela #define elf_rela elf64_rela
#define elf_word uint64_t #define elf_word uint64_t
#define elf_sword int64_t #define elf_sword int64_t
#define bswapSZs bswap64s #define bswapSZs bswap64s
#define SZ 64 #define SZ 64
#include "hw/elf_ops.h" #include "hw/elf_ops.h"
const char *load_elf_strerror(ssize_t error) const char *load_elf_strerror(ssize_t error)
@ -527,7 +527,7 @@ static void bswap_uboot_header(uboot_image_header_t *hdr)
} }
#define ZALLOC_ALIGNMENT 16 #define ZALLOC_ALIGNMENT 16
static void *zalloc(void *x, unsigned items, unsigned size) static void *zalloc(void *x, unsigned items, unsigned size)
{ {
@ -547,13 +547,13 @@ static void zfree(void *x, void *addr)
} }
#define HEAD_CRC 2 #define HEAD_CRC 2
#define EXTRA_FIELD 4 #define EXTRA_FIELD 4
#define ORIG_NAME 8 #define ORIG_NAME 8
#define COMMENT 0x10 #define COMMENT 0x10
#define RESERVED 0xe0 #define RESERVED 0xe0
#define DEFLATED 8 #define DEFLATED 8
ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen) ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src, size_t srclen)
{ {

View File

@ -160,38 +160,38 @@ enum {
enum dma_ch_state enum dma_ch_state
{ {
RST = 1, RST = 1,
STOPPED = 2, STOPPED = 2,
RUNNING = 4 RUNNING = 4
}; };
struct fs_dma_channel struct fs_dma_channel
{ {
qemu_irq irq; qemu_irq irq;
struct etraxfs_dma_client *client; struct etraxfs_dma_client *client;
/* Internal status. */ /* Internal status. */
int stream_cmd_src; int stream_cmd_src;
enum dma_ch_state state; enum dma_ch_state state;
unsigned int input : 1; unsigned int input : 1;
unsigned int eol : 1; unsigned int eol : 1;
struct dma_descr_group current_g; struct dma_descr_group current_g;
struct dma_descr_context current_c; struct dma_descr_context current_c;
struct dma_descr_data current_d; struct dma_descr_data current_d;
/* Control registers. */ /* Control registers. */
uint32_t regs[DMA_REG_MAX]; uint32_t regs[DMA_REG_MAX];
}; };
struct fs_dma_ctrl struct fs_dma_ctrl
{ {
MemoryRegion mmio; MemoryRegion mmio;
int nr_channels; int nr_channels;
struct fs_dma_channel *channels; struct fs_dma_channel *channels;
QEMUBH *bh; QEMUBH *bh;
}; };
static void DMA_run(void *opaque); static void DMA_run(void *opaque);
@ -199,72 +199,72 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c);
static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg) static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg)
{ {
return ctrl->channels[c].regs[reg]; return ctrl->channels[c].regs[reg];
} }
static inline int channel_stopped(struct fs_dma_ctrl *ctrl, int c) static inline int channel_stopped(struct fs_dma_ctrl *ctrl, int c)
{ {
return channel_reg(ctrl, c, RW_CFG) & 2; return channel_reg(ctrl, c, RW_CFG) & 2;
} }
static inline int channel_en(struct fs_dma_ctrl *ctrl, int c) static inline int channel_en(struct fs_dma_ctrl *ctrl, int c)
{ {
return (channel_reg(ctrl, c, RW_CFG) & 1) return (channel_reg(ctrl, c, RW_CFG) & 1)
&& ctrl->channels[c].client; && ctrl->channels[c].client;
} }
static inline int fs_channel(hwaddr addr) static inline int fs_channel(hwaddr addr)
{ {
/* Every channel has a 0x2000 ctrl register map. */ /* Every channel has a 0x2000 ctrl register map. */
return addr >> 13; return addr >> 13;
} }
#ifdef USE_THIS_DEAD_CODE #ifdef USE_THIS_DEAD_CODE
static void channel_load_g(struct fs_dma_ctrl *ctrl, int c) static void channel_load_g(struct fs_dma_ctrl *ctrl, int c)
{ {
hwaddr addr = channel_reg(ctrl, c, RW_GROUP); hwaddr addr = channel_reg(ctrl, c, RW_GROUP);
/* Load and decode. FIXME: handle endianness. */ /* Load and decode. FIXME: handle endianness. */
cpu_physical_memory_read(addr, &ctrl->channels[c].current_g, cpu_physical_memory_read(addr, &ctrl->channels[c].current_g,
sizeof(ctrl->channels[c].current_g)); sizeof(ctrl->channels[c].current_g));
} }
static void dump_c(int ch, struct dma_descr_context *c) static void dump_c(int ch, struct dma_descr_context *c)
{ {
printf("%s ch=%d\n", __func__, ch); printf("%s ch=%d\n", __func__, ch);
printf("next=%x\n", c->next); printf("next=%x\n", c->next);
printf("saved_data=%x\n", c->saved_data); printf("saved_data=%x\n", c->saved_data);
printf("saved_data_buf=%x\n", c->saved_data_buf); printf("saved_data_buf=%x\n", c->saved_data_buf);
printf("eol=%x\n", (uint32_t) c->eol); printf("eol=%x\n", (uint32_t) c->eol);
} }
static void dump_d(int ch, struct dma_descr_data *d) static void dump_d(int ch, struct dma_descr_data *d)
{ {
printf("%s ch=%d\n", __func__, ch); printf("%s ch=%d\n", __func__, ch);
printf("next=%x\n", d->next); printf("next=%x\n", d->next);
printf("buf=%x\n", d->buf); printf("buf=%x\n", d->buf);
printf("after=%x\n", d->after); printf("after=%x\n", d->after);
printf("intr=%x\n", (uint32_t) d->intr); printf("intr=%x\n", (uint32_t) d->intr);
printf("out_eop=%x\n", (uint32_t) d->out_eop); printf("out_eop=%x\n", (uint32_t) d->out_eop);
printf("in_eop=%x\n", (uint32_t) d->in_eop); printf("in_eop=%x\n", (uint32_t) d->in_eop);
printf("eol=%x\n", (uint32_t) d->eol); printf("eol=%x\n", (uint32_t) d->eol);
} }
#endif #endif
static void channel_load_c(struct fs_dma_ctrl *ctrl, int c) static void channel_load_c(struct fs_dma_ctrl *ctrl, int c)
{ {
hwaddr addr = channel_reg(ctrl, c, RW_GROUP_DOWN); hwaddr addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
/* Load and decode. FIXME: handle endianness. */ /* Load and decode. FIXME: handle endianness. */
cpu_physical_memory_read(addr, &ctrl->channels[c].current_c, cpu_physical_memory_read(addr, &ctrl->channels[c].current_c,
sizeof(ctrl->channels[c].current_c)); sizeof(ctrl->channels[c].current_c));
D(dump_c(c, &ctrl->channels[c].current_c)); D(dump_c(c, &ctrl->channels[c].current_c));
/* I guess this should update the current pos. */ /* I guess this should update the current pos. */
ctrl->channels[c].regs[RW_SAVED_DATA] = ctrl->channels[c].regs[RW_SAVED_DATA] =
(uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data; (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data;
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
(uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data_buf; (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data_buf;
} }
static void channel_load_d(struct fs_dma_ctrl *ctrl, int c) static void channel_load_d(struct fs_dma_ctrl *ctrl, int c)
@ -303,273 +303,273 @@ static void channel_store_d(struct fs_dma_ctrl *ctrl, int c)
static inline void channel_stop(struct fs_dma_ctrl *ctrl, int c) static inline void channel_stop(struct fs_dma_ctrl *ctrl, int c)
{ {
/* FIXME: */ /* FIXME: */
} }
static inline void channel_start(struct fs_dma_ctrl *ctrl, int c) static inline void channel_start(struct fs_dma_ctrl *ctrl, int c)
{ {
if (ctrl->channels[c].client) if (ctrl->channels[c].client)
{ {
ctrl->channels[c].eol = 0; ctrl->channels[c].eol = 0;
ctrl->channels[c].state = RUNNING; ctrl->channels[c].state = RUNNING;
if (!ctrl->channels[c].input) if (!ctrl->channels[c].input)
channel_out_run(ctrl, c); channel_out_run(ctrl, c);
} else } else
printf("WARNING: starting DMA ch %d with no client\n", c); printf("WARNING: starting DMA ch %d with no client\n", c);
qemu_bh_schedule_idle(ctrl->bh); qemu_bh_schedule_idle(ctrl->bh);
} }
static void channel_continue(struct fs_dma_ctrl *ctrl, int c) static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
{ {
if (!channel_en(ctrl, c) if (!channel_en(ctrl, c)
|| channel_stopped(ctrl, c) || channel_stopped(ctrl, c)
|| ctrl->channels[c].state != RUNNING || ctrl->channels[c].state != RUNNING
/* Only reload the current data descriptor if it has eol set. */ /* Only reload the current data descriptor if it has eol set. */
|| !ctrl->channels[c].current_d.eol) { || !ctrl->channels[c].current_d.eol) {
D(printf("continue failed ch=%d state=%d stopped=%d en=%d eol=%d\n", D(printf("continue failed ch=%d state=%d stopped=%d en=%d eol=%d\n",
c, ctrl->channels[c].state, c, ctrl->channels[c].state,
channel_stopped(ctrl, c), channel_stopped(ctrl, c),
channel_en(ctrl,c), channel_en(ctrl,c),
ctrl->channels[c].eol)); ctrl->channels[c].eol));
D(dump_d(c, &ctrl->channels[c].current_d)); D(dump_d(c, &ctrl->channels[c].current_d));
return; return;
} }
/* Reload the current descriptor. */ /* Reload the current descriptor. */
channel_load_d(ctrl, c); channel_load_d(ctrl, c);
/* If the current descriptor cleared the eol flag and we had already /* If the current descriptor cleared the eol flag and we had already
reached eol state, do the continue. */ reached eol state, do the continue. */
if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) { if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) {
D(printf("continue %d ok %x\n", c, D(printf("continue %d ok %x\n", c,
ctrl->channels[c].current_d.next)); ctrl->channels[c].current_d.next));
ctrl->channels[c].regs[RW_SAVED_DATA] = ctrl->channels[c].regs[RW_SAVED_DATA] =
(uint32_t)(unsigned long)ctrl->channels[c].current_d.next; (uint32_t)(unsigned long)ctrl->channels[c].current_d.next;
channel_load_d(ctrl, c); channel_load_d(ctrl, c);
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
(uint32_t)(unsigned long)ctrl->channels[c].current_d.buf; (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
channel_start(ctrl, c); channel_start(ctrl, c);
} }
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
(uint32_t)(unsigned long)ctrl->channels[c].current_d.buf; (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
} }
static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
{ {
unsigned int cmd = v & ((1 << 10) - 1); unsigned int cmd = v & ((1 << 10) - 1);
D(printf("%s ch=%d cmd=%x\n", D(printf("%s ch=%d cmd=%x\n",
__func__, c, cmd)); __func__, c, cmd));
if (cmd & regk_dma_load_d) { if (cmd & regk_dma_load_d) {
channel_load_d(ctrl, c); channel_load_d(ctrl, c);
if (cmd & regk_dma_burst) if (cmd & regk_dma_burst)
channel_start(ctrl, c); channel_start(ctrl, c);
} }
if (cmd & regk_dma_load_c) { if (cmd & regk_dma_load_c) {
channel_load_c(ctrl, c); channel_load_c(ctrl, c);
} }
} }
static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c) static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c)
{ {
D(printf("%s %d\n", __func__, c)); D(printf("%s %d\n", __func__, c));
ctrl->channels[c].regs[R_INTR] &= ctrl->channels[c].regs[R_INTR] &=
~(ctrl->channels[c].regs[RW_ACK_INTR]); ~(ctrl->channels[c].regs[RW_ACK_INTR]);
ctrl->channels[c].regs[R_MASKED_INTR] = ctrl->channels[c].regs[R_MASKED_INTR] =
ctrl->channels[c].regs[R_INTR] ctrl->channels[c].regs[R_INTR]
& ctrl->channels[c].regs[RW_INTR_MASK]; & ctrl->channels[c].regs[RW_INTR_MASK];
D(printf("%s: chan=%d masked_intr=%x\n", __func__, D(printf("%s: chan=%d masked_intr=%x\n", __func__,
c, c,
ctrl->channels[c].regs[R_MASKED_INTR])); ctrl->channels[c].regs[R_MASKED_INTR]));
qemu_set_irq(ctrl->channels[c].irq, qemu_set_irq(ctrl->channels[c].irq,
!!ctrl->channels[c].regs[R_MASKED_INTR]); !!ctrl->channels[c].regs[R_MASKED_INTR]);
} }
static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
{ {
uint32_t len; uint32_t len;
uint32_t saved_data_buf; uint32_t saved_data_buf;
unsigned char buf[2 * 1024]; unsigned char buf[2 * 1024];
struct dma_context_metadata meta; struct dma_context_metadata meta;
bool send_context = true; bool send_context = true;
if (ctrl->channels[c].eol) if (ctrl->channels[c].eol)
return 0; return 0;
do { do {
bool out_eop; bool out_eop;
D(printf("ch=%d buf=%x after=%x\n", D(printf("ch=%d buf=%x after=%x\n",
c, c,
(uint32_t)ctrl->channels[c].current_d.buf, (uint32_t)ctrl->channels[c].current_d.buf,
(uint32_t)ctrl->channels[c].current_d.after)); (uint32_t)ctrl->channels[c].current_d.after));
if (send_context) { if (send_context) {
if (ctrl->channels[c].client->client.metadata_push) { if (ctrl->channels[c].client->client.metadata_push) {
meta.metadata = ctrl->channels[c].current_d.md; meta.metadata = ctrl->channels[c].current_d.md;
ctrl->channels[c].client->client.metadata_push( ctrl->channels[c].client->client.metadata_push(
ctrl->channels[c].client->client.opaque, ctrl->channels[c].client->client.opaque,
&meta); &meta);
} }
send_context = false; send_context = false;
} }
channel_load_d(ctrl, c); channel_load_d(ctrl, c);
saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
len = (uint32_t)(unsigned long) len = (uint32_t)(unsigned long)
ctrl->channels[c].current_d.after; ctrl->channels[c].current_d.after;
len -= saved_data_buf; len -= saved_data_buf;
if (len > sizeof buf) if (len > sizeof buf)
len = sizeof buf; len = sizeof buf;
cpu_physical_memory_read (saved_data_buf, buf, len); cpu_physical_memory_read (saved_data_buf, buf, len);
out_eop = ((saved_data_buf + len) == out_eop = ((saved_data_buf + len) ==
ctrl->channels[c].current_d.after) && ctrl->channels[c].current_d.after) &&
ctrl->channels[c].current_d.out_eop; ctrl->channels[c].current_d.out_eop;
D(printf("channel %d pushes %x %u bytes eop=%u\n", c, D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
saved_data_buf, len, out_eop)); saved_data_buf, len, out_eop));
if (ctrl->channels[c].client->client.push) { if (ctrl->channels[c].client->client.push) {
if (len > 0) { if (len > 0) {
ctrl->channels[c].client->client.push( ctrl->channels[c].client->client.push(
ctrl->channels[c].client->client.opaque, ctrl->channels[c].client->client.opaque,
buf, len, out_eop); buf, len, out_eop);
} }
} else { } else {
printf("WARNING: DMA ch%d dataloss," printf("WARNING: DMA ch%d dataloss,"
" no attached client.\n", c); " no attached client.\n", c);
} }
saved_data_buf += len; saved_data_buf += len;
if (saved_data_buf == (uint32_t)(unsigned long) if (saved_data_buf == (uint32_t)(unsigned long)
ctrl->channels[c].current_d.after) { ctrl->channels[c].current_d.after) {
/* Done. Step to next. */ /* Done. Step to next. */
if (ctrl->channels[c].current_d.out_eop) { if (ctrl->channels[c].current_d.out_eop) {
send_context = true; send_context = true;
} }
if (ctrl->channels[c].current_d.intr) { if (ctrl->channels[c].current_d.intr) {
/* data intr. */ /* data intr. */
D(printf("signal intr %d eol=%d\n", D(printf("signal intr %d eol=%d\n",
len, ctrl->channels[c].current_d.eol)); len, ctrl->channels[c].current_d.eol));
ctrl->channels[c].regs[R_INTR] |= (1 << 2); ctrl->channels[c].regs[R_INTR] |= (1 << 2);
channel_update_irq(ctrl, c); channel_update_irq(ctrl, c);
} }
channel_store_d(ctrl, c); channel_store_d(ctrl, c);
if (ctrl->channels[c].current_d.eol) { if (ctrl->channels[c].current_d.eol) {
D(printf("channel %d EOL\n", c)); D(printf("channel %d EOL\n", c));
ctrl->channels[c].eol = 1; ctrl->channels[c].eol = 1;
/* Mark the context as disabled. */ /* Mark the context as disabled. */
ctrl->channels[c].current_c.dis = 1; ctrl->channels[c].current_c.dis = 1;
channel_store_c(ctrl, c); channel_store_c(ctrl, c);
channel_stop(ctrl, c); channel_stop(ctrl, c);
} else { } else {
ctrl->channels[c].regs[RW_SAVED_DATA] = ctrl->channels[c].regs[RW_SAVED_DATA] =
(uint32_t)(unsigned long)ctrl-> (uint32_t)(unsigned long)ctrl->
channels[c].current_d.next; channels[c].current_d.next;
/* Load new descriptor. */ /* Load new descriptor. */
channel_load_d(ctrl, c); channel_load_d(ctrl, c);
saved_data_buf = (uint32_t)(unsigned long) saved_data_buf = (uint32_t)(unsigned long)
ctrl->channels[c].current_d.buf; ctrl->channels[c].current_d.buf;
} }
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
saved_data_buf; saved_data_buf;
D(dump_d(c, &ctrl->channels[c].current_d)); D(dump_d(c, &ctrl->channels[c].current_d));
} }
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf; ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
} while (!ctrl->channels[c].eol); } while (!ctrl->channels[c].eol);
return 1; return 1;
} }
static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, static int channel_in_process(struct fs_dma_ctrl *ctrl, int c,
unsigned char *buf, int buflen, int eop) unsigned char *buf, int buflen, int eop)
{ {
uint32_t len; uint32_t len;
uint32_t saved_data_buf; uint32_t saved_data_buf;
if (ctrl->channels[c].eol == 1) if (ctrl->channels[c].eol == 1)
return 0; return 0;
channel_load_d(ctrl, c); channel_load_d(ctrl, c);
saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after; len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after;
len -= saved_data_buf; len -= saved_data_buf;
if (len > buflen)
len = buflen;
cpu_physical_memory_write (saved_data_buf, buf, len); if (len > buflen)
saved_data_buf += len; len = buflen;
if (saved_data_buf == cpu_physical_memory_write (saved_data_buf, buf, len);
(uint32_t)(unsigned long)ctrl->channels[c].current_d.after saved_data_buf += len;
|| eop) {
uint32_t r_intr = ctrl->channels[c].regs[R_INTR];
D(printf("in dscr end len=%d\n", if (saved_data_buf ==
ctrl->channels[c].current_d.after (uint32_t)(unsigned long)ctrl->channels[c].current_d.after
- ctrl->channels[c].current_d.buf)); || eop) {
ctrl->channels[c].current_d.after = saved_data_buf; uint32_t r_intr = ctrl->channels[c].regs[R_INTR];
/* Done. Step to next. */ D(printf("in dscr end len=%d\n",
if (ctrl->channels[c].current_d.intr) { ctrl->channels[c].current_d.after
/* TODO: signal eop to the client. */ - ctrl->channels[c].current_d.buf));
/* data intr. */ ctrl->channels[c].current_d.after = saved_data_buf;
ctrl->channels[c].regs[R_INTR] |= 3;
}
if (eop) {
ctrl->channels[c].current_d.in_eop = 1;
ctrl->channels[c].regs[R_INTR] |= 8;
}
if (r_intr != ctrl->channels[c].regs[R_INTR])
channel_update_irq(ctrl, c);
channel_store_d(ctrl, c); /* Done. Step to next. */
D(dump_d(c, &ctrl->channels[c].current_d)); if (ctrl->channels[c].current_d.intr) {
/* TODO: signal eop to the client. */
/* data intr. */
ctrl->channels[c].regs[R_INTR] |= 3;
}
if (eop) {
ctrl->channels[c].current_d.in_eop = 1;
ctrl->channels[c].regs[R_INTR] |= 8;
}
if (r_intr != ctrl->channels[c].regs[R_INTR])
channel_update_irq(ctrl, c);
if (ctrl->channels[c].current_d.eol) { channel_store_d(ctrl, c);
D(printf("channel %d EOL\n", c)); D(dump_d(c, &ctrl->channels[c].current_d));
ctrl->channels[c].eol = 1;
/* Mark the context as disabled. */ if (ctrl->channels[c].current_d.eol) {
ctrl->channels[c].current_c.dis = 1; D(printf("channel %d EOL\n", c));
channel_store_c(ctrl, c); ctrl->channels[c].eol = 1;
channel_stop(ctrl, c); /* Mark the context as disabled. */
} else { ctrl->channels[c].current_c.dis = 1;
ctrl->channels[c].regs[RW_SAVED_DATA] = channel_store_c(ctrl, c);
(uint32_t)(unsigned long)ctrl->
channels[c].current_d.next;
/* Load new descriptor. */
channel_load_d(ctrl, c);
saved_data_buf = (uint32_t)(unsigned long)
ctrl->channels[c].current_d.buf;
}
}
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf; channel_stop(ctrl, c);
return len; } else {
ctrl->channels[c].regs[RW_SAVED_DATA] =
(uint32_t)(unsigned long)ctrl->
channels[c].current_d.next;
/* Load new descriptor. */
channel_load_d(ctrl, c);
saved_data_buf = (uint32_t)(unsigned long)
ctrl->channels[c].current_d.buf;
}
}
ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
return len;
} }
static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c) static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c)
{ {
if (ctrl->channels[c].client->client.pull) { if (ctrl->channels[c].client->client.pull) {
ctrl->channels[c].client->client.pull( ctrl->channels[c].client->client.pull(
ctrl->channels[c].client->client.opaque); ctrl->channels[c].client->client.opaque);
return 1; return 1;
} else } else
return 0; return 0;
} }
static uint32_t dma_rinvalid (void *opaque, hwaddr addr) static uint32_t dma_rinvalid (void *opaque, hwaddr addr)
@ -581,33 +581,33 @@ static uint32_t dma_rinvalid (void *opaque, hwaddr addr)
static uint64_t static uint64_t
dma_read(void *opaque, hwaddr addr, unsigned int size) dma_read(void *opaque, hwaddr addr, unsigned int size)
{ {
struct fs_dma_ctrl *ctrl = opaque; struct fs_dma_ctrl *ctrl = opaque;
int c; int c;
uint32_t r = 0; uint32_t r = 0;
if (size != 4) { if (size != 4) {
dma_rinvalid(opaque, addr); dma_rinvalid(opaque, addr);
} }
/* Make addr relative to this channel and bounded to nr regs. */ /* Make addr relative to this channel and bounded to nr regs. */
c = fs_channel(addr); c = fs_channel(addr);
addr &= 0xff; addr &= 0xff;
addr >>= 2; addr >>= 2;
switch (addr) switch (addr)
{ {
case RW_STAT: case RW_STAT:
r = ctrl->channels[c].state & 7; r = ctrl->channels[c].state & 7;
r |= ctrl->channels[c].eol << 5; r |= ctrl->channels[c].eol << 5;
r |= ctrl->channels[c].stream_cmd_src << 8; r |= ctrl->channels[c].stream_cmd_src << 8;
break; break;
default: default:
r = ctrl->channels[c].regs[addr]; r = ctrl->channels[c].regs[addr];
D(printf("%s c=%d addr=" HWADDR_FMT_plx "\n", D(printf("%s c=%d addr=" HWADDR_FMT_plx "\n",
__func__, c, addr)); __func__, c, addr));
break; break;
} }
return r; return r;
} }
static void static void
@ -619,133 +619,133 @@ dma_winvalid (void *opaque, hwaddr addr, uint32_t value)
static void static void
dma_update_state(struct fs_dma_ctrl *ctrl, int c) dma_update_state(struct fs_dma_ctrl *ctrl, int c)
{ {
if (ctrl->channels[c].regs[RW_CFG] & 2) if (ctrl->channels[c].regs[RW_CFG] & 2)
ctrl->channels[c].state = STOPPED; ctrl->channels[c].state = STOPPED;
if (!(ctrl->channels[c].regs[RW_CFG] & 1)) if (!(ctrl->channels[c].regs[RW_CFG] & 1))
ctrl->channels[c].state = RST; ctrl->channels[c].state = RST;
} }
static void static void
dma_write(void *opaque, hwaddr addr, dma_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size) uint64_t val64, unsigned int size)
{ {
struct fs_dma_ctrl *ctrl = opaque; struct fs_dma_ctrl *ctrl = opaque;
uint32_t value = val64; uint32_t value = val64;
int c; int c;
if (size != 4) { if (size != 4) {
dma_winvalid(opaque, addr, value); dma_winvalid(opaque, addr, value);
} }
/* Make addr relative to this channel and bounded to nr regs. */ /* Make addr relative to this channel and bounded to nr regs. */
c = fs_channel(addr); c = fs_channel(addr);
addr &= 0xff; addr &= 0xff;
addr >>= 2; addr >>= 2;
switch (addr) switch (addr)
{ {
case RW_DATA: case RW_DATA:
ctrl->channels[c].regs[addr] = value; ctrl->channels[c].regs[addr] = value;
break; break;
case RW_CFG: case RW_CFG:
ctrl->channels[c].regs[addr] = value; ctrl->channels[c].regs[addr] = value;
dma_update_state(ctrl, c); dma_update_state(ctrl, c);
break; break;
case RW_CMD: case RW_CMD:
/* continue. */ /* continue. */
if (value & ~1) if (value & ~1)
printf("Invalid store to ch=%d RW_CMD %x\n", printf("Invalid store to ch=%d RW_CMD %x\n",
c, value); c, value);
ctrl->channels[c].regs[addr] = value; ctrl->channels[c].regs[addr] = value;
channel_continue(ctrl, c); channel_continue(ctrl, c);
break; break;
case RW_SAVED_DATA: case RW_SAVED_DATA:
case RW_SAVED_DATA_BUF: case RW_SAVED_DATA_BUF:
case RW_GROUP: case RW_GROUP:
case RW_GROUP_DOWN: case RW_GROUP_DOWN:
ctrl->channels[c].regs[addr] = value; ctrl->channels[c].regs[addr] = value;
break; break;
case RW_ACK_INTR: case RW_ACK_INTR:
case RW_INTR_MASK: case RW_INTR_MASK:
ctrl->channels[c].regs[addr] = value; ctrl->channels[c].regs[addr] = value;
channel_update_irq(ctrl, c); channel_update_irq(ctrl, c);
if (addr == RW_ACK_INTR) if (addr == RW_ACK_INTR)
ctrl->channels[c].regs[RW_ACK_INTR] = 0; ctrl->channels[c].regs[RW_ACK_INTR] = 0;
break; break;
case RW_STREAM_CMD: case RW_STREAM_CMD:
if (value & ~1023) if (value & ~1023)
printf("Invalid store to ch=%d " printf("Invalid store to ch=%d "
"RW_STREAMCMD %x\n", "RW_STREAMCMD %x\n",
c, value); c, value);
ctrl->channels[c].regs[addr] = value; ctrl->channels[c].regs[addr] = value;
D(printf("stream_cmd ch=%d\n", c)); D(printf("stream_cmd ch=%d\n", c));
channel_stream_cmd(ctrl, c, value); channel_stream_cmd(ctrl, c, value);
break; break;
default: default:
D(printf("%s c=%d " HWADDR_FMT_plx "\n", D(printf("%s c=%d " HWADDR_FMT_plx "\n",
__func__, c, addr)); __func__, c, addr));
break; break;
} }
} }
static const MemoryRegionOps dma_ops = { static const MemoryRegionOps dma_ops = {
.read = dma_read, .read = dma_read,
.write = dma_write, .write = dma_write,
.endianness = DEVICE_NATIVE_ENDIAN, .endianness = DEVICE_NATIVE_ENDIAN,
.valid = { .valid = {
.min_access_size = 1, .min_access_size = 1,
.max_access_size = 4 .max_access_size = 4
} }
}; };
static int etraxfs_dmac_run(void *opaque) static int etraxfs_dmac_run(void *opaque)
{ {
struct fs_dma_ctrl *ctrl = opaque; struct fs_dma_ctrl *ctrl = opaque;
int i; int i;
int p = 0; int p = 0;
for (i = 0; for (i = 0;
i < ctrl->nr_channels; i < ctrl->nr_channels;
i++) i++)
{ {
if (ctrl->channels[i].state == RUNNING) if (ctrl->channels[i].state == RUNNING)
{ {
if (ctrl->channels[i].input) { if (ctrl->channels[i].input) {
p += channel_in_run(ctrl, i); p += channel_in_run(ctrl, i);
} else { } else {
p += channel_out_run(ctrl, i); p += channel_out_run(ctrl, i);
} }
} }
} }
return p; return p;
} }
int etraxfs_dmac_input(struct etraxfs_dma_client *client, int etraxfs_dmac_input(struct etraxfs_dma_client *client,
void *buf, int len, int eop) void *buf, int len, int eop)
{ {
return channel_in_process(client->ctrl, client->channel, return channel_in_process(client->ctrl, client->channel,
buf, len, eop); buf, len, eop);
} }
/* Connect an IRQ line with a channel. */ /* Connect an IRQ line with a channel. */
void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input) void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input)
{ {
struct fs_dma_ctrl *ctrl = opaque; struct fs_dma_ctrl *ctrl = opaque;
ctrl->channels[c].irq = *line; ctrl->channels[c].irq = *line;
ctrl->channels[c].input = input; ctrl->channels[c].input = input;
} }
void etraxfs_dmac_connect_client(void *opaque, int c, void etraxfs_dmac_connect_client(void *opaque, int c,
struct etraxfs_dma_client *cl) struct etraxfs_dma_client *cl)
{ {
struct fs_dma_ctrl *ctrl = opaque; struct fs_dma_ctrl *ctrl = opaque;
cl->ctrl = ctrl; cl->ctrl = ctrl;
cl->channel = c; cl->channel = c;
ctrl->channels[c].client = cl; ctrl->channels[c].client = cl;
} }
@ -763,18 +763,18 @@ static void DMA_run(void *opaque)
void *etraxfs_dmac_init(hwaddr base, int nr_channels) void *etraxfs_dmac_init(hwaddr base, int nr_channels)
{ {
struct fs_dma_ctrl *ctrl = NULL; struct fs_dma_ctrl *ctrl = NULL;
ctrl = g_malloc0(sizeof *ctrl); ctrl = g_malloc0(sizeof *ctrl);
ctrl->bh = qemu_bh_new(DMA_run, ctrl); ctrl->bh = qemu_bh_new(DMA_run, ctrl);
ctrl->nr_channels = nr_channels; ctrl->nr_channels = nr_channels;
ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels); ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
memory_region_init_io(&ctrl->mmio, NULL, &dma_ops, ctrl, "etraxfs-dma", memory_region_init_io(&ctrl->mmio, NULL, &dma_ops, ctrl, "etraxfs-dma",
nr_channels * 0x2000); nr_channels * 0x2000);
memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio); memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
return ctrl; return ctrl;
} }

View File

@ -49,22 +49,22 @@ static uint8_t max7310_rx(I2CSlave *i2c)
MAX7310State *s = MAX7310(i2c); MAX7310State *s = MAX7310(i2c);
switch (s->command) { switch (s->command) {
case 0x00: /* Input port */ case 0x00: /* Input port */
return s->level ^ s->polarity; return s->level ^ s->polarity;
case 0x01: /* Output port */ case 0x01: /* Output port */
return s->level & ~s->direction; return s->level & ~s->direction;
case 0x02: /* Polarity inversion */ case 0x02: /* Polarity inversion */
return s->polarity; return s->polarity;
case 0x03: /* Configuration */ case 0x03: /* Configuration */
return s->direction; return s->direction;
case 0x04: /* Timeout */ case 0x04: /* Timeout */
return s->status; return s->status;
case 0xff: /* Reserved */ case 0xff: /* Reserved */
return 0xff; return 0xff;
default: default:
@ -95,7 +95,7 @@ static int max7310_tx(I2CSlave *i2c, uint8_t data)
} }
switch (s->command) { switch (s->command) {
case 0x01: /* Output port */ case 0x01: /* Output port */
for (diff = (data ^ s->level) & ~s->direction; diff; for (diff = (data ^ s->level) & ~s->direction; diff;
diff &= ~(1 << line)) { diff &= ~(1 << line)) {
line = ctz32(diff); line = ctz32(diff);
@ -105,20 +105,20 @@ static int max7310_tx(I2CSlave *i2c, uint8_t data)
s->level = (s->level & s->direction) | (data & ~s->direction); s->level = (s->level & s->direction) | (data & ~s->direction);
break; break;
case 0x02: /* Polarity inversion */ case 0x02: /* Polarity inversion */
s->polarity = data; s->polarity = data;
break; break;
case 0x03: /* Configuration */ case 0x03: /* Configuration */
s->level &= ~(s->direction ^ data); s->level &= ~(s->direction ^ data);
s->direction = data; s->direction = data;
break; break;
case 0x04: /* Timeout */ case 0x04: /* Timeout */
s->status = data; s->status = data;
break; break;
case 0x00: /* Input port - ignore writes */ case 0x00: /* Input port - ignore writes */
break; break;
default: default:
qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n", qemu_log_mask(LOG_UNIMP, "%s: Unsupported register 0x02%" PRIx8 "\n",

View File

@ -34,28 +34,28 @@ struct ADS7846State {
OBJECT_DECLARE_SIMPLE_TYPE(ADS7846State, ADS7846) OBJECT_DECLARE_SIMPLE_TYPE(ADS7846State, ADS7846)
/* Control-byte bitfields */ /* Control-byte bitfields */
#define CB_PD0 (1 << 0) #define CB_PD0 (1 << 0)
#define CB_PD1 (1 << 1) #define CB_PD1 (1 << 1)
#define CB_SER (1 << 2) #define CB_SER (1 << 2)
#define CB_MODE (1 << 3) #define CB_MODE (1 << 3)
#define CB_A0 (1 << 4) #define CB_A0 (1 << 4)
#define CB_A1 (1 << 5) #define CB_A1 (1 << 5)
#define CB_A2 (1 << 6) #define CB_A2 (1 << 6)
#define CB_START (1 << 7) #define CB_START (1 << 7)
#define X_AXIS_DMAX 3470 #define X_AXIS_DMAX 3470
#define X_AXIS_MIN 290 #define X_AXIS_MIN 290
#define Y_AXIS_DMAX 3450 #define Y_AXIS_DMAX 3450
#define Y_AXIS_MIN 200 #define Y_AXIS_MIN 200
#define ADS_VBAT 2000 #define ADS_VBAT 2000
#define ADS_VAUX 2000 #define ADS_VAUX 2000
#define ADS_TEMP0 2000 #define ADS_TEMP0 2000
#define ADS_TEMP1 3000 #define ADS_TEMP1 3000
#define ADS_XPOS(x, y) (X_AXIS_MIN + ((X_AXIS_DMAX * (x)) >> 15)) #define ADS_XPOS(x, y) (X_AXIS_MIN + ((X_AXIS_DMAX * (x)) >> 15))
#define ADS_YPOS(x, y) (Y_AXIS_MIN + ((Y_AXIS_DMAX * (y)) >> 15)) #define ADS_YPOS(x, y) (Y_AXIS_MIN + ((Y_AXIS_DMAX * (y)) >> 15))
#define ADS_Z1POS(x, y) 600 #define ADS_Z1POS(x, y) 600
#define ADS_Z2POS(x, y) (600 + 6000 / ADS_XPOS(x, y)) #define ADS_Z2POS(x, y) (600 + 6000 / ADS_XPOS(x, y))
static void ads7846_int_update(ADS7846State *s) static void ads7846_int_update(ADS7846State *s)
{ {
@ -86,7 +86,7 @@ static uint32_t ads7846_transfer(SSIPeripheral *dev, uint32_t value)
} }
if (value & CB_MODE) if (value & CB_MODE)
s->output >>= 4; /* 8 bits instead of 12 */ s->output >>= 4; /* 8 bits instead of 12 */
break; break;
case 1: case 1:
@ -147,10 +147,10 @@ static void ads7846_realize(SSIPeripheral *d, Error **errp)
qdev_init_gpio_out(dev, &s->interrupt, 1); qdev_init_gpio_out(dev, &s->interrupt, 1);
s->input[0] = ADS_TEMP0; /* TEMP0 */ s->input[0] = ADS_TEMP0; /* TEMP0 */
s->input[2] = ADS_VBAT; /* VBAT */ s->input[2] = ADS_VBAT; /* VBAT */
s->input[6] = ADS_VAUX; /* VAUX */ s->input[6] = ADS_VAUX; /* VAUX */
s->input[7] = ADS_TEMP1; /* TEMP1 */ s->input[7] = ADS_TEMP1; /* TEMP1 */
/* We want absolute coordinates */ /* We want absolute coordinates */
qemu_add_mouse_event_handler(ads7846_ts_event, s, 1, qemu_add_mouse_event_handler(ads7846_ts_event, s, 1,

View File

@ -93,9 +93,9 @@ static void alarm_cb (void *opaque)
qemu_set_irq(NVRAM->IRQ, 1); qemu_set_irq(NVRAM->IRQ, 1);
if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 && if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 && (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 && (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) { (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a month */ /* Repeat once a month */
qemu_get_timedate(&tm, NVRAM->time_offset); qemu_get_timedate(&tm, NVRAM->time_offset);
tm.tm_mon++; tm.tm_mon++;
@ -105,21 +105,21 @@ static void alarm_cb (void *opaque)
} }
next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset; next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 && (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 && (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) { (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a day */ /* Repeat once a day */
next_time = 24 * 60 * 60; next_time = 24 * 60 * 60;
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 && (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 && (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) { (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once an hour */ /* Repeat once an hour */
next_time = 60 * 60; next_time = 60 * 60;
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 && (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) != 0 && (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) { (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a minute */ /* Repeat once a minute */
next_time = 60; next_time = 60;
} else { } else {
@ -161,13 +161,13 @@ static void watchdog_cb (void *opaque)
NVRAM->buffer[0x1FF0] |= 0x80; NVRAM->buffer[0x1FF0] |= 0x80;
if (NVRAM->buffer[0x1FF7] & 0x80) { if (NVRAM->buffer[0x1FF7] & 0x80) {
NVRAM->buffer[0x1FF7] = 0x00; NVRAM->buffer[0x1FF7] = 0x00;
NVRAM->buffer[0x1FFC] &= ~0x40; NVRAM->buffer[0x1FFC] &= ~0x40;
/* May it be a hw CPU Reset instead ? */ /* May it be a hw CPU Reset instead ? */
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
} else { } else {
qemu_set_irq(NVRAM->IRQ, 1); qemu_set_irq(NVRAM->IRQ, 1);
qemu_set_irq(NVRAM->IRQ, 0); qemu_set_irq(NVRAM->IRQ, 0);
} }
} }
@ -262,80 +262,80 @@ void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val)
case 0x1FF9: case 0x1FF9:
case 0x07F9: case 0x07F9:
/* seconds (BCD) */ /* seconds (BCD) */
tmp = from_bcd(val & 0x7F); tmp = from_bcd(val & 0x7F);
if (tmp >= 0 && tmp <= 59) { if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm); get_time(NVRAM, &tm);
tm.tm_sec = tmp; tm.tm_sec = tmp;
set_time(NVRAM, &tm); set_time(NVRAM, &tm);
} }
if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) { if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
if (val & 0x80) { if (val & 0x80) {
NVRAM->stop_time = time(NULL); NVRAM->stop_time = time(NULL);
} else { } else {
NVRAM->time_offset += NVRAM->stop_time - time(NULL); NVRAM->time_offset += NVRAM->stop_time - time(NULL);
NVRAM->stop_time = 0; NVRAM->stop_time = 0;
} }
} }
NVRAM->buffer[addr] = val & 0x80; NVRAM->buffer[addr] = val & 0x80;
break; break;
case 0x1FFA: case 0x1FFA:
case 0x07FA: case 0x07FA:
/* minutes (BCD) */ /* minutes (BCD) */
tmp = from_bcd(val & 0x7F); tmp = from_bcd(val & 0x7F);
if (tmp >= 0 && tmp <= 59) { if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm); get_time(NVRAM, &tm);
tm.tm_min = tmp; tm.tm_min = tmp;
set_time(NVRAM, &tm); set_time(NVRAM, &tm);
} }
break; break;
case 0x1FFB: case 0x1FFB:
case 0x07FB: case 0x07FB:
/* hours (BCD) */ /* hours (BCD) */
tmp = from_bcd(val & 0x3F); tmp = from_bcd(val & 0x3F);
if (tmp >= 0 && tmp <= 23) { if (tmp >= 0 && tmp <= 23) {
get_time(NVRAM, &tm); get_time(NVRAM, &tm);
tm.tm_hour = tmp; tm.tm_hour = tmp;
set_time(NVRAM, &tm); set_time(NVRAM, &tm);
} }
break; break;
case 0x1FFC: case 0x1FFC:
case 0x07FC: case 0x07FC:
/* day of the week / century */ /* day of the week / century */
tmp = from_bcd(val & 0x07); tmp = from_bcd(val & 0x07);
get_time(NVRAM, &tm); get_time(NVRAM, &tm);
tm.tm_wday = tmp; tm.tm_wday = tmp;
set_time(NVRAM, &tm); set_time(NVRAM, &tm);
NVRAM->buffer[addr] = val & 0x40; NVRAM->buffer[addr] = val & 0x40;
break; break;
case 0x1FFD: case 0x1FFD:
case 0x07FD: case 0x07FD:
/* date (BCD) */ /* date (BCD) */
tmp = from_bcd(val & 0x3F); tmp = from_bcd(val & 0x3F);
if (tmp != 0) { if (tmp != 0) {
get_time(NVRAM, &tm); get_time(NVRAM, &tm);
tm.tm_mday = tmp; tm.tm_mday = tmp;
set_time(NVRAM, &tm); set_time(NVRAM, &tm);
} }
break; break;
case 0x1FFE: case 0x1FFE:
case 0x07FE: case 0x07FE:
/* month */ /* month */
tmp = from_bcd(val & 0x1F); tmp = from_bcd(val & 0x1F);
if (tmp >= 1 && tmp <= 12) { if (tmp >= 1 && tmp <= 12) {
get_time(NVRAM, &tm); get_time(NVRAM, &tm);
tm.tm_mon = tmp - 1; tm.tm_mon = tmp - 1;
set_time(NVRAM, &tm); set_time(NVRAM, &tm);
} }
break; break;
case 0x1FFF: case 0x1FFF:
case 0x07FF: case 0x07FF:
/* year */ /* year */
tmp = from_bcd(val); tmp = from_bcd(val);
if (tmp >= 0 && tmp <= 99) { if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm); get_time(NVRAM, &tm);
tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900; tm.tm_year = from_bcd(val) + NVRAM->base_year - 1900;
set_time(NVRAM, &tm); set_time(NVRAM, &tm);
} }
break; break;
default: default:
/* Check lock registers state */ /* Check lock registers state */
@ -346,7 +346,7 @@ void m48t59_write(M48t59State *NVRAM, uint32_t addr, uint32_t val)
do_write: do_write:
if (addr < NVRAM->size) { if (addr < NVRAM->size) {
NVRAM->buffer[addr] = val & 0xFF; NVRAM->buffer[addr] = val & 0xFF;
} }
break; break;
} }
} }
@ -367,34 +367,34 @@ uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr)
switch (addr) { switch (addr) {
case 0x1FF0: case 0x1FF0:
/* flags register */ /* flags register */
goto do_read; goto do_read;
case 0x1FF1: case 0x1FF1:
/* unused */ /* unused */
retval = 0; retval = 0;
break; break;
case 0x1FF2: case 0x1FF2:
/* alarm seconds */ /* alarm seconds */
goto do_read; goto do_read;
case 0x1FF3: case 0x1FF3:
/* alarm minutes */ /* alarm minutes */
goto do_read; goto do_read;
case 0x1FF4: case 0x1FF4:
/* alarm hours */ /* alarm hours */
goto do_read; goto do_read;
case 0x1FF5: case 0x1FF5:
/* alarm date */ /* alarm date */
goto do_read; goto do_read;
case 0x1FF6: case 0x1FF6:
/* interrupts */ /* interrupts */
goto do_read; goto do_read;
case 0x1FF7: case 0x1FF7:
/* A read resets the watchdog */ /* A read resets the watchdog */
set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]); set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
goto do_read; goto do_read;
case 0x1FF8: case 0x1FF8:
case 0x07F8: case 0x07F8:
/* control */ /* control */
goto do_read; goto do_read;
case 0x1FF9: case 0x1FF9:
case 0x07F9: case 0x07F9:
/* seconds (BCD) */ /* seconds (BCD) */
@ -446,7 +446,7 @@ uint32_t m48t59_read(M48t59State *NVRAM, uint32_t addr)
do_read: do_read:
if (addr < NVRAM->size) { if (addr < NVRAM->size) {
retval = NVRAM->buffer[addr]; retval = NVRAM->buffer[addr];
} }
break; break;
} }
trace_m48txx_nvram_mem_read(addr, retval); trace_m48txx_nvram_mem_read(addr, retval);

View File

@ -112,19 +112,19 @@ static void menelaus_rtc_hz(void *opaque)
s->rtc.alm_sec --; s->rtc.alm_sec --;
s->rtc.next += 1000; s->rtc.next += 1000;
timer_mod(s->rtc.hz_tm, s->rtc.next); timer_mod(s->rtc.hz_tm, s->rtc.next);
if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */ if ((s->rtc.ctrl >> 3) & 3) { /* EVERY */
menelaus_rtc_update(s); menelaus_rtc_update(s);
if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec) if (((s->rtc.ctrl >> 3) & 3) == 1 && !s->rtc.tm.tm_sec)
s->status |= 1 << 8; /* RTCTMR */ s->status |= 1 << 8; /* RTCTMR */
else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min) else if (((s->rtc.ctrl >> 3) & 3) == 2 && !s->rtc.tm.tm_min)
s->status |= 1 << 8; /* RTCTMR */ s->status |= 1 << 8; /* RTCTMR */
else if (!s->rtc.tm.tm_hour) else if (!s->rtc.tm.tm_hour)
s->status |= 1 << 8; /* RTCTMR */ s->status |= 1 << 8; /* RTCTMR */
} else } else
s->status |= 1 << 8; /* RTCTMR */ s->status |= 1 << 8; /* RTCTMR */
if ((s->rtc.ctrl >> 1) & 1) { /* RTC_AL_EN */ if ((s->rtc.ctrl >> 1) & 1) { /* RTC_AL_EN */
if (s->rtc.alm_sec == 0) if (s->rtc.alm_sec == 0)
s->status |= 1 << 9; /* RTCALM */ s->status |= 1 << 9; /* RTCALM */
/* TODO: wake-up */ /* TODO: wake-up */
} }
if (s->rtc.next_comp <= 0) { if (s->rtc.next_comp <= 0) {
@ -140,19 +140,19 @@ static void menelaus_reset(I2CSlave *i2c)
s->reg = 0x00; s->reg = 0x00;
s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */ s->vcore[0] = 0x0c; /* XXX: X-loader needs 0x8c? check! */
s->vcore[1] = 0x05; s->vcore[1] = 0x05;
s->vcore[2] = 0x02; s->vcore[2] = 0x02;
s->vcore[3] = 0x0c; s->vcore[3] = 0x0c;
s->vcore[4] = 0x03; s->vcore[4] = 0x03;
s->dcdc[0] = 0x33; /* Depends on wiring */ s->dcdc[0] = 0x33; /* Depends on wiring */
s->dcdc[1] = 0x03; s->dcdc[1] = 0x03;
s->dcdc[2] = 0x00; s->dcdc[2] = 0x00;
s->ldo[0] = 0x95; s->ldo[0] = 0x95;
s->ldo[1] = 0x7e; s->ldo[1] = 0x7e;
s->ldo[2] = 0x00; s->ldo[2] = 0x00;
s->ldo[3] = 0x00; /* Depends on wiring */ s->ldo[3] = 0x00; /* Depends on wiring */
s->ldo[4] = 0x03; /* Depends on wiring */ s->ldo[4] = 0x03; /* Depends on wiring */
s->ldo[5] = 0x00; s->ldo[5] = 0x00;
s->ldo[6] = 0x00; s->ldo[6] = 0x00;
s->ldo[7] = 0x00; s->ldo[7] = 0x00;
@ -203,70 +203,70 @@ static void menelaus_gpio_set(void *opaque, int line, int level)
} }
if (!s->pwrbtn_state && level) { if (!s->pwrbtn_state && level) {
s->status |= 1 << 11; /* PSHBTN */ s->status |= 1 << 11; /* PSHBTN */
menelaus_update(s); menelaus_update(s);
} }
s->pwrbtn_state = level; s->pwrbtn_state = level;
} }
#define MENELAUS_REV 0x01 #define MENELAUS_REV 0x01
#define MENELAUS_VCORE_CTRL1 0x02 #define MENELAUS_VCORE_CTRL1 0x02
#define MENELAUS_VCORE_CTRL2 0x03 #define MENELAUS_VCORE_CTRL2 0x03
#define MENELAUS_VCORE_CTRL3 0x04 #define MENELAUS_VCORE_CTRL3 0x04
#define MENELAUS_VCORE_CTRL4 0x05 #define MENELAUS_VCORE_CTRL4 0x05
#define MENELAUS_VCORE_CTRL5 0x06 #define MENELAUS_VCORE_CTRL5 0x06
#define MENELAUS_DCDC_CTRL1 0x07 #define MENELAUS_DCDC_CTRL1 0x07
#define MENELAUS_DCDC_CTRL2 0x08 #define MENELAUS_DCDC_CTRL2 0x08
#define MENELAUS_DCDC_CTRL3 0x09 #define MENELAUS_DCDC_CTRL3 0x09
#define MENELAUS_LDO_CTRL1 0x0a #define MENELAUS_LDO_CTRL1 0x0a
#define MENELAUS_LDO_CTRL2 0x0b #define MENELAUS_LDO_CTRL2 0x0b
#define MENELAUS_LDO_CTRL3 0x0c #define MENELAUS_LDO_CTRL3 0x0c
#define MENELAUS_LDO_CTRL4 0x0d #define MENELAUS_LDO_CTRL4 0x0d
#define MENELAUS_LDO_CTRL5 0x0e #define MENELAUS_LDO_CTRL5 0x0e
#define MENELAUS_LDO_CTRL6 0x0f #define MENELAUS_LDO_CTRL6 0x0f
#define MENELAUS_LDO_CTRL7 0x10 #define MENELAUS_LDO_CTRL7 0x10
#define MENELAUS_LDO_CTRL8 0x11 #define MENELAUS_LDO_CTRL8 0x11
#define MENELAUS_SLEEP_CTRL1 0x12 #define MENELAUS_SLEEP_CTRL1 0x12
#define MENELAUS_SLEEP_CTRL2 0x13 #define MENELAUS_SLEEP_CTRL2 0x13
#define MENELAUS_DEVICE_OFF 0x14 #define MENELAUS_DEVICE_OFF 0x14
#define MENELAUS_OSC_CTRL 0x15 #define MENELAUS_OSC_CTRL 0x15
#define MENELAUS_DETECT_CTRL 0x16 #define MENELAUS_DETECT_CTRL 0x16
#define MENELAUS_INT_MASK1 0x17 #define MENELAUS_INT_MASK1 0x17
#define MENELAUS_INT_MASK2 0x18 #define MENELAUS_INT_MASK2 0x18
#define MENELAUS_INT_STATUS1 0x19 #define MENELAUS_INT_STATUS1 0x19
#define MENELAUS_INT_STATUS2 0x1a #define MENELAUS_INT_STATUS2 0x1a
#define MENELAUS_INT_ACK1 0x1b #define MENELAUS_INT_ACK1 0x1b
#define MENELAUS_INT_ACK2 0x1c #define MENELAUS_INT_ACK2 0x1c
#define MENELAUS_GPIO_CTRL 0x1d #define MENELAUS_GPIO_CTRL 0x1d
#define MENELAUS_GPIO_IN 0x1e #define MENELAUS_GPIO_IN 0x1e
#define MENELAUS_GPIO_OUT 0x1f #define MENELAUS_GPIO_OUT 0x1f
#define MENELAUS_BBSMS 0x20 #define MENELAUS_BBSMS 0x20
#define MENELAUS_RTC_CTRL 0x21 #define MENELAUS_RTC_CTRL 0x21
#define MENELAUS_RTC_UPDATE 0x22 #define MENELAUS_RTC_UPDATE 0x22
#define MENELAUS_RTC_SEC 0x23 #define MENELAUS_RTC_SEC 0x23
#define MENELAUS_RTC_MIN 0x24 #define MENELAUS_RTC_MIN 0x24
#define MENELAUS_RTC_HR 0x25 #define MENELAUS_RTC_HR 0x25
#define MENELAUS_RTC_DAY 0x26 #define MENELAUS_RTC_DAY 0x26
#define MENELAUS_RTC_MON 0x27 #define MENELAUS_RTC_MON 0x27
#define MENELAUS_RTC_YR 0x28 #define MENELAUS_RTC_YR 0x28
#define MENELAUS_RTC_WKDAY 0x29 #define MENELAUS_RTC_WKDAY 0x29
#define MENELAUS_RTC_AL_SEC 0x2a #define MENELAUS_RTC_AL_SEC 0x2a
#define MENELAUS_RTC_AL_MIN 0x2b #define MENELAUS_RTC_AL_MIN 0x2b
#define MENELAUS_RTC_AL_HR 0x2c #define MENELAUS_RTC_AL_HR 0x2c
#define MENELAUS_RTC_AL_DAY 0x2d #define MENELAUS_RTC_AL_DAY 0x2d
#define MENELAUS_RTC_AL_MON 0x2e #define MENELAUS_RTC_AL_MON 0x2e
#define MENELAUS_RTC_AL_YR 0x2f #define MENELAUS_RTC_AL_YR 0x2f
#define MENELAUS_RTC_COMP_MSB 0x30 #define MENELAUS_RTC_COMP_MSB 0x30
#define MENELAUS_RTC_COMP_LSB 0x31 #define MENELAUS_RTC_COMP_LSB 0x31
#define MENELAUS_S1_PULL_EN 0x32 #define MENELAUS_S1_PULL_EN 0x32
#define MENELAUS_S1_PULL_DIR 0x33 #define MENELAUS_S1_PULL_DIR 0x33
#define MENELAUS_S2_PULL_EN 0x34 #define MENELAUS_S2_PULL_EN 0x34
#define MENELAUS_S2_PULL_DIR 0x35 #define MENELAUS_S2_PULL_DIR 0x35
#define MENELAUS_MCT_CTRL1 0x36 #define MENELAUS_MCT_CTRL1 0x36
#define MENELAUS_MCT_CTRL2 0x37 #define MENELAUS_MCT_CTRL2 0x37
#define MENELAUS_MCT_CTRL3 0x38 #define MENELAUS_MCT_CTRL3 0x38
#define MENELAUS_MCT_PIN_ST 0x39 #define MENELAUS_MCT_PIN_ST 0x39
#define MENELAUS_DEBOUNCE1 0x3a #define MENELAUS_DEBOUNCE1 0x3a
static uint8_t menelaus_read(void *opaque, uint8_t addr) static uint8_t menelaus_read(void *opaque, uint8_t addr)
{ {
@ -293,7 +293,7 @@ static uint8_t menelaus_read(void *opaque, uint8_t addr)
return 0; return 0;
case MENELAUS_OSC_CTRL: case MENELAUS_OSC_CTRL:
return s->osc | (1 << 7); /* CLK32K_GOOD */ return s->osc | (1 << 7); /* CLK32K_GOOD */
case MENELAUS_DETECT_CTRL: case MENELAUS_DETECT_CTRL:
return s->detect; return s->detect;
@ -334,9 +334,9 @@ static uint8_t menelaus_read(void *opaque, uint8_t addr)
return to_bcd(s->rtc.tm.tm_min); return to_bcd(s->rtc.tm.tm_min);
case MENELAUS_RTC_HR: case MENELAUS_RTC_HR:
menelaus_rtc_update(s); menelaus_rtc_update(s);
if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
return to_bcd((s->rtc.tm.tm_hour % 12) + 1) | return to_bcd((s->rtc.tm.tm_hour % 12) + 1) |
(!!(s->rtc.tm.tm_hour >= 12) << 7); /* PM_nAM */ (!!(s->rtc.tm.tm_hour >= 12) << 7); /* PM_nAM */
else else
return to_bcd(s->rtc.tm.tm_hour); return to_bcd(s->rtc.tm.tm_hour);
case MENELAUS_RTC_DAY: case MENELAUS_RTC_DAY:
@ -356,7 +356,7 @@ static uint8_t menelaus_read(void *opaque, uint8_t addr)
case MENELAUS_RTC_AL_MIN: case MENELAUS_RTC_AL_MIN:
return to_bcd(s->rtc.alm.tm_min); return to_bcd(s->rtc.alm.tm_min);
case MENELAUS_RTC_AL_HR: case MENELAUS_RTC_AL_HR:
if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */ if ((s->rtc.ctrl >> 2) & 1) /* MODE12_n24 */
return to_bcd((s->rtc.alm.tm_hour % 12) + 1) | return to_bcd((s->rtc.alm.tm_hour % 12) + 1) |
(!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */ (!!(s->rtc.alm.tm_hour >= 12) << 7);/* AL_PM_nAM */
else else
@ -541,7 +541,7 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
break; break;
case MENELAUS_RTC_CTRL: case MENELAUS_RTC_CTRL:
if ((s->rtc.ctrl ^ value) & 1) { /* RTC_EN */ if ((s->rtc.ctrl ^ value) & 1) { /* RTC_EN */
if (value & 1) if (value & 1)
menelaus_rtc_start(s); menelaus_rtc_start(s);
else else
@ -603,7 +603,7 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
default: default:
fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n", fprintf(stderr, "%s: bad RTC_UPDATE value %02x\n",
__func__, value); __func__, value);
s->status |= 1 << 10; /* RTCERR */ s->status |= 1 << 10; /* RTCERR */
menelaus_update(s); menelaus_update(s);
} }
s->rtc.sec_offset = qemu_timedate_diff(&tm); s->rtc.sec_offset = qemu_timedate_diff(&tm);
@ -615,7 +615,7 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
s->rtc.tm.tm_min = from_bcd(value & 0x7f); s->rtc.tm.tm_min = from_bcd(value & 0x7f);
break; break;
case MENELAUS_RTC_HR: case MENELAUS_RTC_HR:
s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */ s->rtc.tm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) : MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
from_bcd(value & 0x3f); from_bcd(value & 0x3f);
break; break;
@ -640,7 +640,7 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value)
menelaus_alm_update(s); menelaus_alm_update(s);
break; break;
case MENELAUS_RTC_AL_HR: case MENELAUS_RTC_AL_HR:
s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */ s->rtc.alm.tm_hour = (s->rtc.ctrl & (1 << 2)) ? /* MODE12_n24 */
MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) : MIN(from_bcd(value & 0x3f), 12) + ((value >> 7) ? 11 : -1) :
from_bcd(value & 0x3f); from_bcd(value & 0x3f);
menelaus_alm_update(s); menelaus_alm_update(s);
@ -792,14 +792,14 @@ static int menelaus_post_load(void *opaque, int version_id)
{ {
MenelausState *s = opaque; MenelausState *s = opaque;
if (s->rtc.ctrl & 1) /* RTC_EN */ if (s->rtc.ctrl & 1) /* RTC_EN */
menelaus_rtc_stop(s); menelaus_rtc_stop(s);
s->rtc.next = s->rtc_next_vmstate; s->rtc.next = s->rtc_next_vmstate;
menelaus_alm_update(s); menelaus_alm_update(s);
menelaus_update(s); menelaus_update(s);
if (s->rtc.ctrl & 1) /* RTC_EN */ if (s->rtc.ctrl & 1) /* RTC_EN */
menelaus_rtc_start(s); menelaus_rtc_start(s);
return 0; return 0;
} }

View File

@ -199,8 +199,8 @@ static void scsi_dma_restart_cb(void *opaque, bool running, RunState state)
} }
static bool scsi_bus_is_address_free(SCSIBus *bus, static bool scsi_bus_is_address_free(SCSIBus *bus,
int channel, int target, int lun, int channel, int target, int lun,
SCSIDevice **p_dev) SCSIDevice **p_dev)
{ {
SCSIDevice *d; SCSIDevice *d;

View File

@ -342,39 +342,39 @@ static void sd_set_scr(SDState *sd)
sd->scr[7] = 0x00; sd->scr[7] = 0x00;
} }
#define MID 0xaa #define MID 0xaa
#define OID "XY" #define OID "XY"
#define PNM "QEMU!" #define PNM "QEMU!"
#define PRV 0x01 #define PRV 0x01
#define MDT_YR 2006 #define MDT_YR 2006
#define MDT_MON 2 #define MDT_MON 2
static void sd_set_cid(SDState *sd) static void sd_set_cid(SDState *sd)
{ {
sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */ sd->cid[0] = MID; /* Fake card manufacturer ID (MID) */
sd->cid[1] = OID[0]; /* OEM/Application ID (OID) */ sd->cid[1] = OID[0]; /* OEM/Application ID (OID) */
sd->cid[2] = OID[1]; sd->cid[2] = OID[1];
sd->cid[3] = PNM[0]; /* Fake product name (PNM) */ sd->cid[3] = PNM[0]; /* Fake product name (PNM) */
sd->cid[4] = PNM[1]; sd->cid[4] = PNM[1];
sd->cid[5] = PNM[2]; sd->cid[5] = PNM[2];
sd->cid[6] = PNM[3]; sd->cid[6] = PNM[3];
sd->cid[7] = PNM[4]; sd->cid[7] = PNM[4];
sd->cid[8] = PRV; /* Fake product revision (PRV) */ sd->cid[8] = PRV; /* Fake product revision (PRV) */
sd->cid[9] = 0xde; /* Fake serial number (PSN) */ sd->cid[9] = 0xde; /* Fake serial number (PSN) */
sd->cid[10] = 0xad; sd->cid[10] = 0xad;
sd->cid[11] = 0xbe; sd->cid[11] = 0xbe;
sd->cid[12] = 0xef; sd->cid[12] = 0xef;
sd->cid[13] = 0x00 | /* Manufacture date (MDT) */ sd->cid[13] = 0x00 | /* Manufacture date (MDT) */
((MDT_YR - 2000) / 10); ((MDT_YR - 2000) / 10);
sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON; sd->cid[14] = ((MDT_YR % 10) << 4) | MDT_MON;
sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1; sd->cid[15] = (sd_crc7(sd->cid, 15) << 1) | 1;
} }
#define HWBLOCK_SHIFT 9 /* 512 bytes */ #define HWBLOCK_SHIFT 9 /* 512 bytes */
#define SECTOR_SHIFT 5 /* 16 kilobytes */ #define SECTOR_SHIFT 5 /* 16 kilobytes */
#define WPGROUP_SHIFT 7 /* 2 megs */ #define WPGROUP_SHIFT 7 /* 2 megs */
#define CMULT_SHIFT 9 /* 512 times HWBLOCK_SIZE */ #define CMULT_SHIFT 9 /* 512 times HWBLOCK_SIZE */
#define WPGROUP_SIZE (1 << (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT)) #define WPGROUP_SIZE (1 << (HWBLOCK_SHIFT + SECTOR_SHIFT + WPGROUP_SHIFT))
static const uint8_t sd_csd_rw_mask[16] = { static const uint8_t sd_csd_rw_mask[16] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -395,31 +395,31 @@ static void sd_set_csd(SDState *sd, uint64_t size)
csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1; csize = (size >> (CMULT_SHIFT + hwblock_shift)) - 1;
if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */ if (size <= SDSC_MAX_CAPACITY) { /* Standard Capacity SD */
sd->csd[0] = 0x00; /* CSD structure */ sd->csd[0] = 0x00; /* CSD structure */
sd->csd[1] = 0x26; /* Data read access-time-1 */ sd->csd[1] = 0x26; /* Data read access-time-1 */
sd->csd[2] = 0x00; /* Data read access-time-2 */ sd->csd[2] = 0x00; /* Data read access-time-2 */
sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */ sd->csd[3] = 0x32; /* Max. data transfer rate: 25 MHz */
sd->csd[4] = 0x5f; /* Card Command Classes */ sd->csd[4] = 0x5f; /* Card Command Classes */
sd->csd[5] = 0x50 | /* Max. read data block length */ sd->csd[5] = 0x50 | /* Max. read data block length */
hwblock_shift; hwblock_shift;
sd->csd[6] = 0xe0 | /* Partial block for read allowed */ sd->csd[6] = 0xe0 | /* Partial block for read allowed */
((csize >> 10) & 0x03); ((csize >> 10) & 0x03);
sd->csd[7] = 0x00 | /* Device size */ sd->csd[7] = 0x00 | /* Device size */
((csize >> 2) & 0xff); ((csize >> 2) & 0xff);
sd->csd[8] = 0x3f | /* Max. read current */ sd->csd[8] = 0x3f | /* Max. read current */
((csize << 6) & 0xc0); ((csize << 6) & 0xc0);
sd->csd[9] = 0xfc | /* Max. write current */ sd->csd[9] = 0xfc | /* Max. write current */
((CMULT_SHIFT - 2) >> 1); ((CMULT_SHIFT - 2) >> 1);
sd->csd[10] = 0x40 | /* Erase sector size */ sd->csd[10] = 0x40 | /* Erase sector size */
(((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1); (((CMULT_SHIFT - 2) << 7) & 0x80) | (sectsize >> 1);
sd->csd[11] = 0x00 | /* Write protect group size */ sd->csd[11] = 0x00 | /* Write protect group size */
((sectsize << 7) & 0x80) | wpsize; ((sectsize << 7) & 0x80) | wpsize;
sd->csd[12] = 0x90 | /* Write speed factor */ sd->csd[12] = 0x90 | /* Write speed factor */
(hwblock_shift >> 2); (hwblock_shift >> 2);
sd->csd[13] = 0x20 | /* Max. write data block length */ sd->csd[13] = 0x20 | /* Max. write data block length */
((hwblock_shift << 6) & 0xc0); ((hwblock_shift << 6) & 0xc0);
sd->csd[14] = 0x00; /* File format group */ sd->csd[14] = 0x00; /* File format group */
} else { /* SDHC */ } else { /* SDHC */
size /= 512 * KiB; size /= 512 * KiB;
size -= 1; size -= 1;
sd->csd[0] = 0x40; sd->csd[0] = 0x40;
@ -513,7 +513,7 @@ static int sd_req_crc_validate(SDRequest *req)
buffer[0] = 0x40 | req->cmd; buffer[0] = 0x40 | req->cmd;
stl_be_p(&buffer[1], req->arg); stl_be_p(&buffer[1], req->arg);
return 0; return 0;
return sd_crc7(buffer, 5) != req->crc; /* TODO */ return sd_crc7(buffer, 5) != req->crc; /* TODO */
} }
static void sd_response_r1_make(SDState *sd, uint8_t *response) static void sd_response_r1_make(SDState *sd, uint8_t *response)
@ -851,19 +851,19 @@ static void sd_function_switch(SDState *sd, uint32_t arg)
int i, mode, new_func; int i, mode, new_func;
mode = !!(arg & 0x80000000); mode = !!(arg & 0x80000000);
sd->data[0] = 0x00; /* Maximum current consumption */ sd->data[0] = 0x00; /* Maximum current consumption */
sd->data[1] = 0x01; sd->data[1] = 0x01;
sd->data[2] = 0x80; /* Supported group 6 functions */ sd->data[2] = 0x80; /* Supported group 6 functions */
sd->data[3] = 0x01; sd->data[3] = 0x01;
sd->data[4] = 0x80; /* Supported group 5 functions */ sd->data[4] = 0x80; /* Supported group 5 functions */
sd->data[5] = 0x01; sd->data[5] = 0x01;
sd->data[6] = 0x80; /* Supported group 4 functions */ sd->data[6] = 0x80; /* Supported group 4 functions */
sd->data[7] = 0x01; sd->data[7] = 0x01;
sd->data[8] = 0x80; /* Supported group 3 functions */ sd->data[8] = 0x80; /* Supported group 3 functions */
sd->data[9] = 0x01; sd->data[9] = 0x01;
sd->data[10] = 0x80; /* Supported group 2 functions */ sd->data[10] = 0x80; /* Supported group 2 functions */
sd->data[11] = 0x43; sd->data[11] = 0x43;
sd->data[12] = 0x80; /* Supported group 1 functions */ sd->data[12] = 0x80; /* Supported group 1 functions */
sd->data[13] = 0x03; sd->data[13] = 0x03;
memset(&sd->data[14], 0, 3); memset(&sd->data[14], 0, 3);
@ -1001,7 +1001,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
switch (req.cmd) { switch (req.cmd) {
/* Basic commands (Class 0 and Class 1) */ /* Basic commands (Class 0 and Class 1) */
case 0: /* CMD0: GO_IDLE_STATE */ case 0: /* CMD0: GO_IDLE_STATE */
switch (sd->state) { switch (sd->state) {
case sd_inactive_state: case sd_inactive_state:
return sd->spi ? sd_r1 : sd_r0; return sd->spi ? sd_r1 : sd_r0;
@ -1013,14 +1013,14 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 1: /* CMD1: SEND_OP_CMD */ case 1: /* CMD1: SEND_OP_CMD */
if (!sd->spi) if (!sd->spi)
goto bad_cmd; goto bad_cmd;
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
return sd_r1; return sd_r1;
case 2: /* CMD2: ALL_SEND_CID */ case 2: /* CMD2: ALL_SEND_CID */
if (sd->spi) if (sd->spi)
goto bad_cmd; goto bad_cmd;
switch (sd->state) { switch (sd->state) {
@ -1033,7 +1033,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 3: /* CMD3: SEND_RELATIVE_ADDR */ case 3: /* CMD3: SEND_RELATIVE_ADDR */
if (sd->spi) if (sd->spi)
goto bad_cmd; goto bad_cmd;
switch (sd->state) { switch (sd->state) {
@ -1048,7 +1048,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 4: /* CMD4: SEND_DSR */ case 4: /* CMD4: SEND_DSR */
if (sd->spi) if (sd->spi)
goto bad_cmd; goto bad_cmd;
switch (sd->state) { switch (sd->state) {
@ -1063,7 +1063,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
case 5: /* CMD5: reserved for SDIO cards */ case 5: /* CMD5: reserved for SDIO cards */
return sd_illegal; return sd_illegal;
case 6: /* CMD6: SWITCH_FUNCTION */ case 6: /* CMD6: SWITCH_FUNCTION */
switch (sd->mode) { switch (sd->mode) {
case sd_data_transfer_mode: case sd_data_transfer_mode:
sd_function_switch(sd, req.arg); sd_function_switch(sd, req.arg);
@ -1077,7 +1077,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 7: /* CMD7: SELECT/DESELECT_CARD */ case 7: /* CMD7: SELECT/DESELECT_CARD */
if (sd->spi) if (sd->spi)
goto bad_cmd; goto bad_cmd;
switch (sd->state) { switch (sd->state) {
@ -1115,7 +1115,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 8: /* CMD8: SEND_IF_COND */ case 8: /* CMD8: SEND_IF_COND */
if (sd->spec_version < SD_PHY_SPECv2_00_VERS) { if (sd->spec_version < SD_PHY_SPECv2_00_VERS) {
break; break;
} }
@ -1133,7 +1133,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
sd->vhs = req.arg; sd->vhs = req.arg;
return sd_r7; return sd_r7;
case 9: /* CMD9: SEND_CSD */ case 9: /* CMD9: SEND_CSD */
switch (sd->state) { switch (sd->state) {
case sd_standby_state: case sd_standby_state:
if (sd->rca != rca) if (sd->rca != rca)
@ -1155,7 +1155,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 10: /* CMD10: SEND_CID */ case 10: /* CMD10: SEND_CID */
switch (sd->state) { switch (sd->state) {
case sd_standby_state: case sd_standby_state:
if (sd->rca != rca) if (sd->rca != rca)
@ -1177,7 +1177,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 12: /* CMD12: STOP_TRANSMISSION */ case 12: /* CMD12: STOP_TRANSMISSION */
switch (sd->state) { switch (sd->state) {
case sd_sendingdata_state: case sd_sendingdata_state:
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
@ -1194,7 +1194,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 13: /* CMD13: SEND_STATUS */ case 13: /* CMD13: SEND_STATUS */
switch (sd->mode) { switch (sd->mode) {
case sd_data_transfer_mode: case sd_data_transfer_mode:
if (!sd->spi && sd->rca != rca) { if (!sd->spi && sd->rca != rca) {
@ -1208,7 +1208,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 15: /* CMD15: GO_INACTIVE_STATE */ case 15: /* CMD15: GO_INACTIVE_STATE */
if (sd->spi) if (sd->spi)
goto bad_cmd; goto bad_cmd;
switch (sd->mode) { switch (sd->mode) {
@ -1225,7 +1225,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
/* Block read commands (Classs 2) */ /* Block read commands (Classs 2) */
case 16: /* CMD16: SET_BLOCKLEN */ case 16: /* CMD16: SET_BLOCKLEN */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
if (req.arg > (1 << HWBLOCK_SHIFT)) { if (req.arg > (1 << HWBLOCK_SHIFT)) {
@ -1242,8 +1242,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 17: /* CMD17: READ_SINGLE_BLOCK */ case 17: /* CMD17: READ_SINGLE_BLOCK */
case 18: /* CMD18: READ_MULTIPLE_BLOCK */ case 18: /* CMD18: READ_MULTIPLE_BLOCK */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
@ -1287,8 +1287,8 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
/* Block write commands (Class 4) */ /* Block write commands (Class 4) */
case 24: /* CMD24: WRITE_SINGLE_BLOCK */ case 24: /* CMD24: WRITE_SINGLE_BLOCK */
case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */ case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
@ -1316,7 +1316,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 26: /* CMD26: PROGRAM_CID */ case 26: /* CMD26: PROGRAM_CID */
if (sd->spi) if (sd->spi)
goto bad_cmd; goto bad_cmd;
switch (sd->state) { switch (sd->state) {
@ -1331,7 +1331,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 27: /* CMD27: PROGRAM_CSD */ case 27: /* CMD27: PROGRAM_CSD */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->state = sd_receivingdata_state; sd->state = sd_receivingdata_state;
@ -1345,7 +1345,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
/* Write protection (Class 6) */ /* Write protection (Class 6) */
case 28: /* CMD28: SET_WRITE_PROT */ case 28: /* CMD28: SET_WRITE_PROT */
if (sd->size > SDSC_MAX_CAPACITY) { if (sd->size > SDSC_MAX_CAPACITY) {
return sd_illegal; return sd_illegal;
} }
@ -1367,7 +1367,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 29: /* CMD29: CLR_WRITE_PROT */ case 29: /* CMD29: CLR_WRITE_PROT */
if (sd->size > SDSC_MAX_CAPACITY) { if (sd->size > SDSC_MAX_CAPACITY) {
return sd_illegal; return sd_illegal;
} }
@ -1389,7 +1389,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 30: /* CMD30: SEND_WRITE_PROT */ case 30: /* CMD30: SEND_WRITE_PROT */
if (sd->size > SDSC_MAX_CAPACITY) { if (sd->size > SDSC_MAX_CAPACITY) {
return sd_illegal; return sd_illegal;
} }
@ -1413,7 +1413,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
/* Erase commands (Class 5) */ /* Erase commands (Class 5) */
case 32: /* CMD32: ERASE_WR_BLK_START */ case 32: /* CMD32: ERASE_WR_BLK_START */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->erase_start = req.arg; sd->erase_start = req.arg;
@ -1424,7 +1424,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 33: /* CMD33: ERASE_WR_BLK_END */ case 33: /* CMD33: ERASE_WR_BLK_END */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->erase_end = req.arg; sd->erase_end = req.arg;
@ -1435,7 +1435,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
} }
break; break;
case 38: /* CMD38: ERASE */ case 38: /* CMD38: ERASE */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
if (sd->csd[14] & 0x30) { if (sd->csd[14] & 0x30) {
@ -1455,7 +1455,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
break; break;
/* Lock card commands (Class 7) */ /* Lock card commands (Class 7) */
case 42: /* CMD42: LOCK_UNLOCK */ case 42: /* CMD42: LOCK_UNLOCK */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->state = sd_receivingdata_state; sd->state = sd_receivingdata_state;
@ -1478,7 +1478,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
return sd_illegal; return sd_illegal;
/* Application specific commands (Class 8) */ /* Application specific commands (Class 8) */
case 55: /* CMD55: APP_CMD */ case 55: /* CMD55: APP_CMD */
switch (sd->state) { switch (sd->state) {
case sd_ready_state: case sd_ready_state:
case sd_identification_state: case sd_identification_state:
@ -1501,7 +1501,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
sd->card_status |= APP_CMD; sd->card_status |= APP_CMD;
return sd_r1; return sd_r1;
case 56: /* CMD56: GEN_CMD */ case 56: /* CMD56: GEN_CMD */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->data_offset = 0; sd->data_offset = 0;
@ -1546,7 +1546,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
req.cmd, req.arg, sd_state_name(sd->state)); req.cmd, req.arg, sd_state_name(sd->state));
sd->card_status |= APP_CMD; sd->card_status |= APP_CMD;
switch (req.cmd) { switch (req.cmd) {
case 6: /* ACMD6: SET_BUS_WIDTH */ case 6: /* ACMD6: SET_BUS_WIDTH */
if (sd->spi) { if (sd->spi) {
goto unimplemented_spi_cmd; goto unimplemented_spi_cmd;
} }
@ -1561,7 +1561,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
} }
break; break;
case 13: /* ACMD13: SD_STATUS */ case 13: /* ACMD13: SD_STATUS */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->state = sd_sendingdata_state; sd->state = sd_sendingdata_state;
@ -1574,7 +1574,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
} }
break; break;
case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
*(uint32_t *) sd->data = sd->blk_written; *(uint32_t *) sd->data = sd->blk_written;
@ -1589,7 +1589,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
} }
break; break;
case 23: /* ACMD23: SET_WR_BLK_ERASE_COUNT */ case 23: /* ACMD23: SET_WR_BLK_ERASE_COUNT */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
return sd_r1; return sd_r1;
@ -1599,7 +1599,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
} }
break; break;
case 41: /* ACMD41: SD_APP_OP_COND */ case 41: /* ACMD41: SD_APP_OP_COND */
if (sd->spi) { if (sd->spi) {
/* SEND_OP_CMD */ /* SEND_OP_CMD */
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
@ -1641,7 +1641,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
return sd_r3; return sd_r3;
case 42: /* ACMD42: SET_CLR_CARD_DETECT */ case 42: /* ACMD42: SET_CLR_CARD_DETECT */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
/* Bringing in the 50KOhm pull-up resistor... Done. */ /* Bringing in the 50KOhm pull-up resistor... Done. */
@ -1652,7 +1652,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
} }
break; break;
case 51: /* ACMD51: SEND_SCR */ case 51: /* ACMD51: SEND_SCR */
switch (sd->state) { switch (sd->state) {
case sd_transfer_state: case sd_transfer_state:
sd->state = sd_sendingdata_state; sd->state = sd_sendingdata_state;
@ -1840,7 +1840,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
sd_acmd_name(sd->current_cmd), sd_acmd_name(sd->current_cmd),
sd->current_cmd, value); sd->current_cmd, value);
switch (sd->current_cmd) { switch (sd->current_cmd) {
case 24: /* CMD24: WRITE_SINGLE_BLOCK */ case 24: /* CMD24: WRITE_SINGLE_BLOCK */
sd->data[sd->data_offset ++] = value; sd->data[sd->data_offset ++] = value;
if (sd->data_offset >= sd->blk_len) { if (sd->data_offset >= sd->blk_len) {
/* TODO: Check CRC before committing */ /* TODO: Check CRC before committing */
@ -1853,7 +1853,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
} }
break; break;
case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */ case 25: /* CMD25: WRITE_MULTIPLE_BLOCK */
if (sd->data_offset == 0) { if (sd->data_offset == 0) {
/* Start of the block - let's check the address is valid */ /* Start of the block - let's check the address is valid */
if (!address_in_range(sd, "WRITE_MULTIPLE_BLOCK", if (!address_in_range(sd, "WRITE_MULTIPLE_BLOCK",
@ -1890,7 +1890,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
} }
break; break;
case 26: /* CMD26: PROGRAM_CID */ case 26: /* CMD26: PROGRAM_CID */
sd->data[sd->data_offset ++] = value; sd->data[sd->data_offset ++] = value;
if (sd->data_offset >= sizeof(sd->cid)) { if (sd->data_offset >= sizeof(sd->cid)) {
/* TODO: Check CRC before committing */ /* TODO: Check CRC before committing */
@ -1909,7 +1909,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
} }
break; break;
case 27: /* CMD27: PROGRAM_CSD */ case 27: /* CMD27: PROGRAM_CSD */
sd->data[sd->data_offset ++] = value; sd->data[sd->data_offset ++] = value;
if (sd->data_offset >= sizeof(sd->csd)) { if (sd->data_offset >= sizeof(sd->csd)) {
/* TODO: Check CRC before committing */ /* TODO: Check CRC before committing */
@ -1933,7 +1933,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
} }
break; break;
case 42: /* CMD42: LOCK_UNLOCK */ case 42: /* CMD42: LOCK_UNLOCK */
sd->data[sd->data_offset ++] = value; sd->data[sd->data_offset ++] = value;
if (sd->data_offset >= sd->blk_len) { if (sd->data_offset >= sd->blk_len) {
/* TODO: Check CRC before committing */ /* TODO: Check CRC before committing */
@ -1944,7 +1944,7 @@ void sd_write_byte(SDState *sd, uint8_t value)
} }
break; break;
case 56: /* CMD56: GEN_CMD */ case 56: /* CMD56: GEN_CMD */
sd->data[sd->data_offset ++] = value; sd->data[sd->data_offset ++] = value;
if (sd->data_offset >= sd->blk_len) { if (sd->data_offset >= sd->blk_len) {
APP_WRITE_BLOCK(sd->data_start, sd->data_offset); APP_WRITE_BLOCK(sd->data_start, sd->data_offset);
@ -1996,29 +1996,29 @@ uint8_t sd_read_byte(SDState *sd)
sd_acmd_name(sd->current_cmd), sd_acmd_name(sd->current_cmd),
sd->current_cmd, io_len); sd->current_cmd, io_len);
switch (sd->current_cmd) { switch (sd->current_cmd) {
case 6: /* CMD6: SWITCH_FUNCTION */ case 6: /* CMD6: SWITCH_FUNCTION */
ret = sd->data[sd->data_offset ++]; ret = sd->data[sd->data_offset ++];
if (sd->data_offset >= 64) if (sd->data_offset >= 64)
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
break; break;
case 9: /* CMD9: SEND_CSD */ case 9: /* CMD9: SEND_CSD */
case 10: /* CMD10: SEND_CID */ case 10: /* CMD10: SEND_CID */
ret = sd->data[sd->data_offset ++]; ret = sd->data[sd->data_offset ++];
if (sd->data_offset >= 16) if (sd->data_offset >= 16)
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
break; break;
case 13: /* ACMD13: SD_STATUS */ case 13: /* ACMD13: SD_STATUS */
ret = sd->sd_status[sd->data_offset ++]; ret = sd->sd_status[sd->data_offset ++];
if (sd->data_offset >= sizeof(sd->sd_status)) if (sd->data_offset >= sizeof(sd->sd_status))
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
break; break;
case 17: /* CMD17: READ_SINGLE_BLOCK */ case 17: /* CMD17: READ_SINGLE_BLOCK */
if (sd->data_offset == 0) if (sd->data_offset == 0)
BLK_READ_BLOCK(sd->data_start, io_len); BLK_READ_BLOCK(sd->data_start, io_len);
ret = sd->data[sd->data_offset ++]; ret = sd->data[sd->data_offset ++];
@ -2027,7 +2027,7 @@ uint8_t sd_read_byte(SDState *sd)
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
break; break;
case 18: /* CMD18: READ_MULTIPLE_BLOCK */ case 18: /* CMD18: READ_MULTIPLE_BLOCK */
if (sd->data_offset == 0) { if (sd->data_offset == 0) {
if (!address_in_range(sd, "READ_MULTIPLE_BLOCK", if (!address_in_range(sd, "READ_MULTIPLE_BLOCK",
sd->data_start, io_len)) { sd->data_start, io_len)) {
@ -2058,28 +2058,28 @@ uint8_t sd_read_byte(SDState *sd)
ret = sd_tuning_block_pattern[sd->data_offset++]; ret = sd_tuning_block_pattern[sd->data_offset++];
break; break;
case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */ case 22: /* ACMD22: SEND_NUM_WR_BLOCKS */
ret = sd->data[sd->data_offset ++]; ret = sd->data[sd->data_offset ++];
if (sd->data_offset >= 4) if (sd->data_offset >= 4)
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
break; break;
case 30: /* CMD30: SEND_WRITE_PROT */ case 30: /* CMD30: SEND_WRITE_PROT */
ret = sd->data[sd->data_offset ++]; ret = sd->data[sd->data_offset ++];
if (sd->data_offset >= 4) if (sd->data_offset >= 4)
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
break; break;
case 51: /* ACMD51: SEND_SCR */ case 51: /* ACMD51: SEND_SCR */
ret = sd->scr[sd->data_offset ++]; ret = sd->scr[sd->data_offset ++];
if (sd->data_offset >= sizeof(sd->scr)) if (sd->data_offset >= sizeof(sd->scr))
sd->state = sd_transfer_state; sd->state = sd_transfer_state;
break; break;
case 56: /* CMD56: GEN_CMD */ case 56: /* CMD56: GEN_CMD */
if (sd->data_offset == 0) if (sd->data_offset == 0)
APP_READ_BLOCK(sd->data_start, sd->blk_len); APP_READ_BLOCK(sd->data_start, sd->blk_len);
ret = sd->data[sd->data_offset ++]; ret = sd->data[sd->data_offset ++];

View File

@ -30,7 +30,7 @@
/*#define IB700_DEBUG 1*/ /*#define IB700_DEBUG 1*/
#ifdef IB700_DEBUG #ifdef IB700_DEBUG
#define ib700_debug(fs,...) \ #define ib700_debug(fs,...) \
fprintf(stderr,"ib700: %s: "fs,__func__,##__VA_ARGS__) fprintf(stderr,"ib700: %s: "fs,__func__,##__VA_ARGS__)
#else #else
#define ib700_debug(fs,...) #define ib700_debug(fs,...)

View File

@ -18,14 +18,14 @@ typedef struct aes_key_st AES_KEY;
#define AES_decrypt QEMU_AES_decrypt #define AES_decrypt QEMU_AES_decrypt
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key); AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key); AES_KEY *key);
void AES_encrypt(const unsigned char *in, unsigned char *out, void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key); const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out, void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key); const AES_KEY *key);
extern const uint8_t AES_sbox[256]; extern const uint8_t AES_sbox[256];
extern const uint8_t AES_isbox[256]; extern const uint8_t AES_isbox[256];

View File

@ -15,30 +15,30 @@
/* d3des.h - /* d3des.h -
* *
* Headers and defines for d3des.c * Headers and defines for d3des.c
* Graven Imagery, 1992. * Graven Imagery, 1992.
* *
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
* (GEnie : OUTER; CIS : [71755,204]) * (GEnie : OUTER; CIS : [71755,204])
*/ */
#define EN0 0 /* MODE == encrypt */ #define EN0 0 /* MODE == encrypt */
#define DE1 1 /* MODE == decrypt */ #define DE1 1 /* MODE == decrypt */
void deskey(unsigned char *, int); void deskey(unsigned char *, int);
/* hexkey[8] MODE /* hexkey[8] MODE
* Sets the internal key register according to the hexadecimal * Sets the internal key register according to the hexadecimal
* key contained in the 8 bytes of hexkey, according to the DES, * key contained in the 8 bytes of hexkey, according to the DES,
* for encryption or decryption according to MODE. * for encryption or decryption according to MODE.
*/ */
void usekey(unsigned long *); void usekey(unsigned long *);
/* cookedkey[32] /* cookedkey[32]
* Loads the internal key register with the data in cookedkey. * Loads the internal key register with the data in cookedkey.
*/ */
void des(unsigned char *, unsigned char *); void des(unsigned char *, unsigned char *);
/* from[8] to[8] /* from[8] to[8]
* Encrypts/Decrypts (according to the key currently loaded in the * Encrypts/Decrypts (according to the key currently loaded in the
* internal key register) one block of eight bytes at address 'from' * internal key register) one block of eight bytes at address 'from'
* into the block at address 'to'. They can be the same. * into the block at address 'to'. They can be the same.

View File

@ -188,20 +188,20 @@ enum bfd_architecture
#define bfd_mach_alpha_ev5 0x20 #define bfd_mach_alpha_ev5 0x20
#define bfd_mach_alpha_ev6 0x30 #define bfd_mach_alpha_ev6 0x30
bfd_arch_arm, /* Advanced Risc Machines ARM */ bfd_arch_arm, /* Advanced Risc Machines ARM */
#define bfd_mach_arm_unknown 0 #define bfd_mach_arm_unknown 0
#define bfd_mach_arm_2 1 #define bfd_mach_arm_2 1
#define bfd_mach_arm_2a 2 #define bfd_mach_arm_2a 2
#define bfd_mach_arm_3 3 #define bfd_mach_arm_3 3
#define bfd_mach_arm_3M 4 #define bfd_mach_arm_3M 4
#define bfd_mach_arm_4 5 #define bfd_mach_arm_4 5
#define bfd_mach_arm_4T 6 #define bfd_mach_arm_4T 6
#define bfd_mach_arm_5 7 #define bfd_mach_arm_5 7
#define bfd_mach_arm_5T 8 #define bfd_mach_arm_5T 8
#define bfd_mach_arm_5TE 9 #define bfd_mach_arm_5TE 9
#define bfd_mach_arm_XScale 10 #define bfd_mach_arm_XScale 10
#define bfd_mach_arm_ep9312 11 #define bfd_mach_arm_ep9312 11
#define bfd_mach_arm_iWMMXt 12 #define bfd_mach_arm_iWMMXt 12
#define bfd_mach_arm_iWMMXt2 13 #define bfd_mach_arm_iWMMXt2 13
bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_ns32k, /* National Semiconductors ns32000 */
bfd_arch_w65, /* WDC 65816 */ bfd_arch_w65, /* WDC 65816 */
bfd_arch_tic30, /* Texas Instruments TMS320C30 */ bfd_arch_tic30, /* Texas Instruments TMS320C30 */
@ -241,7 +241,7 @@ enum bfd_architecture
bfd_arch_ia64, /* HP/Intel ia64 */ bfd_arch_ia64, /* HP/Intel ia64 */
#define bfd_mach_ia64_elf64 64 #define bfd_mach_ia64_elf64 64
#define bfd_mach_ia64_elf32 32 #define bfd_mach_ia64_elf32 32
bfd_arch_nios2, /* Nios II */ bfd_arch_nios2, /* Nios II */
#define bfd_mach_nios2 0 #define bfd_mach_nios2 0
#define bfd_mach_nios2r1 1 #define bfd_mach_nios2r1 1
#define bfd_mach_nios2r2 2 #define bfd_mach_nios2r2 2
@ -269,14 +269,14 @@ typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
G_GNUC_PRINTF(2, 3); G_GNUC_PRINTF(2, 3);
enum dis_insn_type { enum dis_insn_type {
dis_noninsn, /* Not a valid instruction */ dis_noninsn, /* Not a valid instruction */
dis_nonbranch, /* Not a branch instruction */ dis_nonbranch, /* Not a branch instruction */
dis_branch, /* Unconditional branch */ dis_branch, /* Unconditional branch */
dis_condbranch, /* Conditional branch */ dis_condbranch, /* Conditional branch */
dis_jsr, /* Jump to subroutine */ dis_jsr, /* Jump to subroutine */
dis_condjsr, /* Conditional jump to subroutine */ dis_condjsr, /* Conditional jump to subroutine */
dis_dref, /* Data reference instruction */ dis_dref, /* Data reference instruction */
dis_dref2 /* Two data references in instruction */ dis_dref2 /* Two data references in instruction */
}; };
/* This struct is passed into the instruction decoding routine, /* This struct is passed into the instruction decoding routine,
@ -319,8 +319,8 @@ typedef struct disassemble_info {
The top 16 bits are reserved for public use (and are documented here). The top 16 bits are reserved for public use (and are documented here).
The bottom 16 bits are for the internal use of the disassembler. */ The bottom 16 bits are for the internal use of the disassembler. */
unsigned long flags; unsigned long flags;
#define INSN_HAS_RELOC 0x80000000 #define INSN_HAS_RELOC 0x80000000
#define INSN_ARM_BE32 0x00010000 #define INSN_ARM_BE32 0x00010000
PTR private_data; PTR private_data;
/* Function used to get bytes to disassemble. MEMADDR is the /* Function used to get bytes to disassemble. MEMADDR is the
@ -330,7 +330,7 @@ typedef struct disassemble_info {
Returns an errno value or 0 for success. */ Returns an errno value or 0 for success. */
int (*read_memory_func) int (*read_memory_func)
(bfd_vma memaddr, bfd_byte *myaddr, int length, (bfd_vma memaddr, bfd_byte *myaddr, int length,
struct disassemble_info *info); struct disassemble_info *info);
/* Function which should be called if we get an error that we can't /* Function which should be called if we get an error that we can't
recover from. STATUS is the errno value from read_memory_func and recover from. STATUS is the errno value from read_memory_func and
@ -384,14 +384,14 @@ typedef struct disassemble_info {
To determine whether this decoder supports this information, set To determine whether this decoder supports this information, set
insn_info_valid to 0, decode an instruction, then check it. */ insn_info_valid to 0, decode an instruction, then check it. */
char insn_info_valid; /* Branch info has been set. */ char insn_info_valid; /* Branch info has been set. */
char branch_delay_insns; /* How many sequential insn's will run before char branch_delay_insns; /* How many sequential insn's will run before
a branch takes effect. (0 = normal) */ a branch takes effect. (0 = normal) */
char data_size; /* Size of data reference in insn, in bytes */ char data_size; /* Size of data reference in insn, in bytes */
enum dis_insn_type insn_type; /* Type of instruction */ enum dis_insn_type insn_type; /* Type of instruction */
bfd_vma target; /* Target address of branch or dref, if known; bfd_vma target; /* Target address of branch or dref, if known;
zero if unknown. */ zero if unknown. */
bfd_vma target2; /* Second target address for dref2 */ bfd_vma target2; /* Second target address for dref2 */
/* Command line options specific to the target disassembler. */ /* Command line options specific to the target disassembler. */
char * disassembler_options; char * disassembler_options;

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
#include "hw/core/cpu.h" #include "hw/core/cpu.h"
#include "qemu/rcu.h" #include "qemu/rcu.h"
#define EXCP_INTERRUPT 0x10000 /* async interruption */ #define EXCP_INTERRUPT 0x10000 /* async interruption */
#define EXCP_HLT 0x10001 /* hlt instruction reached */ #define EXCP_HLT 0x10001 /* hlt instruction reached */
#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */

View File

@ -66,7 +66,7 @@
#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100 #define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200 #define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200
#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400 #define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400
#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */ #define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_WAKE_STATUS 0x8000 #define ACPI_BITMASK_WAKE_STATUS 0x8000
#define ACPI_BITMASK_ALL_FIXED_STATUS (\ #define ACPI_BITMASK_ALL_FIXED_STATUS (\
@ -84,7 +84,7 @@
#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100 #define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200 #define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200
#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400 #define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400
#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */ #define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_PM1_COMMON_ENABLED ( \ #define ACPI_BITMASK_PM1_COMMON_ENABLED ( \
ACPI_BITMASK_RT_CLOCK_ENABLE | \ ACPI_BITMASK_RT_CLOCK_ENABLE | \

View File

@ -1,30 +1,30 @@
static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr) static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
{ {
bswap16s(&ehdr->e_type); /* Object file type */ bswap16s(&ehdr->e_type); /* Object file type */
bswap16s(&ehdr->e_machine); /* Architecture */ bswap16s(&ehdr->e_machine); /* Architecture */
bswap32s(&ehdr->e_version); /* Object file version */ bswap32s(&ehdr->e_version); /* Object file version */
bswapSZs(&ehdr->e_entry); /* Entry point virtual address */ bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
bswapSZs(&ehdr->e_phoff); /* Program header table file offset */ bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
bswapSZs(&ehdr->e_shoff); /* Section header table file offset */ bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
bswap32s(&ehdr->e_flags); /* Processor-specific flags */ bswap32s(&ehdr->e_flags); /* Processor-specific flags */
bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
bswap16s(&ehdr->e_phnum); /* Program header table entry count */ bswap16s(&ehdr->e_phnum); /* Program header table entry count */
bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
bswap16s(&ehdr->e_shnum); /* Section header table entry count */ bswap16s(&ehdr->e_shnum); /* Section header table entry count */
bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
} }
static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr) static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
{ {
bswap32s(&phdr->p_type); /* Segment type */ bswap32s(&phdr->p_type); /* Segment type */
bswapSZs(&phdr->p_offset); /* Segment file offset */ bswapSZs(&phdr->p_offset); /* Segment file offset */
bswapSZs(&phdr->p_vaddr); /* Segment virtual address */ bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
bswapSZs(&phdr->p_paddr); /* Segment physical address */ bswapSZs(&phdr->p_paddr); /* Segment physical address */
bswapSZs(&phdr->p_filesz); /* Segment size in file */ bswapSZs(&phdr->p_filesz); /* Segment size in file */
bswapSZs(&phdr->p_memsz); /* Segment size in memory */ bswapSZs(&phdr->p_memsz); /* Segment size in memory */
bswap32s(&phdr->p_flags); /* Segment flags */ bswap32s(&phdr->p_flags); /* Segment flags */
bswapSZs(&phdr->p_align); /* Segment alignment */ bswapSZs(&phdr->p_align); /* Segment alignment */
} }
static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr) static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)

View File

@ -137,11 +137,11 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
pci_map_irq_fn map_irq); pci_map_irq_fn map_irq);
/* TODO: add this define to pci_regs.h in linux and then in qemu. */ /* TODO: add this define to pci_regs.h in linux and then in qemu. */
#define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */ #define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */
#define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */ #define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */
#define PCI_BRIDGE_CTL_SEC_DISCARD 0x200 /* Secondary discard timer */ #define PCI_BRIDGE_CTL_SEC_DISCARD 0x200 /* Secondary discard timer */
#define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */ #define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */
#define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */ #define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */
typedef struct PCIBridgeQemuCap { typedef struct PCIBridgeQemuCap {
uint8_t id; /* Standard PCI capability header field */ uint8_t id; /* Standard PCI capability header field */

View File

@ -43,22 +43,22 @@ struct PCMCIACardClass {
void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value); void (*io_write)(PCMCIACardState *card, uint32_t address, uint16_t value);
}; };
#define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */ #define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */
#define CISTPL_NO_LINK 0x14 /* No Link Tuple */ #define CISTPL_NO_LINK 0x14 /* No Link Tuple */
#define CISTPL_VERS_1 0x15 /* Level 1 Version Tuple */ #define CISTPL_VERS_1 0x15 /* Level 1 Version Tuple */
#define CISTPL_JEDEC_C 0x18 /* JEDEC ID Tuple */ #define CISTPL_JEDEC_C 0x18 /* JEDEC ID Tuple */
#define CISTPL_JEDEC_A 0x19 /* JEDEC ID Tuple */ #define CISTPL_JEDEC_A 0x19 /* JEDEC ID Tuple */
#define CISTPL_CONFIG 0x1a /* Configuration Tuple */ #define CISTPL_CONFIG 0x1a /* Configuration Tuple */
#define CISTPL_CFTABLE_ENTRY 0x1b /* 16-bit PCCard Configuration */ #define CISTPL_CFTABLE_ENTRY 0x1b /* 16-bit PCCard Configuration */
#define CISTPL_DEVICE_OC 0x1c /* Additional Device Information */ #define CISTPL_DEVICE_OC 0x1c /* Additional Device Information */
#define CISTPL_DEVICE_OA 0x1d /* Additional Device Information */ #define CISTPL_DEVICE_OA 0x1d /* Additional Device Information */
#define CISTPL_DEVICE_GEO 0x1e /* Additional Device Information */ #define CISTPL_DEVICE_GEO 0x1e /* Additional Device Information */
#define CISTPL_DEVICE_GEO_A 0x1f /* Additional Device Information */ #define CISTPL_DEVICE_GEO_A 0x1f /* Additional Device Information */
#define CISTPL_MANFID 0x20 /* Manufacture ID Tuple */ #define CISTPL_MANFID 0x20 /* Manufacture ID Tuple */
#define CISTPL_FUNCID 0x21 /* Function ID Tuple */ #define CISTPL_FUNCID 0x21 /* Function ID Tuple */
#define CISTPL_FUNCE 0x22 /* Function Extension Tuple */ #define CISTPL_FUNCE 0x22 /* Function Extension Tuple */
#define CISTPL_END 0xff /* Tuple End */ #define CISTPL_END 0xff /* Tuple End */
#define CISTPL_ENDMARK 0xff #define CISTPL_ENDMARK 0xff
/* dscm1xxxx.c */ /* dscm1xxxx.c */
PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv); PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv);

View File

@ -8,7 +8,7 @@
#include "qemu/notify.h" #include "qemu/notify.h"
#include "qom/object.h" #include "qom/object.h"
#define MAX_SCSI_DEVS 255 #define MAX_SCSI_DEVS 255
typedef struct SCSIBus SCSIBus; typedef struct SCSIBus SCSIBus;
typedef struct SCSIBusInfo SCSIBusInfo; typedef struct SCSIBusInfo SCSIBusInfo;

View File

@ -77,10 +77,10 @@ typedef enum {
typedef enum { typedef enum {
sd_none = -1, sd_none = -1,
sd_bc = 0, /* broadcast -- no response */ sd_bc = 0, /* broadcast -- no response */
sd_bcr, /* broadcast with response */ sd_bcr, /* broadcast with response */
sd_ac, /* addressed -- no data transfer */ sd_ac, /* addressed -- no data transfer */
sd_adtc, /* addressed with data transfer */ sd_adtc, /* addressed with data transfer */
} sd_cmd_type_t; } sd_cmd_type_t;
typedef struct { typedef struct {

View File

@ -29,7 +29,7 @@
* vhost-user to advertise VHOST_USER_F_PROTOCOL_FEATURES between QEMU * vhost-user to advertise VHOST_USER_F_PROTOCOL_FEATURES between QEMU
* and a vhost-user backend. * and a vhost-user backend.
*/ */
#define VIRTIO_F_BAD_FEATURE 30 #define VIRTIO_F_BAD_FEATURE 30
#define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \ #define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \
(0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \ (0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \

View File

@ -22,23 +22,23 @@
* Note that nbits should be always a compile time evaluable constant. * Note that nbits should be always a compile time evaluable constant.
* Otherwise many inlines will generate horrible code. * Otherwise many inlines will generate horrible code.
* *
* bitmap_zero(dst, nbits) *dst = 0UL * bitmap_zero(dst, nbits) *dst = 0UL
* bitmap_fill(dst, nbits) *dst = ~0UL * bitmap_fill(dst, nbits) *dst = ~0UL
* bitmap_copy(dst, src, nbits) *dst = *src * bitmap_copy(dst, src, nbits) *dst = *src
* bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2 * bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2
* bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2 * bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2
* bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2 * bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2
* bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2) * bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2)
* bitmap_complement(dst, src, nbits) *dst = ~(*src) * bitmap_complement(dst, src, nbits) *dst = ~(*src)
* bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal? * bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal?
* bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap? * bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap?
* bitmap_empty(src, nbits) Are all bits zero in *src? * bitmap_empty(src, nbits) Are all bits zero in *src?
* bitmap_full(src, nbits) Are all bits set in *src? * bitmap_full(src, nbits) Are all bits set in *src?
* bitmap_set(dst, pos, nbits) Set specified bit area * bitmap_set(dst, pos, nbits) Set specified bit area
* bitmap_set_atomic(dst, pos, nbits) Set specified bit area with atomic ops * bitmap_set_atomic(dst, pos, nbits) Set specified bit area with atomic ops
* bitmap_clear(dst, pos, nbits) Clear specified bit area * bitmap_clear(dst, pos, nbits) Clear specified bit area
* bitmap_test_and_clear_atomic(dst, pos, nbits) Test and clear area * bitmap_test_and_clear_atomic(dst, pos, nbits) Test and clear area
* bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area * bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
* bitmap_to_le(dst, src, nbits) Convert bitmap to little endian * bitmap_to_le(dst, src, nbits) Convert bitmap to little endian
* bitmap_from_le(dst, src, nbits) Convert bitmap from little endian * bitmap_from_le(dst, src, nbits) Convert bitmap from little endian
* bitmap_copy_with_src_offset(dst, src, offset, nbits) * bitmap_copy_with_src_offset(dst, src, offset, nbits)
@ -50,17 +50,17 @@
/* /*
* Also the following operations apply to bitmaps. * Also the following operations apply to bitmaps.
* *
* set_bit(bit, addr) *addr |= bit * set_bit(bit, addr) *addr |= bit
* clear_bit(bit, addr) *addr &= ~bit * clear_bit(bit, addr) *addr &= ~bit
* change_bit(bit, addr) *addr ^= bit * change_bit(bit, addr) *addr ^= bit
* test_bit(bit, addr) Is bit set in *addr? * test_bit(bit, addr) Is bit set in *addr?
* test_and_set_bit(bit, addr) Set bit and return old value * test_and_set_bit(bit, addr) Set bit and return old value
* test_and_clear_bit(bit, addr) Clear bit and return old value * test_and_clear_bit(bit, addr) Clear bit and return old value
* test_and_change_bit(bit, addr) Change bit and return old value * test_and_change_bit(bit, addr) Change bit and return old value
* find_first_zero_bit(addr, nbits) Position first zero bit in *addr * find_first_zero_bit(addr, nbits) Position first zero bit in *addr
* find_first_bit(addr, nbits) Position first set bit in *addr * find_first_bit(addr, nbits) Position first set bit in *addr
* find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit * find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit
* find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
*/ */
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))

View File

@ -33,8 +33,8 @@
#ifndef glue #ifndef glue
#define xglue(x, y) x ## y #define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y) #define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s) #define stringify(s) tostring(s)
#define tostring(s) #s #define tostring(s) #s
#endif #endif
#ifndef likely #ifndef likely

View File

@ -237,7 +237,7 @@ extern "C" {
* supports QEMU_ERROR, this will be reported at compile time; otherwise * supports QEMU_ERROR, this will be reported at compile time; otherwise
* this will be reported at link time due to the missing symbol. * this will be reported at link time due to the missing symbol.
*/ */
extern G_NORETURN G_NORETURN extern
void QEMU_ERROR("code path is reachable") void QEMU_ERROR("code path is reachable")
qemu_build_not_reached_always(void); qemu_build_not_reached_always(void);
#if defined(__OPTIMIZE__) && !defined(__NO_INLINE__) #if defined(__OPTIMIZE__) && !defined(__NO_INLINE__)

View File

@ -59,16 +59,16 @@
* as described in RFC 2396 but separated for further processing. * as described in RFC 2396 but separated for further processing.
*/ */
typedef struct URI { typedef struct URI {
char *scheme; /* the URI scheme */ char *scheme; /* the URI scheme */
char *opaque; /* opaque part */ char *opaque; /* opaque part */
char *authority; /* the authority part */ char *authority; /* the authority part */
char *server; /* the server part */ char *server; /* the server part */
char *user; /* the user part */ char *user; /* the user part */
int port; /* the port number */ int port; /* the port number */
char *path; /* the path string */ char *path; /* the path string */
char *fragment; /* the fragment identifier */ char *fragment; /* the fragment identifier */
int cleanup; /* parsing potentially unclean URI */ int cleanup; /* parsing potentially unclean URI */
char *query; /* the query string (as it appears in the URI) */ char *query; /* the query string (as it appears in the URI) */
} URI; } URI;
URI *uri_new(void); URI *uri_new(void);
@ -84,16 +84,16 @@ void uri_free(URI *uri);
/* Single web service query parameter 'name=value'. */ /* Single web service query parameter 'name=value'. */
typedef struct QueryParam { typedef struct QueryParam {
char *name; /* Name (unescaped). */ char *name; /* Name (unescaped). */
char *value; /* Value (unescaped). */ char *value; /* Value (unescaped). */
int ignore; /* Ignore this field in qparam_get_query */ int ignore; /* Ignore this field in qparam_get_query */
} QueryParam; } QueryParam;
/* Set of parameters. */ /* Set of parameters. */
typedef struct QueryParams { typedef struct QueryParams {
int n; /* number of parameters used */ int n; /* number of parameters used */
int alloc; /* allocated space */ int alloc; /* allocated space */
QueryParam *p; /* array of parameters */ QueryParam *p; /* array of parameters */
} QueryParams; } QueryParams;
struct QueryParams *query_params_new (int init_alloc); struct QueryParams *query_params_new (int init_alloc);

View File

@ -34,8 +34,8 @@
#define FW_CFG_SETUP_SIZE 0x17 #define FW_CFG_SETUP_SIZE 0x17
#define FW_CFG_SETUP_DATA 0x18 #define FW_CFG_SETUP_DATA 0x18
#define BIOS_CFG_IOPORT_CFG 0x510 #define BIOS_CFG_IOPORT_CFG 0x510
#define BIOS_CFG_IOPORT_DATA 0x511 #define BIOS_CFG_IOPORT_DATA 0x511
#define FW_CFG_DMA_CTL_ERROR 0x01 #define FW_CFG_DMA_CTL_ERROR 0x01
#define FW_CFG_DMA_CTL_READ 0x02 #define FW_CFG_DMA_CTL_READ 0x02
@ -49,65 +49,65 @@
#define BIOS_CFG_DMA_ADDR_LOW 0x518 #define BIOS_CFG_DMA_ADDR_LOW 0x518
/* Break the translation block flow so -d cpu shows us values */ /* Break the translation block flow so -d cpu shows us values */
#define DEBUG_HERE \ #define DEBUG_HERE \
jmp 1f; \ jmp 1f; \
1: 1:
/* /*
* Read a variable from the fw_cfg device. * Read a variable from the fw_cfg device.
* Clobbers: %edx * Clobbers: %edx
* Out: %eax * Out: %eax
*/ */
.macro read_fw VAR .macro read_fw VAR
mov $\VAR, %ax mov $\VAR, %ax
mov $BIOS_CFG_IOPORT_CFG, %dx mov $BIOS_CFG_IOPORT_CFG, %dx
outw %ax, (%dx) outw %ax, (%dx)
mov $BIOS_CFG_IOPORT_DATA, %dx mov $BIOS_CFG_IOPORT_DATA, %dx
inb (%dx), %al inb (%dx), %al
shl $8, %eax shl $8, %eax
inb (%dx), %al inb (%dx), %al
shl $8, %eax shl $8, %eax
inb (%dx), %al inb (%dx), %al
shl $8, %eax shl $8, %eax
inb (%dx), %al inb (%dx), %al
bswap %eax bswap %eax
.endm .endm
/* /*
* Read data from the fw_cfg device using DMA. * Read data from the fw_cfg device using DMA.
* Clobbers: %edx, %eax, ADDR, SIZE, memory[%esp-16] to memory[%esp] * Clobbers: %edx, %eax, ADDR, SIZE, memory[%esp-16] to memory[%esp]
*/ */
.macro read_fw_dma VAR, SIZE, ADDR .macro read_fw_dma VAR, SIZE, ADDR
/* Address */ /* Address */
bswapl \ADDR bswapl \ADDR
pushl \ADDR pushl \ADDR
/* We only support 32 bit target addresses */ /* We only support 32 bit target addresses */
xorl %eax, %eax xorl %eax, %eax
pushl %eax pushl %eax
mov $BIOS_CFG_DMA_ADDR_HIGH, %dx mov $BIOS_CFG_DMA_ADDR_HIGH, %dx
outl %eax, (%dx) outl %eax, (%dx)
/* Size */ /* Size */
bswapl \SIZE bswapl \SIZE
pushl \SIZE pushl \SIZE
/* Control */ /* Control */
movl $(\VAR << 16) | (FW_CFG_DMA_CTL_READ | FW_CFG_DMA_CTL_SELECT), %eax movl $(\VAR << 16) | (FW_CFG_DMA_CTL_READ | FW_CFG_DMA_CTL_SELECT), %eax
bswapl %eax bswapl %eax
pushl %eax pushl %eax
movl %esp, %eax /* Address of the struct we generated */ movl %esp, %eax /* Address of the struct we generated */
bswapl %eax bswapl %eax
mov $BIOS_CFG_DMA_ADDR_LOW, %dx mov $BIOS_CFG_DMA_ADDR_LOW, %dx
outl %eax, (%dx) /* Initiate DMA */ outl %eax, (%dx) /* Initiate DMA */
1: mov (%esp), %eax /* Wait for completion */ 1: mov (%esp), %eax /* Wait for completion */
bswapl %eax bswapl %eax
testl $~FW_CFG_DMA_CTL_ERROR, %eax testl $~FW_CFG_DMA_CTL_ERROR, %eax
jnz 1b jnz 1b
addl $16, %esp addl $16, %esp
.endm .endm
@ -115,116 +115,116 @@
* Read a blob from the fw_cfg device using DMA * Read a blob from the fw_cfg device using DMA
* Requires _ADDR, _SIZE and _DATA values for the parameter. * Requires _ADDR, _SIZE and _DATA values for the parameter.
* *
* Clobbers: %eax, %edx, %es, %ecx, %edi and adresses %esp-20 to %esp * Clobbers: %eax, %edx, %es, %ecx, %edi and adresses %esp-20 to %esp
*/ */
#ifdef USE_FW_CFG_DMA #ifdef USE_FW_CFG_DMA
#define read_fw_blob_dma(var) \ #define read_fw_blob_dma(var) \
read_fw var ## _SIZE; \ read_fw var ## _SIZE; \
mov %eax, %ecx; \ mov %eax, %ecx; \
read_fw var ## _ADDR; \ read_fw var ## _ADDR; \
mov %eax, %edi ;\ mov %eax, %edi ; \
read_fw_dma var ## _DATA, %ecx, %edi read_fw_dma var ## _DATA, %ecx, %edi
#else #else
#define read_fw_blob_dma(var) read_fw_blob(var) #define read_fw_blob_dma(var) read_fw_blob(var)
#endif #endif
#define read_fw_blob_pre(var) \ #define read_fw_blob_pre(var) \
read_fw var ## _SIZE; \ read_fw var ## _SIZE; \
mov %eax, %ecx; \ mov %eax, %ecx; \
mov $var ## _DATA, %ax; \ mov $var ## _DATA, %ax; \
mov $BIOS_CFG_IOPORT_CFG, %edx; \ mov $BIOS_CFG_IOPORT_CFG, %edx; \
outw %ax, (%dx); \ outw %ax, (%dx); \
mov $BIOS_CFG_IOPORT_DATA, %dx; \ mov $BIOS_CFG_IOPORT_DATA, %dx; \
cld cld
/* /*
* Read a blob from the fw_cfg device. * Read a blob from the fw_cfg device.
* Requires _ADDR, _SIZE and _DATA values for the parameter. * Requires _ADDR, _SIZE and _DATA values for the parameter.
* *
* Clobbers: %eax, %edx, %es, %ecx, %edi * Clobbers: %eax, %edx, %es, %ecx, %edi
*/ */
#define read_fw_blob(var) \ #define read_fw_blob(var) \
read_fw var ## _ADDR; \ read_fw var ## _ADDR; \
mov %eax, %edi; \ mov %eax, %edi; \
read_fw_blob_pre(var); \ read_fw_blob_pre(var); \
/* old as(1) doesn't like this insn so emit the bytes instead: \ /* old as(1) doesn't like this insn so emit the bytes instead: \
rep insb (%dx), %es:(%edi); \ rep insb (%dx), %es:(%edi); \
*/ \ */ \
.dc.b 0xf3,0x6c .dc.b 0xf3,0x6c
/* /*
* Read a blob from the fw_cfg device in forced addr32 mode. * Read a blob from the fw_cfg device in forced addr32 mode.
* Requires _ADDR, _SIZE and _DATA values for the parameter. * Requires _ADDR, _SIZE and _DATA values for the parameter.
* *
* Clobbers: %eax, %edx, %es, %ecx, %edi * Clobbers: %eax, %edx, %es, %ecx, %edi
*/ */
#define read_fw_blob_addr32(var) \ #define read_fw_blob_addr32(var) \
read_fw var ## _ADDR; \ read_fw var ## _ADDR; \
mov %eax, %edi; \ mov %eax, %edi; \
read_fw_blob_pre(var); \ read_fw_blob_pre(var); \
/* old as(1) doesn't like this insn so emit the bytes instead: \ /* old as(1) doesn't like this insn so emit the bytes instead: \
addr32 rep insb (%dx), %es:(%edi); \ addr32 rep insb (%dx), %es:(%edi); \
*/ \ */ \
.dc.b 0x67,0xf3,0x6c .dc.b 0x67,0xf3,0x6c
/* /*
* Read a blob from the fw_cfg device in forced addr32 mode, address is in %edi. * Read a blob from the fw_cfg device in forced addr32 mode, address is in %edi.
* Requires _SIZE and _DATA values for the parameter. * Requires _SIZE and _DATA values for the parameter.
* *
* Clobbers: %eax, %edx, %edi, %es, %ecx * Clobbers: %eax, %edx, %edi, %es, %ecx
*/ */
#define read_fw_blob_addr32_edi(var) \ #define read_fw_blob_addr32_edi(var) \
read_fw_blob_pre(var); \ read_fw_blob_pre(var); \
/* old as(1) doesn't like this insn so emit the bytes instead: \ /* old as(1) doesn't like this insn so emit the bytes instead: \
addr32 rep insb (%dx), %es:(%edi); \ addr32 rep insb (%dx), %es:(%edi); \
*/ \ */ \
.dc.b 0x67,0xf3,0x6c .dc.b 0x67,0xf3,0x6c
#define OPTION_ROM_START \ #define OPTION_ROM_START \
.code16; \ .code16; \
.text; \ .text; \
.global _start; \ .global _start; \
_start:; \ _start:; \
.short 0xaa55; \ .short 0xaa55; \
.byte (_end - _start) / 512; .byte (_end - _start) / 512;
#define BOOT_ROM_START \ #define BOOT_ROM_START \
OPTION_ROM_START \ OPTION_ROM_START \
lret; \ lret; \
.org 0x18; \ .org 0x18; \
.short 0; \ .short 0; \
.short _pnph; \ .short _pnph; \
_pnph: \ _pnph: \
.ascii "$PnP"; \ .ascii "$PnP"; \
.byte 0x01; \ .byte 0x01; \
.byte ( _pnph_len / 16 ); \ .byte ( _pnph_len / 16 ); \
.short 0x0000; \ .short 0x0000; \
.byte 0x00; \ .byte 0x00; \
.byte 0x00; \ .byte 0x00; \
.long 0x00000000; \ .long 0x00000000; \
.short _manufacturer; \ .short _manufacturer; \
.short _product; \ .short _product; \
.long 0x00000000; \ .long 0x00000000; \
.short 0x0000; \ .short 0x0000; \
.short 0x0000; \ .short 0x0000; \
.short _bev; \ .short _bev; \
.short 0x0000; \ .short 0x0000; \
.short 0x0000; \ .short 0x0000; \
.equ _pnph_len, . - _pnph; \ .equ _pnph_len, . - _pnph; \
_bev:; \ _bev:; \
/* DS = CS */ \ /* DS = CS */ \
movw %cs, %ax; \ movw %cs, %ax; \
movw %ax, %ds; movw %ax, %ds;
#define OPTION_ROM_END \ #define OPTION_ROM_END \
.byte 0; \ .byte 0; \
.align 512, 0; \ .align 512, 0; \
_end: _end:
#define BOOT_ROM_END \ #define BOOT_ROM_END \
_manufacturer:; \ _manufacturer:; \
.asciz "QEMU"; \ .asciz "QEMU"; \
_product:; \ _product:; \
.asciz BOOT_ROM_PRODUCT; \ .asciz BOOT_ROM_PRODUCT; \
OPTION_ROM_END OPTION_ROM_END

View File

@ -3175,7 +3175,7 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
* cache->xlat and the end of the section. * cache->xlat and the end of the section.
*/ */
diff = int128_sub(cache->mrs.size, diff = int128_sub(cache->mrs.size,
int128_make64(cache->xlat - cache->mrs.offset_within_region)); int128_make64(cache->xlat - cache->mrs.offset_within_region));
l = int128_get64(int128_min(diff, int128_make64(l))); l = int128_get64(int128_min(diff, int128_make64(l)));
mr = cache->mrs.mr; mr = cache->mrs.mr;

View File

@ -41,6 +41,26 @@
#define CR0_RESET 0xE0UL #define CR0_RESET 0xE0UL
#define CR14_RESET 0xC2000000UL; #define CR14_RESET 0xC2000000UL;
#ifndef CONFIG_USER_ONLY
static bool is_early_exception_psw(uint64_t mask, uint64_t addr)
{
if (mask & PSW_MASK_RESERVED) {
return true;
}
switch (mask & (PSW_MASK_32 | PSW_MASK_64)) {
case 0:
return addr & ~0xffffffULL;
case PSW_MASK_32:
return addr & ~0x7fffffffULL;
case PSW_MASK_32 | PSW_MASK_64:
return false;
default: /* PSW_MASK_64 */
return true;
}
}
#endif
void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr) void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
{ {
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
@ -57,6 +77,12 @@ void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
env->cc_op = (mask >> 44) & 3; env->cc_op = (mask >> 44) & 3;
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
if (is_early_exception_psw(mask, addr)) {
env->int_pgm_ilen = 0;
trigger_pgm_exception(env, PGM_SPECIFICATION);
return;
}
if ((old_mask ^ mask) & PSW_MASK_PER) { if ((old_mask ^ mask) & PSW_MASK_PER) {
s390_cpu_recompute_watchpoints(env_cpu(env)); s390_cpu_recompute_watchpoints(env_cpu(env));
} }

View File

@ -29,6 +29,7 @@
#include "cpu_models.h" #include "cpu_models.h"
#include "exec/cpu-defs.h" #include "exec/cpu-defs.h"
#include "qemu/cpu-float.h" #include "qemu/cpu-float.h"
#include "tcg/tcg_s390x.h"
#define ELF_MACHINE_UNAME "S390X" #define ELF_MACHINE_UNAME "S390X"
@ -87,6 +88,7 @@ struct CPUArchState {
uint64_t cc_vr; uint64_t cc_vr;
uint64_t ex_value; uint64_t ex_value;
uint64_t ex_target;
uint64_t __excp_addr; uint64_t __excp_addr;
uint64_t psa; uint64_t psa;
@ -292,6 +294,7 @@ extern const VMStateDescription vmstate_s390_cpu;
#define PSW_MASK_32 0x0000000080000000ULL #define PSW_MASK_32 0x0000000080000000ULL
#define PSW_MASK_SHORT_ADDR 0x000000007fffffffULL #define PSW_MASK_SHORT_ADDR 0x000000007fffffffULL
#define PSW_MASK_SHORT_CTRL 0xffffffff80000000ULL #define PSW_MASK_SHORT_CTRL 0xffffffff80000000ULL
#define PSW_MASK_RESERVED 0xb80800fe7fffffffULL
#undef PSW_ASC_PRIMARY #undef PSW_ASC_PRIMARY
#undef PSW_ASC_ACCREG #undef PSW_ASC_ACCREG
@ -381,6 +384,14 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc, static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags) target_ulong *cs_base, uint32_t *flags)
{ {
if (env->psw.addr & 1) {
/*
* Instructions must be at even addresses.
* This needs to be checked before address translation.
*/
env->int_pgm_ilen = 2; /* see s390_cpu_tlb_fill() */
tcg_s390_program_interrupt(env, PGM_SPECIFICATION, 0);
}
*pc = env->psw.addr; *pc = env->psw.addr;
*cs_base = env->ex_value; *cs_base = env->ex_value;
*flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW; *flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW;

View File

@ -85,8 +85,8 @@ void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
/* /*
* Unaligned accesses are only diagnosed with MO_ALIGN. At the moment, * Unaligned accesses are only diagnosed with MO_ALIGN. At the moment,
* this is only for the atomic operations, for which we want to raise a * this is only for the atomic and relative long operations, for which we want
* specification exception. * to raise a specification exception.
*/ */
static G_NORETURN static G_NORETURN
void do_unaligned_access(CPUState *cs, uintptr_t retaddr) void do_unaligned_access(CPUState *cs, uintptr_t retaddr)
@ -212,7 +212,8 @@ static void do_program_interrupt(CPUS390XState *env)
LowCore *lowcore; LowCore *lowcore;
int ilen = env->int_pgm_ilen; int ilen = env->int_pgm_ilen;
assert(ilen == 2 || ilen == 4 || ilen == 6); assert((env->int_pgm_code == PGM_SPECIFICATION && ilen == 0) ||
ilen == 2 || ilen == 4 || ilen == 6);
switch (env->int_pgm_code) { switch (env->int_pgm_code) {
case PGM_PER: case PGM_PER:

View File

@ -410,12 +410,12 @@
/* LOAD */ /* LOAD */
C(0x1800, LR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, 0) C(0x1800, LR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, 0)
C(0x5800, L, RX_a, Z, 0, a2, new, r1_32, ld32s, 0) D(0x5800, L, RX_a, Z, 0, a2, new, r1_32, ld32s, 0, 0)
C(0xe358, LY, RXY_a, LD, 0, a2, new, r1_32, ld32s, 0) D(0xe358, LY, RXY_a, LD, 0, a2, new, r1_32, ld32s, 0, 0)
C(0xb904, LGR, RRE, Z, 0, r2_o, 0, r1, mov2, 0) C(0xb904, LGR, RRE, Z, 0, r2_o, 0, r1, mov2, 0)
C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0) C(0xb914, LGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, 0)
C(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0) D(0xe304, LG, RXY_a, Z, 0, a2, r1, 0, ld64, 0, 0)
C(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0) D(0xe314, LGF, RXY_a, Z, 0, a2, r1, 0, ld32s, 0, 0)
F(0x2800, LDR, RR_a, Z, 0, f2, 0, f1, mov2, 0, IF_AFP1 | IF_AFP2) F(0x2800, LDR, RR_a, Z, 0, f2, 0, f1, mov2, 0, IF_AFP1 | IF_AFP2)
F(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0, IF_AFP1) F(0x6800, LD, RX_a, Z, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
F(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0, IF_AFP1) F(0xed65, LDY, RXY_a, LD, 0, m2_64, 0, f1, mov2, 0, IF_AFP1)
@ -426,9 +426,9 @@
/* LOAD IMMEDIATE */ /* LOAD IMMEDIATE */
C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0) C(0xc001, LGFI, RIL_a, EI, 0, i2, 0, r1, mov2, 0)
/* LOAD RELATIVE LONG */ /* LOAD RELATIVE LONG */
C(0xc40d, LRL, RIL_b, GIE, 0, ri2, new, r1_32, ld32s, 0) D(0xc40d, LRL, RIL_b, GIE, 0, ri2, new, r1_32, ld32s, 0, MO_ALIGN)
C(0xc408, LGRL, RIL_b, GIE, 0, ri2, r1, 0, ld64, 0) D(0xc408, LGRL, RIL_b, GIE, 0, ri2, r1, 0, ld64, 0, MO_ALIGN)
C(0xc40c, LGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32s, 0) D(0xc40c, LGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32s, 0, MO_ALIGN)
/* LOAD ADDRESS */ /* LOAD ADDRESS */
C(0x4100, LA, RX_a, Z, 0, a2, 0, r1, mov2, 0) C(0x4100, LA, RX_a, Z, 0, a2, 0, r1, mov2, 0)
C(0xe371, LAY, RXY_a, LD, 0, a2, 0, r1, mov2, 0) C(0xe371, LAY, RXY_a, LD, 0, a2, 0, r1, mov2, 0)
@ -456,9 +456,9 @@
C(0x1200, LTR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, s32) C(0x1200, LTR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, s32)
C(0xb902, LTGR, RRE, Z, 0, r2_o, 0, r1, mov2, s64) C(0xb902, LTGR, RRE, Z, 0, r2_o, 0, r1, mov2, s64)
C(0xb912, LTGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, s64) C(0xb912, LTGFR, RRE, Z, 0, r2_32s, 0, r1, mov2, s64)
C(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64) D(0xe312, LT, RXY_a, EI, 0, a2, new, r1_32, ld32s, s64, 0)
C(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64) D(0xe302, LTG, RXY_a, EI, 0, a2, r1, 0, ld64, s64, 0)
C(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64) D(0xe332, LTGF, RXY_a, GIE, 0, a2, r1, 0, ld32s, s64, 0)
F(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32, IF_BFP) F(0xb302, LTEBR, RRE, Z, 0, e2, 0, cond_e1e2, mov2, f32, IF_BFP)
F(0xb312, LTDBR, RRE, Z, 0, f2, 0, f1, mov2, f64, IF_BFP) F(0xb312, LTDBR, RRE, Z, 0, f2, 0, f1, mov2, f64, IF_BFP)
F(0xb342, LTXBR, RRE, Z, x2h, x2l, 0, x1_P, movx, f128, IF_BFP) F(0xb342, LTXBR, RRE, Z, x2h, x2l, 0, x1_P, movx, f128, IF_BFP)
@ -502,16 +502,16 @@
C(0xc405, LHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16s, 0) C(0xc405, LHRL, RIL_b, GIE, 0, ri2, new, r1_32, ld16s, 0)
C(0xc404, LGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16s, 0) C(0xc404, LGHRL, RIL_b, GIE, 0, ri2, r1, 0, ld16s, 0)
/* LOAD HIGH */ /* LOAD HIGH */
C(0xe3ca, LFH, RXY_a, HW, 0, a2, new, r1_32h, ld32u, 0) D(0xe3ca, LFH, RXY_a, HW, 0, a2, new, r1_32h, ld32u, 0, 0)
/* LOAG HIGH AND TRAP */ /* LOAG HIGH AND TRAP */
C(0xe3c8, LFHAT, RXY_a, LAT, 0, m2_32u, r1, 0, lfhat, 0) C(0xe3c8, LFHAT, RXY_a, LAT, 0, m2_32u, r1, 0, lfhat, 0)
/* LOAD LOGICAL */ /* LOAD LOGICAL */
C(0xb916, LLGFR, RRE, Z, 0, r2_32u, 0, r1, mov2, 0) C(0xb916, LLGFR, RRE, Z, 0, r2_32u, 0, r1, mov2, 0)
C(0xe316, LLGF, RXY_a, Z, 0, a2, r1, 0, ld32u, 0) D(0xe316, LLGF, RXY_a, Z, 0, a2, r1, 0, ld32u, 0, 0)
/* LOAD LOGICAL AND TRAP */ /* LOAD LOGICAL AND TRAP */
C(0xe39d, LLGFAT, RXY_a, LAT, 0, a2, r1, 0, llgfat, 0) C(0xe39d, LLGFAT, RXY_a, LAT, 0, a2, r1, 0, llgfat, 0)
/* LOAD LOGICAL RELATIVE LONG */ /* LOAD LOGICAL RELATIVE LONG */
C(0xc40e, LLGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0) D(0xc40e, LLGFRL, RIL_b, GIE, 0, ri2, r1, 0, ld32u, 0, MO_ALIGN)
/* LOAD LOGICAL CHARACTER */ /* LOAD LOGICAL CHARACTER */
C(0xb994, LLCR, RRE, EI, 0, r2_8u, 0, r1_32, mov2, 0) C(0xb994, LLCR, RRE, EI, 0, r2_8u, 0, r1_32, mov2, 0)
C(0xb984, LLGCR, RRE, EI, 0, r2_8u, 0, r1, mov2, 0) C(0xb984, LLGCR, RRE, EI, 0, r2_8u, 0, r1, mov2, 0)
@ -840,16 +840,16 @@
F(0xed15, SQDB, RXE, Z, 0, m2_64, new, f1, sqdb, 0, IF_BFP) F(0xed15, SQDB, RXE, Z, 0, m2_64, new, f1, sqdb, 0, IF_BFP)
/* STORE */ /* STORE */
C(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0) D(0x5000, ST, RX_a, Z, r1_o, a2, 0, 0, st32, 0, 0)
C(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0) D(0xe350, STY, RXY_a, LD, r1_o, a2, 0, 0, st32, 0, 0)
C(0xe324, STG, RXY_a, Z, r1_o, a2, 0, 0, st64, 0) D(0xe324, STG, RXY_a, Z, r1_o, a2, 0, 0, st64, 0, 0)
F(0x6000, STD, RX_a, Z, f1, a2, 0, 0, st64, 0, IF_AFP1) E(0x6000, STD, RX_a, Z, f1, a2, 0, 0, st64, 0, 0, IF_AFP1)
F(0xed67, STDY, RXY_a, LD, f1, a2, 0, 0, st64, 0, IF_AFP1) E(0xed67, STDY, RXY_a, LD, f1, a2, 0, 0, st64, 0, 0, IF_AFP1)
F(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0, IF_AFP1) E(0x7000, STE, RX_a, Z, e1, a2, 0, 0, st32, 0, 0, IF_AFP1)
F(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0, IF_AFP1) E(0xed66, STEY, RXY_a, LD, e1, a2, 0, 0, st32, 0, 0, IF_AFP1)
/* STORE RELATIVE LONG */ /* STORE RELATIVE LONG */
C(0xc40f, STRL, RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0) D(0xc40f, STRL, RIL_b, GIE, r1_o, ri2, 0, 0, st32, 0, MO_ALIGN)
C(0xc40b, STGRL, RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0) D(0xc40b, STGRL, RIL_b, GIE, r1_o, ri2, 0, 0, st64, 0, MO_ALIGN)
/* STORE CHARACTER */ /* STORE CHARACTER */
C(0x4200, STC, RX_a, Z, r1_o, a2, 0, 0, st8, 0) C(0x4200, STC, RX_a, Z, r1_o, a2, 0, 0, st8, 0)
C(0xe372, STCY, RXY_a, LD, r1_o, a2, 0, 0, st8, 0) C(0xe372, STCY, RXY_a, LD, r1_o, a2, 0, 0, st8, 0)
@ -867,7 +867,7 @@
/* STORE HALFWORD RELATIVE LONG */ /* STORE HALFWORD RELATIVE LONG */
C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0) C(0xc407, STHRL, RIL_b, GIE, r1_o, ri2, 0, 0, st16, 0)
/* STORE HIGH */ /* STORE HIGH */
C(0xe3cb, STFH, RXY_a, HW, r1_sr32, a2, 0, 0, st32, 0) D(0xe3cb, STFH, RXY_a, HW, r1_sr32, a2, 0, 0, st32, 0, 0)
/* STORE ON CONDITION */ /* STORE ON CONDITION */
D(0xebf3, STOC, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 0) D(0xebf3, STOC, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 0)
D(0xebe3, STOCG, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 1) D(0xebe3, STOCG, RSY_b, LOC, 0, 0, 0, 0, soc, 0, 1)

View File

@ -149,7 +149,6 @@ static inline int s390_probe_access(CPUArchState *env, target_ulong addr,
nonfault, phost, ra); nonfault, phost, ra);
if (unlikely(flags & TLB_INVALID_MASK)) { if (unlikely(flags & TLB_INVALID_MASK)) {
assert(!nonfault);
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
/* Address is in TEC in system mode; see s390_cpu_record_sigsegv. */ /* Address is in TEC in system mode; see s390_cpu_record_sigsegv. */
env->__excp_addr = addr & TARGET_PAGE_MASK; env->__excp_addr = addr & TARGET_PAGE_MASK;
@ -2468,8 +2467,16 @@ void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
*/ */
void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr) void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr)
{ {
uint64_t insn = cpu_lduw_code(env, addr); uint64_t insn;
uint8_t opc = insn >> 8; uint8_t opc;
/* EXECUTE targets must be at even addresses. */
if (addr & 1) {
tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
}
insn = cpu_lduw_code(env, addr);
opc = insn >> 8;
/* Or in the contents of R1[56:63]. */ /* Or in the contents of R1[56:63]. */
insn |= r1 & 0xff; insn |= r1 & 0xff;
@ -2530,6 +2537,7 @@ void HELPER(ex)(CPUS390XState *env, uint32_t ilen, uint64_t r1, uint64_t addr)
that ex_value is non-zero, which flags that we are in a state that ex_value is non-zero, which flags that we are in a state
that requires such execution. */ that requires such execution. */
env->ex_value = insn | ilen; env->ex_value = insn | ilen;
env->ex_target = addr;
} }
uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src, uint32_t HELPER(mvcos)(CPUS390XState *env, uint64_t dest, uint64_t src,

View File

@ -2770,19 +2770,22 @@ static DisasJumpType op_ld16u(DisasContext *s, DisasOps *o)
static DisasJumpType op_ld32s(DisasContext *s, DisasOps *o) static DisasJumpType op_ld32s(DisasContext *s, DisasOps *o)
{ {
tcg_gen_qemu_ld32s(o->out, o->in2, get_mem_index(s)); tcg_gen_qemu_ld_tl(o->out, o->in2, get_mem_index(s),
MO_TESL | s->insn->data);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_ld32u(DisasContext *s, DisasOps *o) static DisasJumpType op_ld32u(DisasContext *s, DisasOps *o)
{ {
tcg_gen_qemu_ld32u(o->out, o->in2, get_mem_index(s)); tcg_gen_qemu_ld_tl(o->out, o->in2, get_mem_index(s),
MO_TEUL | s->insn->data);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_ld64(DisasContext *s, DisasOps *o) static DisasJumpType op_ld64(DisasContext *s, DisasOps *o)
{ {
tcg_gen_qemu_ld64(o->out, o->in2, get_mem_index(s)); tcg_gen_qemu_ld_i64(o->out, o->in2, get_mem_index(s),
MO_TEUQ | s->insn->data);
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -2910,19 +2913,21 @@ static DisasJumpType op_lpp(DisasContext *s, DisasOps *o)
static DisasJumpType op_lpsw(DisasContext *s, DisasOps *o) static DisasJumpType op_lpsw(DisasContext *s, DisasOps *o)
{ {
TCGv_i64 t1, t2; TCGv_i64 mask, addr;
per_breaking_event(s); per_breaking_event(s);
t1 = tcg_temp_new_i64(); /*
t2 = tcg_temp_new_i64(); * Convert the short PSW into the normal PSW, similar to what
tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), * s390_cpu_load_normal() does.
MO_TEUL | MO_ALIGN_8); */
tcg_gen_addi_i64(o->in2, o->in2, 4); mask = tcg_temp_new_i64();
tcg_gen_qemu_ld32u(t2, o->in2, get_mem_index(s)); addr = tcg_temp_new_i64();
/* Convert the 32-bit PSW_MASK into the 64-bit PSW_MASK. */ tcg_gen_qemu_ld_i64(mask, o->in2, get_mem_index(s), MO_TEUQ | MO_ALIGN_8);
tcg_gen_shli_i64(t1, t1, 32); tcg_gen_andi_i64(addr, mask, PSW_MASK_SHORT_ADDR);
gen_helper_load_psw(cpu_env, t1, t2); tcg_gen_andi_i64(mask, mask, PSW_MASK_SHORT_CTRL);
tcg_gen_xori_i64(mask, mask, PSW_MASK_SHORTPSW);
gen_helper_load_psw(cpu_env, mask, addr);
return DISAS_NORETURN; return DISAS_NORETURN;
} }
@ -3695,11 +3700,15 @@ static DisasJumpType op_rosbg(DisasContext *s, DisasOps *o)
int i3 = get_field(s, i3); int i3 = get_field(s, i3);
int i4 = get_field(s, i4); int i4 = get_field(s, i4);
int i5 = get_field(s, i5); int i5 = get_field(s, i5);
TCGv_i64 orig_out;
uint64_t mask; uint64_t mask;
/* If this is a test-only form, arrange to discard the result. */ /* If this is a test-only form, arrange to discard the result. */
if (i3 & 0x80) { if (i3 & 0x80) {
tcg_debug_assert(o->out != NULL);
orig_out = o->out;
o->out = tcg_temp_new_i64(); o->out = tcg_temp_new_i64();
tcg_gen_mov_i64(o->out, orig_out);
} }
i3 &= 63; i3 &= 63;
@ -4066,9 +4075,23 @@ static DisasJumpType op_sske(DisasContext *s, DisasOps *o)
return DISAS_NEXT; return DISAS_NEXT;
} }
static void gen_check_psw_mask(DisasContext *s)
{
TCGv_i64 reserved = tcg_temp_new_i64();
TCGLabel *ok = gen_new_label();
tcg_gen_andi_i64(reserved, psw_mask, PSW_MASK_RESERVED);
tcg_gen_brcondi_i64(TCG_COND_EQ, reserved, 0, ok);
gen_program_exception(s, PGM_SPECIFICATION);
gen_set_label(ok);
}
static DisasJumpType op_ssm(DisasContext *s, DisasOps *o) static DisasJumpType op_ssm(DisasContext *s, DisasOps *o)
{ {
tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8); tcg_gen_deposit_i64(psw_mask, psw_mask, o->in2, 56, 8);
gen_check_psw_mask(s);
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
s->exit_to_mainloop = true; s->exit_to_mainloop = true;
return DISAS_TOO_MANY; return DISAS_TOO_MANY;
@ -4329,6 +4352,8 @@ static DisasJumpType op_stnosm(DisasContext *s, DisasOps *o)
tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56); tcg_gen_ori_i64(psw_mask, psw_mask, i2 << 56);
} }
gen_check_psw_mask(s);
/* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */ /* Exit to main loop to reevaluate s390_cpu_exec_interrupt. */
s->exit_to_mainloop = true; s->exit_to_mainloop = true;
return DISAS_TOO_MANY; return DISAS_TOO_MANY;
@ -4367,13 +4392,15 @@ static DisasJumpType op_st16(DisasContext *s, DisasOps *o)
static DisasJumpType op_st32(DisasContext *s, DisasOps *o) static DisasJumpType op_st32(DisasContext *s, DisasOps *o)
{ {
tcg_gen_qemu_st32(o->in1, o->in2, get_mem_index(s)); tcg_gen_qemu_st_tl(o->in1, o->in2, get_mem_index(s),
MO_TEUL | s->insn->data);
return DISAS_NEXT; return DISAS_NEXT;
} }
static DisasJumpType op_st64(DisasContext *s, DisasOps *o) static DisasJumpType op_st64(DisasContext *s, DisasOps *o)
{ {
tcg_gen_qemu_st64(o->in1, o->in2, get_mem_index(s)); tcg_gen_qemu_st_i64(o->in1, o->in2, get_mem_index(s),
MO_TEUQ | s->insn->data);
return DISAS_NEXT; return DISAS_NEXT;
} }
@ -5747,7 +5774,18 @@ static void in2_a2(DisasContext *s, DisasOps *o)
static TCGv gen_ri2(DisasContext *s) static TCGv gen_ri2(DisasContext *s)
{ {
return tcg_constant_i64(s->base.pc_next + (int64_t)get_field(s, i2) * 2); int64_t delta = (int64_t)get_field(s, i2) * 2;
TCGv ri2;
if (unlikely(s->ex_value)) {
ri2 = tcg_temp_new_i64();
tcg_gen_ld_i64(ri2, cpu_env, offsetof(CPUS390XState, ex_target));
tcg_gen_addi_i64(ri2, ri2, delta);
} else {
ri2 = tcg_constant_i64(s->base.pc_next + delta);
}
return ri2;
} }
static void in2_ri2(DisasContext *s, DisasOps *o) static void in2_ri2(DisasContext *s, DisasOps *o)
@ -5855,21 +5893,24 @@ static void in2_mri2_16u(DisasContext *s, DisasOps *o)
static void in2_mri2_32s(DisasContext *s, DisasOps *o) static void in2_mri2_32s(DisasContext *s, DisasOps *o)
{ {
o->in2 = tcg_temp_new_i64(); o->in2 = tcg_temp_new_i64();
tcg_gen_qemu_ld32s(o->in2, gen_ri2(s), get_mem_index(s)); tcg_gen_qemu_ld_tl(o->in2, gen_ri2(s), get_mem_index(s),
MO_TESL | MO_ALIGN);
} }
#define SPEC_in2_mri2_32s 0 #define SPEC_in2_mri2_32s 0
static void in2_mri2_32u(DisasContext *s, DisasOps *o) static void in2_mri2_32u(DisasContext *s, DisasOps *o)
{ {
o->in2 = tcg_temp_new_i64(); o->in2 = tcg_temp_new_i64();
tcg_gen_qemu_ld32u(o->in2, gen_ri2(s), get_mem_index(s)); tcg_gen_qemu_ld_tl(o->in2, gen_ri2(s), get_mem_index(s),
MO_TEUL | MO_ALIGN);
} }
#define SPEC_in2_mri2_32u 0 #define SPEC_in2_mri2_32u 0
static void in2_mri2_64(DisasContext *s, DisasOps *o) static void in2_mri2_64(DisasContext *s, DisasOps *o)
{ {
o->in2 = tcg_temp_new_i64(); o->in2 = tcg_temp_new_i64();
tcg_gen_qemu_ld64(o->in2, gen_ri2(s), get_mem_index(s)); tcg_gen_qemu_ld_i64(o->in2, gen_ri2(s), get_mem_index(s),
MO_TEUQ | MO_ALIGN);
} }
#define SPEC_in2_mri2_64 0 #define SPEC_in2_mri2_64 0

View File

@ -1,11 +1,25 @@
S390X_SRC=$(SRC_PATH)/tests/tcg/s390x S390X_SRC=$(SRC_PATH)/tests/tcg/s390x
VPATH+=$(S390X_SRC) VPATH+=$(S390X_SRC)
QEMU_OPTS=-action panic=exit-failure -kernel QEMU_OPTS=-action panic=exit-failure -kernel
LINK_SCRIPT=$(S390X_SRC)/softmmu.ld
LDFLAGS=-nostdlib -static -Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none
%: %.S %.o: %.S
$(CC) -march=z13 -m64 -nostdlib -static -Wl,-Ttext=0 \ $(CC) -march=z13 -m64 -c $< -o $@
-Wl,--build-id=none $< -o $@
%: %.o $(LINK_SCRIPT)
$(CC) $< -o $@ $(LDFLAGS)
TESTS += unaligned-lowcore TESTS += unaligned-lowcore
TESTS += bal TESTS += bal
TESTS += sam TESTS += sam
TESTS += lpsw
TESTS += lpswe-early
TESTS += ssm-early
TESTS += stosm-early
TESTS += exrl-ssm-early
include $(S390X_SRC)/pgm-specification.mak
$(PGM_SPECIFICATION_TESTS): pgm-specification-softmmu.o
$(PGM_SPECIFICATION_TESTS): LDFLAGS+=pgm-specification-softmmu.o
TESTS += $(PGM_SPECIFICATION_TESTS)

View File

@ -2,6 +2,9 @@ S390X_SRC=$(SRC_PATH)/tests/tcg/s390x
VPATH+=$(S390X_SRC) VPATH+=$(S390X_SRC)
CFLAGS+=-march=zEC12 -m64 CFLAGS+=-march=zEC12 -m64
%.o: %.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@
config-cc.mak: Makefile config-cc.mak: Makefile
$(quiet-@)( \ $(quiet-@)( \
$(call cc-option,-march=z14, CROSS_CC_HAS_Z14); \ $(call cc-option,-march=z14, CROSS_CC_HAS_Z14); \
@ -29,10 +32,19 @@ TESTS+=clst
TESTS+=long-double TESTS+=long-double
TESTS+=cdsg TESTS+=cdsg
TESTS+=chrl TESTS+=chrl
TESTS+=rxsbg
TESTS+=ex-relative-long
cdsg: CFLAGS+=-pthread cdsg: CFLAGS+=-pthread
cdsg: LDFLAGS+=-pthread cdsg: LDFLAGS+=-pthread
rxsbg: CFLAGS+=-O2
include $(S390X_SRC)/pgm-specification.mak
$(PGM_SPECIFICATION_TESTS): pgm-specification-user.o
$(PGM_SPECIFICATION_TESTS): LDFLAGS+=pgm-specification-user.o
TESTS += $(PGM_SPECIFICATION_TESTS)
Z13_TESTS=vistr Z13_TESTS=vistr
$(Z13_TESTS): CFLAGS+=-march=z13 -O2 $(Z13_TESTS): CFLAGS+=-march=z13 -O2
TESTS+=$(Z13_TESTS) TESTS+=$(Z13_TESTS)

16
tests/tcg/s390x/br-odd.S Normal file
View File

@ -0,0 +1,16 @@
/*
* Test BRanching to a non-mapped odd address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
lgrl %r1,odd_addr
br %r1
.align 8
odd_addr:
.quad 0xDDDDDDDDDDDDDDDD
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,0xDDDDDDDDDDDDDDDD

View File

@ -0,0 +1,16 @@
/*
* Test CGRL with a non-doubleword aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
cgrl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.long 0
unaligned:
.quad 0

View File

@ -0,0 +1,16 @@
/*
* Test CLRL with a non-word aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
clrl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.short 0
unaligned:
.long 0

View File

@ -0,0 +1,16 @@
/*
* Test CRL with a non-word aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
crl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.short 0
unaligned:
.long 0

17
tests/tcg/s390x/ex-odd.S Normal file
View File

@ -0,0 +1,17 @@
/*
* Test EXECUTing a non-mapped odd address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
lgrl %r1,odd_addr
fail:
ex 0,0(%r1)
.align 8
odd_addr:
.quad 0xDDDDDDDDDDDDDDDD
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,fail

View File

@ -0,0 +1,156 @@
/* Check EXECUTE with relative long instructions as targets. */
#include <stdlib.h>
#include <stdio.h>
struct test {
const char *name;
long (*func)(long reg, long *cc);
long exp_reg;
long exp_mem;
long exp_cc;
};
/*
* Each test sets the MEM_IDXth element of the mem array to MEM and uses a
* single relative long instruction on it. The other elements remain zero.
* This is in order to prevent stumbling upon MEM in random memory in case
* there is an off-by-a-small-value bug.
*
* Note that while gcc supports the ZL constraint for relative long operands,
* clang doesn't, so the assembly code accesses mem[MEM_IDX] using MEM_ASM.
*/
static long mem[0x1000];
#define MEM_IDX 0x800
#define MEM_ASM "mem+0x800*8"
/* Initial %r2 value. */
#define REG 0x1234567887654321
/* Initial mem[MEM_IDX] value. */
#define MEM 0xfedcba9889abcdef
/* Initial cc value. */
#define CC 0
/* Relative long instructions and their expected effects. */
#define FOR_EACH_INSN(F) \
F(cgfrl, REG, MEM, 2) \
F(cghrl, REG, MEM, 2) \
F(cgrl, REG, MEM, 2) \
F(chrl, REG, MEM, 1) \
F(clgfrl, REG, MEM, 2) \
F(clghrl, REG, MEM, 2) \
F(clgrl, REG, MEM, 1) \
F(clhrl, REG, MEM, 2) \
F(clrl, REG, MEM, 1) \
F(crl, REG, MEM, 1) \
F(larl, (long)&mem[MEM_IDX], MEM, CC) \
F(lgfrl, 0xfffffffffedcba98, MEM, CC) \
F(lghrl, 0xfffffffffffffedc, MEM, CC) \
F(lgrl, MEM, MEM, CC) \
F(lhrl, 0x12345678fffffedc, MEM, CC) \
F(llghrl, 0x000000000000fedc, MEM, CC) \
F(llhrl, 0x123456780000fedc, MEM, CC) \
F(lrl, 0x12345678fedcba98, MEM, CC) \
F(stgrl, REG, REG, CC) \
F(sthrl, REG, 0x4321ba9889abcdef, CC) \
F(strl, REG, 0x8765432189abcdef, CC)
/* Test functions. */
#define DEFINE_EX_TEST(insn, exp_reg, exp_mem, exp_cc) \
static long test_ex_ ## insn(long reg, long *cc) \
{ \
register long r2 asm("r2"); \
char mask = 0x20; /* make target use %r2 */ \
long pm, target; \
\
r2 = reg; \
asm("larl %[target],0f\n" \
"cr %%r0,%%r0\n" /* initial cc */ \
"ex %[mask],0(%[target])\n" \
"jg 1f\n" \
"0: " #insn " %%r0," MEM_ASM "\n" \
"1: ipm %[pm]\n" \
: [target] "=&a" (target), [r2] "+r" (r2), [pm] "=r" (pm) \
: [mask] "a" (mask) \
: "cc", "memory"); \
reg = r2; \
*cc = (pm >> 28) & 3; \
\
return reg; \
}
#define DEFINE_EXRL_TEST(insn, exp_reg, exp_mem, exp_cc) \
static long test_exrl_ ## insn(long reg, long *cc) \
{ \
register long r2 asm("r2"); \
char mask = 0x20; /* make target use %r2 */ \
long pm; \
\
r2 = reg; \
asm("cr %%r0,%%r0\n" /* initial cc */ \
"exrl %[mask],0f\n" \
"jg 1f\n" \
"0: " #insn " %%r0," MEM_ASM "\n" \
"1: ipm %[pm]\n" \
: [r2] "+r" (r2), [pm] "=r" (pm) \
: [mask] "a" (mask) \
: "cc", "memory"); \
reg = r2; \
*cc = (pm >> 28) & 3; \
\
return reg; \
}
FOR_EACH_INSN(DEFINE_EX_TEST)
FOR_EACH_INSN(DEFINE_EXRL_TEST)
/* Test definitions. */
#define REGISTER_EX_EXRL_TEST(ex_insn, insn, _exp_reg, _exp_mem, _exp_cc) \
{ \
.name = #ex_insn " " #insn, \
.func = test_ ## ex_insn ## _ ## insn, \
.exp_reg = (_exp_reg), \
.exp_mem = (_exp_mem), \
.exp_cc = (_exp_cc), \
},
#define REGISTER_EX_TEST(insn, exp_reg, exp_mem, exp_cc) \
REGISTER_EX_EXRL_TEST(ex, insn, exp_reg, exp_mem, exp_cc)
#define REGISTER_EXRL_TEST(insn, exp_reg, exp_mem, exp_cc) \
REGISTER_EX_EXRL_TEST(exrl, insn, exp_reg, exp_mem, exp_cc)
static const struct test tests[] = {
FOR_EACH_INSN(REGISTER_EX_TEST)
FOR_EACH_INSN(REGISTER_EXRL_TEST)
};
/* Loop over all tests and run them. */
int main(void)
{
const struct test *test;
int ret = EXIT_SUCCESS;
long reg, cc;
size_t i;
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
test = &tests[i];
mem[MEM_IDX] = MEM;
cc = -1;
reg = test->func(REG, &cc);
#define ASSERT_EQ(expected, actual) do { \
if (expected != actual) { \
fprintf(stderr, "%s: " #expected " (0x%lx) != " #actual " (0x%lx)\n", \
test->name, expected, actual); \
ret = EXIT_FAILURE; \
} \
} while (0)
ASSERT_EQ(test->exp_reg, reg);
ASSERT_EQ(test->exp_mem, mem[MEM_IDX]);
ASSERT_EQ(test->exp_cc, cc);
#undef ASSERT_EQ
}
return ret;
}

View File

@ -0,0 +1,43 @@
/*
* Test early exception recognition using EXRL + SSM.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.org 0x8d
ilc:
.org 0x8e
program_interruption_code:
.org 0x150
program_old_psw:
.org 0x1D0 /* program new PSW */
.quad 0,pgm
.org 0x200 /* lowcore padding */
.globl _start
_start:
exrl %r0,ssm
expected_pswa:
j failure
ssm:
ssm ssm_op
pgm:
chhsi program_interruption_code,0x6 /* specification exception? */
jne failure
cli ilc,6 /* ilc for EXRL? */
jne failure
clc program_old_psw(16),expected_old_psw /* correct old PSW? */
jne failure
lpswe success_psw
failure:
lpswe failure_psw
ssm_op:
.byte 0x08 /* bit 4 set */
.align 8
expected_old_psw:
.quad 0x0800000180000000,expected_pswa /* bit 2 set */
success_psw:
.quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
failure_psw:
.quad 0x2000000000000,0 /* disabled wait */

View File

@ -0,0 +1,16 @@
/*
* Test LGRL from a non-doubleword aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
lgrl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.long 0
unaligned:
.quad 0

View File

@ -0,0 +1,16 @@
/*
* Test LLGFRL from a non-word aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
llgfrl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.short 0
unaligned:
.long 0

36
tests/tcg/s390x/lpsw.S Normal file
View File

@ -0,0 +1,36 @@
/*
* Test the LPSW instruction.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.org 0x140
svc_old_psw:
.org 0x1c0 /* supervisor call new PSW */
.quad 0x80000000,svc /* 31-bit mode */
.org 0x200 /* lowcore padding */
.globl _start
_start:
lpsw short_psw
lpsw_target:
svc 0
expected_pswa:
j failure
svc:
clc svc_old_psw(16),expected_psw /* correct full PSW? */
jne failure
lpswe success_psw
failure:
lpswe failure_psw
.align 8
short_psw:
.long 0x90001,0x80000000+lpsw_target /* problem state,
64-bit mode */
expected_psw:
.quad 0x1000180000000,expected_pswa /* corresponds to short_psw */
success_psw:
.quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
failure_psw:
.quad 0x2000000000000,0 /* disabled wait */

View File

@ -0,0 +1,38 @@
/*
* Test early exception recognition using LPSWE.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.org 0x8d
ilc:
.org 0x8e
program_interruption_code:
.org 0x150
program_old_psw:
.org 0x1D0 /* program new PSW */
.quad 0,pgm
.org 0x200 /* lowcore padding */
.globl _start
_start:
lpswe bad_psw
j failure
pgm:
chhsi program_interruption_code,0x6 /* specification exception? */
jne failure
cli ilc,0 /* ilc zero? */
jne failure
clc program_old_psw(16),bad_psw /* correct old PSW? */
jne failure
lpswe success_psw
failure:
lpswe failure_psw
.align 8
bad_psw:
.quad 0x8000000000000000,0xfedcba9876543210 /* bit 0 set */
success_psw:
.quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
failure_psw:
.quad 0x2000000000000,0 /* disabled wait */

View File

@ -0,0 +1,18 @@
/*
* Test LPSWE from a non-doubleword aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
larl %r1,unaligned
fail:
lpswe 0(%r1)
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,fail
.long 0
unaligned:
.quad 0

View File

@ -0,0 +1,16 @@
/*
* Test LRL from a non-word aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
lrl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.short 0
unaligned:
.long 0

View File

@ -0,0 +1,40 @@
/*
* Common softmmu code for specification exception testing.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.section .head
.org 0x8d
ilc:
.org 0x8e
program_interruption_code:
.org 0x150
program_old_psw:
.org 0x1D0 /* program new PSW */
.quad 0x180000000,pgm /* 64-bit mode */
.org 0x200 /* lowcore padding */
.globl _start
_start:
lpswe test_psw
pgm:
chhsi program_interruption_code,0x6 /* PGM_SPECIFICATION? */
jne failure
lg %r0,expected_old_psw+8 /* ilc adjustment */
llgc %r1,ilc
agr %r0,%r1
stg %r0,expected_old_psw+8
clc expected_old_psw(16),program_old_psw /* correct location? */
jne failure
lpswe success_psw
failure:
lpswe failure_psw
.align 8
test_psw:
.quad 0x180000000,test /* 64-bit mode */
success_psw:
.quad 0x2000180000000,0xfff /* see is_special_wait_psw() */
failure_psw:
.quad 0x2000180000000,0 /* disabled wait */

View File

@ -0,0 +1,37 @@
/*
* Common user code for specification exception testing.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <assert.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern void test(void);
extern long expected_old_psw[2];
static void handle_sigill(int sig, siginfo_t *info, void *ucontext)
{
if ((long)info->si_addr != expected_old_psw[1]) {
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
int main(void)
{
struct sigaction act;
int err;
memset(&act, 0, sizeof(act));
act.sa_sigaction = handle_sigill;
act.sa_flags = SA_SIGINFO;
err = sigaction(SIGILL, &act, NULL);
assert(err == 0);
test();
return EXIT_FAILURE;
}

View File

@ -0,0 +1,15 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# List of specification exception tests.
# Shared between the softmmu and the user makefiles.
PGM_SPECIFICATION_TESTS = \
br-odd \
cgrl-unaligned \
clrl-unaligned \
crl-unaligned \
ex-odd \
lgrl-unaligned \
llgfrl-unaligned \
lpswe-unaligned \
lrl-unaligned \
stgrl-unaligned \
strl-unaligned

46
tests/tcg/s390x/rxsbg.c Normal file
View File

@ -0,0 +1,46 @@
/*
* Test the RXSBG instruction.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <assert.h>
#include <stdlib.h>
static inline __attribute__((__always_inline__)) void
rxsbg(unsigned long *r1, unsigned long r2, int i3, int i4, int i5, int *cc)
{
asm("rxsbg %[r1],%[r2],%[i3],%[i4],%[i5]\n"
"ipm %[cc]"
: [r1] "+r" (*r1), [cc] "=r" (*cc)
: [r2] "r" (r2) , [i3] "i" (i3) , [i4] "i" (i4) , [i5] "i" (i5)
: "cc");
*cc = (*cc >> 28) & 3;
}
void test_cc0(void)
{
unsigned long r1 = 6;
int cc;
rxsbg(&r1, 3, 61 | 0x80, 62, 1, &cc);
assert(r1 == 6);
assert(cc == 0);
}
void test_cc1(void)
{
unsigned long r1 = 2;
int cc;
rxsbg(&r1, 3, 61 | 0x80, 62, 1, &cc);
assert(r1 == 2);
assert(cc == 1);
}
int main(void)
{
test_cc0();
test_cc1();
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,20 @@
/*
* Linker script for the softmmu test kernels.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
ENTRY(_start)
SECTIONS {
. = 0;
.text : {
*(.head)
*(.text)
}
/DISCARD/ : {
*(*)
}
}

View File

@ -0,0 +1,41 @@
/*
* Test early exception recognition using SSM.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.org 0x8d
ilc:
.org 0x8e
program_interruption_code:
.org 0x150
program_old_psw:
.org 0x1D0 /* program new PSW */
.quad 0,pgm
.org 0x200 /* lowcore padding */
.globl _start
_start:
ssm ssm_op
expected_pswa:
j failure
pgm:
chhsi program_interruption_code,0x6 /* specification exception? */
jne failure
cli ilc,4 /* ilc for SSM? */
jne failure
clc program_old_psw(16),expected_old_psw /* correct old PSW? */
jne failure
lpswe success_psw
failure:
lpswe failure_psw
ssm_op:
.byte 0x20 /* bit 2 set */
.align 8
expected_old_psw:
.quad 0x2000000180000000,expected_pswa /* bit 2 set */
success_psw:
.quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
failure_psw:
.quad 0x2000000000000,0 /* disabled wait */

View File

@ -0,0 +1,16 @@
/*
* Test STGRL to a non-doubleword aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
stgrl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.long 0
unaligned:
.quad 0

View File

@ -0,0 +1,41 @@
/*
* Test early exception recognition using STOSM.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.org 0x8d
ilc:
.org 0x8e
program_interruption_code:
.org 0x150
program_old_psw:
.org 0x1D0 /* program new PSW */
.quad 0,pgm
.org 0x200 /* lowcore padding */
.globl _start
_start:
stosm ssm_op,0x10 /* bit 3 set */
expected_pswa:
j failure
pgm:
chhsi program_interruption_code,0x6 /* specification exception? */
jne failure
cli ilc,4 /* ilc for STOSM? */
jne failure
clc program_old_psw(16),expected_old_psw /* correct old PSW? */
jne failure
lpswe success_psw
failure:
lpswe failure_psw
ssm_op:
.byte 0
.align 8
expected_old_psw:
.quad 0x1000000180000000,expected_pswa /* bit 3 set */
success_psw:
.quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
failure_psw:
.quad 0x2000000000000,0 /* disabled wait */

View File

@ -0,0 +1,16 @@
/*
* Test STRL to a non-word aligned address.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.globl test
test:
strl %r1,unaligned
.align 8
.globl expected_old_psw
expected_old_psw:
.quad 0x180000000,test
.short 0
unaligned:
.long 0

View File

@ -531,6 +531,13 @@ int main(int argc, char **argv)
g_test_add_func("/blockjob/cancel/standby", test_cancel_standby); g_test_add_func("/blockjob/cancel/standby", test_cancel_standby);
g_test_add_func("/blockjob/cancel/pending", test_cancel_pending); g_test_add_func("/blockjob/cancel/pending", test_cancel_pending);
g_test_add_func("/blockjob/cancel/concluded", test_cancel_concluded); g_test_add_func("/blockjob/cancel/concluded", test_cancel_concluded);
g_test_add_func("/blockjob/complete_in_standby", test_complete_in_standby);
/*
* This test is flaky and sometimes fails in CI and otherwise:
* don't run unless user opts in via environment variable.
*/
if (getenv("QEMU_TEST_FLAKY_TESTS")) {
g_test_add_func("/blockjob/complete_in_standby", test_complete_in_standby);
}
return g_test_run(); return g_test_run();
} }

View File

@ -151,7 +151,7 @@ static QSLIST_HEAD(, list_element) Q_list_head;
#define TEST_NAME "qslist" #define TEST_NAME "qslist"
#define TEST_LIST_REMOVE_RCU(el, f) \ #define TEST_LIST_REMOVE_RCU(el, f) \
QSLIST_REMOVE_RCU(&Q_list_head, el, list_element, f) QSLIST_REMOVE_RCU(&Q_list_head, el, list_element, f)
#define TEST_LIST_INSERT_AFTER_RCU(list_el, el, f) \ #define TEST_LIST_INSERT_AFTER_RCU(list_el, el, f) \
QSLIST_INSERT_AFTER_RCU(&Q_list_head, list_el, el, f) QSLIST_INSERT_AFTER_RCU(&Q_list_head, list_el, el, f)

View File

@ -71,8 +71,8 @@ unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
found_first: found_first:
tmp &= (~0UL >> (BITS_PER_LONG - size)); tmp &= (~0UL >> (BITS_PER_LONG - size));
if (tmp == 0UL) { /* Are any bits set? */ if (tmp == 0UL) { /* Are any bits set? */
return result + size; /* Nope. */ return result + size; /* Nope. */
} }
found_middle: found_middle:
return result + ctzl(tmp); return result + ctzl(tmp);
@ -120,8 +120,8 @@ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
found_first: found_first:
tmp |= ~0UL << size; tmp |= ~0UL << size;
if (tmp == ~0UL) { /* Are any bits zero? */ if (tmp == ~0UL) { /* Are any bits zero? */
return result + size; /* Nope. */ return result + size; /* Nope. */
} }
found_middle: found_middle:
return result + ctzl(~tmp); return result + ctzl(~tmp);

View File

@ -3,13 +3,13 @@
#include "qemu/envlist.h" #include "qemu/envlist.h"
struct envlist_entry { struct envlist_entry {
const char *ev_var; /* actual env value */ const char *ev_var; /* actual env value */
QLIST_ENTRY(envlist_entry) ev_link; QLIST_ENTRY(envlist_entry) ev_link;
}; };
struct envlist { struct envlist {
QLIST_HEAD(, envlist_entry) el_entries; /* actual entries */ QLIST_HEAD(, envlist_entry) el_entries; /* actual entries */
size_t el_count; /* number of entries */ size_t el_count; /* number of entries */
}; };
static int envlist_parse(envlist_t *envlist, static int envlist_parse(envlist_t *envlist,
@ -21,14 +21,14 @@ static int envlist_parse(envlist_t *envlist,
envlist_t * envlist_t *
envlist_create(void) envlist_create(void)
{ {
envlist_t *envlist; envlist_t *envlist;
envlist = g_malloc(sizeof(*envlist)); envlist = g_malloc(sizeof(*envlist));
QLIST_INIT(&envlist->el_entries); QLIST_INIT(&envlist->el_entries);
envlist->el_count = 0; envlist->el_count = 0;
return (envlist); return (envlist);
} }
/* /*
@ -37,18 +37,18 @@ envlist_create(void)
void void
envlist_free(envlist_t *envlist) envlist_free(envlist_t *envlist)
{ {
struct envlist_entry *entry; struct envlist_entry *entry;
assert(envlist != NULL); assert(envlist != NULL);
while (envlist->el_entries.lh_first != NULL) { while (envlist->el_entries.lh_first != NULL) {
entry = envlist->el_entries.lh_first; entry = envlist->el_entries.lh_first;
QLIST_REMOVE(entry, ev_link); QLIST_REMOVE(entry, ev_link);
g_free((char *)entry->ev_var); g_free((char *)entry->ev_var);
g_free(entry); g_free(entry);
} }
g_free(envlist); g_free(envlist);
} }
/* /*
@ -65,7 +65,7 @@ envlist_free(envlist_t *envlist)
int int
envlist_parse_set(envlist_t *envlist, const char *env) envlist_parse_set(envlist_t *envlist, const char *env)
{ {
return (envlist_parse(envlist, env, &envlist_setenv)); return (envlist_parse(envlist, env, &envlist_setenv));
} }
/* /*
@ -77,7 +77,7 @@ envlist_parse_set(envlist_t *envlist, const char *env)
int int
envlist_parse_unset(envlist_t *envlist, const char *env) envlist_parse_unset(envlist_t *envlist, const char *env)
{ {
return (envlist_parse(envlist, env, &envlist_unsetenv)); return (envlist_parse(envlist, env, &envlist_unsetenv));
} }
/* /*
@ -90,15 +90,15 @@ static int
envlist_parse(envlist_t *envlist, const char *env, envlist_parse(envlist_t *envlist, const char *env,
int (*callback)(envlist_t *, const char *)) int (*callback)(envlist_t *, const char *))
{ {
char *tmpenv, *envvar; char *tmpenv, *envvar;
char *envsave = NULL; char *envsave = NULL;
int ret = 0; int ret = 0;
assert(callback != NULL); assert(callback != NULL);
if ((envlist == NULL) || (env == NULL)) if ((envlist == NULL) || (env == NULL))
return (EINVAL); return (EINVAL);
tmpenv = g_strdup(env); tmpenv = g_strdup(env);
envsave = tmpenv; envsave = tmpenv;
do { do {
@ -109,7 +109,7 @@ envlist_parse(envlist_t *envlist, const char *env,
if ((*callback)(envlist, tmpenv) != 0) { if ((*callback)(envlist, tmpenv) != 0) {
ret = errno; ret = errno;
break; break;
} }
tmpenv = envvar + 1; tmpenv = envvar + 1;
} while (envvar != NULL); } while (envvar != NULL);
@ -126,42 +126,42 @@ envlist_parse(envlist_t *envlist, const char *env,
int int
envlist_setenv(envlist_t *envlist, const char *env) envlist_setenv(envlist_t *envlist, const char *env)
{ {
struct envlist_entry *entry = NULL; struct envlist_entry *entry = NULL;
const char *eq_sign; const char *eq_sign;
size_t envname_len; size_t envname_len;
if ((envlist == NULL) || (env == NULL)) if ((envlist == NULL) || (env == NULL))
return (EINVAL); return (EINVAL);
/* find out first equals sign in given env */ /* find out first equals sign in given env */
if ((eq_sign = strchr(env, '=')) == NULL) if ((eq_sign = strchr(env, '=')) == NULL)
return (EINVAL); return (EINVAL);
envname_len = eq_sign - env + 1; envname_len = eq_sign - env + 1;
/* /*
* If there already exists variable with given name * If there already exists variable with given name
* we remove and release it before allocating a whole * we remove and release it before allocating a whole
* new entry. * new entry.
*/ */
for (entry = envlist->el_entries.lh_first; entry != NULL; for (entry = envlist->el_entries.lh_first; entry != NULL;
entry = entry->ev_link.le_next) { entry = entry->ev_link.le_next) {
if (strncmp(entry->ev_var, env, envname_len) == 0) if (strncmp(entry->ev_var, env, envname_len) == 0)
break; break;
} }
if (entry != NULL) { if (entry != NULL) {
QLIST_REMOVE(entry, ev_link); QLIST_REMOVE(entry, ev_link);
g_free((char *)entry->ev_var); g_free((char *)entry->ev_var);
g_free(entry); g_free(entry);
} else { } else {
envlist->el_count++; envlist->el_count++;
} }
entry = g_malloc(sizeof(*entry)); entry = g_malloc(sizeof(*entry));
entry->ev_var = g_strdup(env); entry->ev_var = g_strdup(env);
QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link); QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
return (0); return (0);
} }
/* /*
@ -171,34 +171,34 @@ envlist_setenv(envlist_t *envlist, const char *env)
int int
envlist_unsetenv(envlist_t *envlist, const char *env) envlist_unsetenv(envlist_t *envlist, const char *env)
{ {
struct envlist_entry *entry; struct envlist_entry *entry;
size_t envname_len; size_t envname_len;
if ((envlist == NULL) || (env == NULL)) if ((envlist == NULL) || (env == NULL))
return (EINVAL); return (EINVAL);
/* env is not allowed to contain '=' */ /* env is not allowed to contain '=' */
if (strchr(env, '=') != NULL) if (strchr(env, '=') != NULL)
return (EINVAL); return (EINVAL);
/* /*
* Find out the requested entry and remove * Find out the requested entry and remove
* it from the list. * it from the list.
*/ */
envname_len = strlen(env); envname_len = strlen(env);
for (entry = envlist->el_entries.lh_first; entry != NULL; for (entry = envlist->el_entries.lh_first; entry != NULL;
entry = entry->ev_link.le_next) { entry = entry->ev_link.le_next) {
if (strncmp(entry->ev_var, env, envname_len) == 0) if (strncmp(entry->ev_var, env, envname_len) == 0)
break; break;
} }
if (entry != NULL) { if (entry != NULL) {
QLIST_REMOVE(entry, ev_link); QLIST_REMOVE(entry, ev_link);
g_free((char *)entry->ev_var); g_free((char *)entry->ev_var);
g_free(entry); g_free(entry);
envlist->el_count--; envlist->el_count--;
} }
return (0); return (0);
} }
/* /*
@ -214,19 +214,19 @@ envlist_unsetenv(envlist_t *envlist, const char *env)
char ** char **
envlist_to_environ(const envlist_t *envlist, size_t *count) envlist_to_environ(const envlist_t *envlist, size_t *count)
{ {
struct envlist_entry *entry; struct envlist_entry *entry;
char **env, **penv; char **env, **penv;
penv = env = g_new(char *, envlist->el_count + 1); penv = env = g_new(char *, envlist->el_count + 1);
for (entry = envlist->el_entries.lh_first; entry != NULL; for (entry = envlist->el_entries.lh_first; entry != NULL;
entry = entry->ev_link.le_next) { entry = entry->ev_link.le_next) {
*(penv++) = g_strdup(entry->ev_var); *(penv++) = g_strdup(entry->ev_var);
} }
*penv = NULL; /* NULL terminate the list */ *penv = NULL; /* NULL terminate the list */
if (count != NULL) if (count != NULL)
*count = envlist->el_count; *count = envlist->el_count;
return (env); return (env);
} }