* 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:
commit
4c6f44644d
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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. */
|
||||||
|
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
150
hw/rtc/m48t59.c
150
hw/rtc/m48t59.c
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
184
hw/sd/sd.c
184
hw/sd/sd.c
@ -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 ++];
|
||||||
|
@ -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,...)
|
||||||
|
@ -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];
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
1790
include/elf.h
1790
include/elf.h
File diff suppressed because it is too large
Load Diff
@ -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) */
|
||||||
|
@ -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 | \
|
||||||
|
@ -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)
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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) | \
|
||||||
|
@ -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)))
|
||||||
|
@ -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
|
||||||
|
@ -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__)
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
16
tests/tcg/s390x/br-odd.S
Normal 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
|
16
tests/tcg/s390x/cgrl-unaligned.S
Normal file
16
tests/tcg/s390x/cgrl-unaligned.S
Normal 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
|
16
tests/tcg/s390x/clrl-unaligned.S
Normal file
16
tests/tcg/s390x/clrl-unaligned.S
Normal 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
|
16
tests/tcg/s390x/crl-unaligned.S
Normal file
16
tests/tcg/s390x/crl-unaligned.S
Normal 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
17
tests/tcg/s390x/ex-odd.S
Normal 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
|
156
tests/tcg/s390x/ex-relative-long.c
Normal file
156
tests/tcg/s390x/ex-relative-long.c
Normal 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;
|
||||||
|
}
|
43
tests/tcg/s390x/exrl-ssm-early.S
Normal file
43
tests/tcg/s390x/exrl-ssm-early.S
Normal 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 */
|
16
tests/tcg/s390x/lgrl-unaligned.S
Normal file
16
tests/tcg/s390x/lgrl-unaligned.S
Normal 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
|
16
tests/tcg/s390x/llgfrl-unaligned.S
Normal file
16
tests/tcg/s390x/llgfrl-unaligned.S
Normal 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
36
tests/tcg/s390x/lpsw.S
Normal 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 */
|
38
tests/tcg/s390x/lpswe-early.S
Normal file
38
tests/tcg/s390x/lpswe-early.S
Normal 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 */
|
18
tests/tcg/s390x/lpswe-unaligned.S
Normal file
18
tests/tcg/s390x/lpswe-unaligned.S
Normal 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
|
16
tests/tcg/s390x/lrl-unaligned.S
Normal file
16
tests/tcg/s390x/lrl-unaligned.S
Normal 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
|
40
tests/tcg/s390x/pgm-specification-softmmu.S
Normal file
40
tests/tcg/s390x/pgm-specification-softmmu.S
Normal 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 */
|
37
tests/tcg/s390x/pgm-specification-user.c
Normal file
37
tests/tcg/s390x/pgm-specification-user.c
Normal 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;
|
||||||
|
}
|
15
tests/tcg/s390x/pgm-specification.mak
Normal file
15
tests/tcg/s390x/pgm-specification.mak
Normal 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
46
tests/tcg/s390x/rxsbg.c
Normal 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;
|
||||||
|
}
|
20
tests/tcg/s390x/softmmu.ld
Normal file
20
tests/tcg/s390x/softmmu.ld
Normal 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/ : {
|
||||||
|
*(*)
|
||||||
|
}
|
||||||
|
}
|
41
tests/tcg/s390x/ssm-early.S
Normal file
41
tests/tcg/s390x/ssm-early.S
Normal 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 */
|
16
tests/tcg/s390x/stgrl-unaligned.S
Normal file
16
tests/tcg/s390x/stgrl-unaligned.S
Normal 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
|
41
tests/tcg/s390x/stosm-early.S
Normal file
41
tests/tcg/s390x/stosm-early.S
Normal 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 */
|
16
tests/tcg/s390x/strl-unaligned.S
Normal file
16
tests/tcg/s390x/strl-unaligned.S
Normal 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
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
182
util/envlist.c
182
util/envlist.c
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user