summaryrefslogtreecommitdiffstats
path: root/qemu/hw/scsi/mptconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/scsi/mptconfig.c')
-rw-r--r--qemu/hw/scsi/mptconfig.c905
1 files changed, 0 insertions, 905 deletions
diff --git a/qemu/hw/scsi/mptconfig.c b/qemu/hw/scsi/mptconfig.c
deleted file mode 100644
index 707185469..000000000
--- a/qemu/hw/scsi/mptconfig.c
+++ /dev/null
@@ -1,905 +0,0 @@
-/*
- * QEMU LSI SAS1068 Host Bus Adapter emulation - configuration pages
- *
- * Copyright (c) 2016 Red Hat, Inc.
- *
- * Author: Paolo Bonzini
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- */
-#include "qemu/osdep.h"
-#include "hw/hw.h"
-#include "hw/pci/pci.h"
-#include "hw/scsi/scsi.h"
-
-#include "mptsas.h"
-#include "mpi.h"
-#include "trace.h"
-
-/* Generic functions for marshaling and unmarshaling. */
-
-#define repl1(x) x
-#define repl2(x) x x
-#define repl3(x) x x x
-#define repl4(x) x x x x
-#define repl5(x) x x x x x
-#define repl6(x) x x x x x x
-#define repl7(x) x x x x x x x
-#define repl8(x) x x x x x x x x
-
-#define repl(n, x) glue(repl, n)(x)
-
-typedef union PackValue {
- uint64_t ll;
- char *str;
-} PackValue;
-
-static size_t vfill(uint8_t *data, size_t size, const char *fmt, va_list ap)
-{
- size_t ofs;
- PackValue val;
- const char *p;
-
- ofs = 0;
- p = fmt;
- while (*p) {
- memset(&val, 0, sizeof(val));
- switch (*p) {
- case '*':
- p++;
- break;
- case 'b':
- case 'w':
- case 'l':
- val.ll = va_arg(ap, int);
- break;
- case 'q':
- val.ll = va_arg(ap, int64_t);
- break;
- case 's':
- val.str = va_arg(ap, void *);
- break;
- }
- switch (*p++) {
- case 'b':
- if (data) {
- stb_p(data + ofs, val.ll);
- }
- ofs++;
- break;
- case 'w':
- if (data) {
- stw_le_p(data + ofs, val.ll);
- }
- ofs += 2;
- break;
- case 'l':
- if (data) {
- stl_le_p(data + ofs, val.ll);
- }
- ofs += 4;
- break;
- case 'q':
- if (data) {
- stq_le_p(data + ofs, val.ll);
- }
- ofs += 8;
- break;
- case 's':
- {
- int cnt = atoi(p);
- if (data) {
- if (val.str) {
- strncpy((void *)data + ofs, val.str, cnt);
- } else {
- memset((void *)data + ofs, 0, cnt);
- }
- }
- ofs += cnt;
- break;
- }
- }
- }
-
- return ofs;
-}
-
-static size_t vpack(uint8_t **p_data, const char *fmt, va_list ap1)
-{
- size_t size = 0;
- uint8_t *data = NULL;
-
- if (p_data) {
- va_list ap2;
-
- va_copy(ap2, ap1);
- size = vfill(NULL, 0, fmt, ap2);
- *p_data = data = g_malloc(size);
- va_end(ap2);
- }
- return vfill(data, size, fmt, ap1);
-}
-
-static size_t fill(uint8_t *data, size_t size, const char *fmt, ...)
-{
- va_list ap;
- size_t ret;
-
- va_start(ap, fmt);
- ret = vfill(data, size, fmt, ap);
- va_end(ap);
-
- return ret;
-}
-
-/* Functions to build the page header and fill in the length, always used
- * through the macros.
- */
-
-#define MPTSAS_CONFIG_PACK(number, type, version, fmt, ...) \
- mptsas_config_pack(data, "b*bbb" fmt, version, number, type, \
- ## __VA_ARGS__)
-
-static size_t mptsas_config_pack(uint8_t **data, const char *fmt, ...)
-{
- va_list ap;
- size_t ret;
-
- va_start(ap, fmt);
- ret = vpack(data, fmt, ap);
- va_end(ap);
-
- if (data) {
- assert(ret < 256 && (ret % 4) == 0);
- stb_p(*data + 1, ret / 4);
- }
- return ret;
-}
-
-#define MPTSAS_CONFIG_PACK_EXT(number, type, version, fmt, ...) \
- mptsas_config_pack_ext(data, "b*bbb*wb*b" fmt, version, number, \
- MPI_CONFIG_PAGETYPE_EXTENDED, type, ## __VA_ARGS__)
-
-static size_t mptsas_config_pack_ext(uint8_t **data, const char *fmt, ...)
-{
- va_list ap;
- size_t ret;
-
- va_start(ap, fmt);
- ret = vpack(data, fmt, ap);
- va_end(ap);
-
- if (data) {
- assert(ret < 65536 && (ret % 4) == 0);
- stw_le_p(*data + 4, ret / 4);
- }
- return ret;
-}
-
-/* Manufacturing pages */
-
-static
-size_t mptsas_config_manufacturing_0(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "s16s8s16s16s16",
- "QEMU MPT Fusion",
- "2.5",
- "QEMU MPT Fusion",
- "QEMU",
- "0000111122223333");
-}
-
-static
-size_t mptsas_config_manufacturing_1(MPTSASState *s, uint8_t **data, int address)
-{
- /* VPD - all zeros */
- return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "s256");
-}
-
-static
-size_t mptsas_config_manufacturing_2(MPTSASState *s, uint8_t **data, int address)
-{
- PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s);
- return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "wb*b*l",
- pcic->device_id, pcic->revision);
-}
-
-static
-size_t mptsas_config_manufacturing_3(MPTSASState *s, uint8_t **data, int address)
-{
- PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s);
- return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "wb*b*l",
- pcic->device_id, pcic->revision);
-}
-
-static
-size_t mptsas_config_manufacturing_4(MPTSASState *s, uint8_t **data, int address)
-{
- /* All zeros */
- return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x05,
- "*l*b*b*b*b*b*b*w*s56*l*l*l*l*l*l"
- "*b*b*w*b*b*w*l*l");
-}
-
-static
-size_t mptsas_config_manufacturing_5(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(5, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x02,
- "q*b*b*w*l*l", s->sas_addr);
-}
-
-static
-size_t mptsas_config_manufacturing_6(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(6, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "*l");
-}
-
-static
-size_t mptsas_config_manufacturing_7(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(7, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "*l*l*l*s16*b*b*w", MPTSAS_NUM_PORTS);
-}
-
-static
-size_t mptsas_config_manufacturing_8(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(8, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "*l");
-}
-
-static
-size_t mptsas_config_manufacturing_9(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(9, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "*l");
-}
-
-static
-size_t mptsas_config_manufacturing_10(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(10, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
- "*l");
-}
-
-/* I/O unit pages */
-
-static
-size_t mptsas_config_io_unit_0(MPTSASState *s, uint8_t **data, int address)
-{
- PCIDevice *pci = PCI_DEVICE(s);
- uint64_t unique_value = 0x53504D554D4551LL; /* "QEMUMPTx" */
-
- unique_value |= (uint64_t)pci->devfn << 56;
- return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x00,
- "q", unique_value);
-}
-
-static
-size_t mptsas_config_io_unit_1(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x02, "l",
- 0x41 /* single function, RAID disabled */ );
-}
-
-static
-size_t mptsas_config_io_unit_2(MPTSASState *s, uint8_t **data, int address)
-{
- PCIDevice *pci = PCI_DEVICE(s);
- uint8_t devfn = pci->devfn;
- return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x02,
- "llbbw*b*b*w*b*b*w*b*b*w*l",
- 0, 0x100, 0 /* pci bus? */, devfn, 0);
-}
-
-static
-size_t mptsas_config_io_unit_3(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x01,
- "*b*b*w*l");
-}
-
-static
-size_t mptsas_config_io_unit_4(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x00, "*l*l*q");
-}
-
-/* I/O controller pages */
-
-static
-size_t mptsas_config_ioc_0(MPTSASState *s, uint8_t **data, int address)
-{
- PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s);
-
- return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_IOC, 0x01,
- "*l*lwwb*b*b*blww",
- pcic->vendor_id, pcic->device_id, pcic->revision,
- pcic->subsystem_vendor_id,
- pcic->subsystem_id);
-}
-
-static
-size_t mptsas_config_ioc_1(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_IOC, 0x03,
- "*l*l*b*b*b*b");
-}
-
-static
-size_t mptsas_config_ioc_2(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_IOC, 0x04,
- "*l*b*b*b*b");
-}
-
-static
-size_t mptsas_config_ioc_3(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_IOC, 0x00,
- "*b*b*w");
-}
-
-static
-size_t mptsas_config_ioc_4(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_IOC, 0x00,
- "*b*b*w");
-}
-
-static
-size_t mptsas_config_ioc_5(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(5, MPI_CONFIG_PAGETYPE_IOC, 0x00,
- "*l*b*b*w");
-}
-
-static
-size_t mptsas_config_ioc_6(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK(6, MPI_CONFIG_PAGETYPE_IOC, 0x01,
- "*l*b*b*b*b*b*b*b*b*b*b*w*l*l*l*l*b*b*w"
- "*w*w*w*w*l*l*l");
-}
-
-/* SAS I/O unit pages (extended) */
-
-#define MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE 16
-
-#define MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION 0x02
-#define MPI_SAS_IOUNIT0_RATE_1_5 0x08
-#define MPI_SAS_IOUNIT0_RATE_3_0 0x09
-
-#define MPI_SAS_DEVICE_INFO_NO_DEVICE 0x00000000
-#define MPI_SAS_DEVICE_INFO_END_DEVICE 0x00000001
-#define MPI_SAS_DEVICE_INFO_SSP_TARGET 0x00000400
-
-#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS 0x00
-
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT 0x0001
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED 0x0002
-#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT 0x0004
-
-
-
-static SCSIDevice *mptsas_phy_get_device(MPTSASState *s, int i,
- int *phy_handle, int *dev_handle)
-{
- SCSIDevice *d = scsi_device_find(&s->bus, 0, i, 0);
-
- if (phy_handle) {
- *phy_handle = i + 1;
- }
- if (dev_handle) {
- *dev_handle = d ? i + 1 + MPTSAS_NUM_PORTS : 0;
- }
- return d;
-}
-
-static
-size_t mptsas_config_sas_io_unit_0(MPTSASState *s, uint8_t **data, int address)
-{
- size_t size = MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x04,
- "*w*wb*b*w"
- repl(MPTSAS_NUM_PORTS, "*s16"),
- MPTSAS_NUM_PORTS);
-
- if (data) {
- size_t ofs = size - MPTSAS_NUM_PORTS * MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE;
- int i;
-
- for (i = 0; i < MPTSAS_NUM_PORTS; i++) {
- int phy_handle, dev_handle;
- SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
-
- fill(*data + ofs, MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE,
- "bbbblwwl", i, 0, 0,
- (dev
- ? MPI_SAS_IOUNIT0_RATE_3_0
- : MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION),
- (dev
- ? MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET
- : MPI_SAS_DEVICE_INFO_NO_DEVICE),
- dev_handle,
- dev_handle,
- 0);
- ofs += MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE;
- }
- assert(ofs == size);
- }
- return size;
-}
-
-#define MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE 12
-
-static
-size_t mptsas_config_sas_io_unit_1(MPTSASState *s, uint8_t **data, int address)
-{
- size_t size = MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x07,
- "*w*w*w*wb*b*b*b"
- repl(MPTSAS_NUM_PORTS, "*s12"),
- MPTSAS_NUM_PORTS);
-
- if (data) {
- size_t ofs = size - MPTSAS_NUM_PORTS * MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE;
- int i;
-
- for (i = 0; i < MPTSAS_NUM_PORTS; i++) {
- SCSIDevice *dev = mptsas_phy_get_device(s, i, NULL, NULL);
- fill(*data + ofs, MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE,
- "bbbblww", i, 0, 0,
- (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5,
- (dev
- ? MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET
- : MPI_SAS_DEVICE_INFO_NO_DEVICE),
- 0, 0);
- ofs += MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE;
- }
- assert(ofs == size);
- }
- return size;
-}
-
-static
-size_t mptsas_config_sas_io_unit_2(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK_EXT(2, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x06,
- "*b*b*w*w*w*b*b*w");
-}
-
-static
-size_t mptsas_config_sas_io_unit_3(MPTSASState *s, uint8_t **data, int address)
-{
- return MPTSAS_CONFIG_PACK_EXT(3, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x06,
- "*l*l*l*l*l*l*l*l*l");
-}
-
-/* SAS PHY pages (extended) */
-
-static int mptsas_phy_addr_get(MPTSASState *s, int address)
-{
- int i;
- if ((address >> MPI_SAS_PHY_PGAD_FORM_SHIFT) == 0) {
- i = address & 255;
- } else if ((address >> MPI_SAS_PHY_PGAD_FORM_SHIFT) == 1) {
- i = address & 65535;
- } else {
- return -EINVAL;
- }
-
- if (i >= MPTSAS_NUM_PORTS) {
- return -EINVAL;
- }
-
- return i;
-}
-
-static
-size_t mptsas_config_phy_0(MPTSASState *s, uint8_t **data, int address)
-{
- int phy_handle = -1;
- int dev_handle = -1;
- int i = mptsas_phy_addr_get(s, address);
- SCSIDevice *dev;
-
- if (i < 0) {
- trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 0);
- return i;
- }
-
- dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
- trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 0);
-
- return MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0x01,
- "w*wqwb*blbb*b*b*l",
- dev_handle, s->sas_addr, dev_handle, i,
- (dev
- ? MPI_SAS_DEVICE_INFO_END_DEVICE /* | MPI_SAS_DEVICE_INFO_SSP_TARGET?? */
- : MPI_SAS_DEVICE_INFO_NO_DEVICE),
- (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5,
- (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5);
-}
-
-static
-size_t mptsas_config_phy_1(MPTSASState *s, uint8_t **data, int address)
-{
- int phy_handle = -1;
- int dev_handle = -1;
- int i = mptsas_phy_addr_get(s, address);
-
- if (i < 0) {
- trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 1);
- return i;
- }
-
- (void) mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
- trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 1);
-
- return MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0x01,
- "*l*l*l*l*l");
-}
-
-/* SAS device pages (extended) */
-
-static int mptsas_device_addr_get(MPTSASState *s, int address)
-{
- uint32_t handle, i;
- uint32_t form = address >> MPI_SAS_PHY_PGAD_FORM_SHIFT;
- if (form == MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) {
- handle = address & MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK;
- do {
- if (handle == 65535) {
- handle = MPTSAS_NUM_PORTS + 1;
- } else {
- ++handle;
- }
- i = handle - 1 - MPTSAS_NUM_PORTS;
- } while (i < MPTSAS_NUM_PORTS && !scsi_device_find(&s->bus, 0, i, 0));
-
- } else if (form == MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID) {
- if (address & MPI_SAS_DEVICE_PGAD_BT_BUS_MASK) {
- return -EINVAL;
- }
- i = address & MPI_SAS_DEVICE_PGAD_BT_TID_MASK;
-
- } else if (form == MPI_SAS_DEVICE_PGAD_FORM_HANDLE) {
- handle = address & MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK;
- i = handle - 1 - MPTSAS_NUM_PORTS;
-
- } else {
- return -EINVAL;
- }
-
- if (i >= MPTSAS_NUM_PORTS) {
- return -EINVAL;
- }
-
- return i;
-}
-
-static
-size_t mptsas_config_sas_device_0(MPTSASState *s, uint8_t **data, int address)
-{
- int phy_handle = -1;
- int dev_handle = -1;
- int i = mptsas_device_addr_get(s, address);
- SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
-
- trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 0);
- if (!dev) {
- return -ENOENT;
- }
-
- return MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x05,
- "*w*wqwbbwbblwb*b",
- dev->wwn, phy_handle, i,
- MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS,
- dev_handle, i, 0,
- MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET,
- (MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT |
- MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED |
- MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT), i);
-}
-
-static
-size_t mptsas_config_sas_device_1(MPTSASState *s, uint8_t **data, int address)
-{
- int phy_handle = -1;
- int dev_handle = -1;
- int i = mptsas_device_addr_get(s, address);
- SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
-
- trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 1);
- if (!dev) {
- return -ENOENT;
- }
-
- return MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x00,
- "*lq*lwbb*s20",
- dev->wwn, dev_handle, i, 0);
-}
-
-static
-size_t mptsas_config_sas_device_2(MPTSASState *s, uint8_t **data, int address)
-{
- int phy_handle = -1;
- int dev_handle = -1;
- int i = mptsas_device_addr_get(s, address);
- SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
-
- trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 2);
- if (!dev) {
- return -ENOENT;
- }
-
- return MPTSAS_CONFIG_PACK_EXT(2, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x01,
- "ql", dev->wwn, 0);
-}
-
-typedef struct MPTSASConfigPage {
- uint8_t number;
- uint8_t type;
- size_t (*mpt_config_build)(MPTSASState *s, uint8_t **data, int address);
-} MPTSASConfigPage;
-
-static const MPTSASConfigPage mptsas_config_pages[] = {
- {
- 0, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_0,
- }, {
- 1, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_1,
- }, {
- 2, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_2,
- }, {
- 3, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_3,
- }, {
- 4, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_4,
- }, {
- 5, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_5,
- }, {
- 6, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_6,
- }, {
- 7, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_7,
- }, {
- 8, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_8,
- }, {
- 9, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_9,
- }, {
- 10, MPI_CONFIG_PAGETYPE_MANUFACTURING,
- mptsas_config_manufacturing_10,
- }, {
- 0, MPI_CONFIG_PAGETYPE_IO_UNIT,
- mptsas_config_io_unit_0,
- }, {
- 1, MPI_CONFIG_PAGETYPE_IO_UNIT,
- mptsas_config_io_unit_1,
- }, {
- 2, MPI_CONFIG_PAGETYPE_IO_UNIT,
- mptsas_config_io_unit_2,
- }, {
- 3, MPI_CONFIG_PAGETYPE_IO_UNIT,
- mptsas_config_io_unit_3,
- }, {
- 4, MPI_CONFIG_PAGETYPE_IO_UNIT,
- mptsas_config_io_unit_4,
- }, {
- 0, MPI_CONFIG_PAGETYPE_IOC,
- mptsas_config_ioc_0,
- }, {
- 1, MPI_CONFIG_PAGETYPE_IOC,
- mptsas_config_ioc_1,
- }, {
- 2, MPI_CONFIG_PAGETYPE_IOC,
- mptsas_config_ioc_2,
- }, {
- 3, MPI_CONFIG_PAGETYPE_IOC,
- mptsas_config_ioc_3,
- }, {
- 4, MPI_CONFIG_PAGETYPE_IOC,
- mptsas_config_ioc_4,
- }, {
- 5, MPI_CONFIG_PAGETYPE_IOC,
- mptsas_config_ioc_5,
- }, {
- 6, MPI_CONFIG_PAGETYPE_IOC,
- mptsas_config_ioc_6,
- }, {
- 0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
- mptsas_config_sas_io_unit_0,
- }, {
- 1, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
- mptsas_config_sas_io_unit_1,
- }, {
- 2, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
- mptsas_config_sas_io_unit_2,
- }, {
- 3, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
- mptsas_config_sas_io_unit_3,
- }, {
- 0, MPI_CONFIG_EXTPAGETYPE_SAS_PHY,
- mptsas_config_phy_0,
- }, {
- 1, MPI_CONFIG_EXTPAGETYPE_SAS_PHY,
- mptsas_config_phy_1,
- }, {
- 0, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
- mptsas_config_sas_device_0,
- }, {
- 1, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
- mptsas_config_sas_device_1,
- }, {
- 2, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
- mptsas_config_sas_device_2,
- }
-};
-
-static const MPTSASConfigPage *mptsas_find_config_page(int type, int number)
-{
- const MPTSASConfigPage *page;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(mptsas_config_pages); i++) {
- page = &mptsas_config_pages[i];
- if (page->type == type && page->number == number) {
- return page;
- }
- }
-
- return NULL;
-}
-
-void mptsas_process_config(MPTSASState *s, MPIMsgConfig *req)
-{
- PCIDevice *pci = PCI_DEVICE(s);
-
- MPIMsgConfigReply reply;
- const MPTSASConfigPage *page;
- size_t length;
- uint8_t type;
- uint8_t *data = NULL;
- uint32_t flags_and_length;
- uint32_t dmalen;
- uint64_t pa;
-
- mptsas_fix_config_endianness(req);
-
- QEMU_BUILD_BUG_ON(sizeof(s->doorbell_msg) < sizeof(*req));
- QEMU_BUILD_BUG_ON(sizeof(s->doorbell_reply) < sizeof(reply));
-
- /* Copy common bits from the request into the reply. */
- memset(&reply, 0, sizeof(reply));
- reply.Action = req->Action;
- reply.Function = req->Function;
- reply.MsgContext = req->MsgContext;
- reply.MsgLength = sizeof(reply) / 4;
- reply.PageType = req->PageType;
- reply.PageNumber = req->PageNumber;
- reply.PageLength = req->PageLength;
- reply.PageVersion = req->PageVersion;
-
- type = req->PageType & MPI_CONFIG_PAGETYPE_MASK;
- if (type == MPI_CONFIG_PAGETYPE_EXTENDED) {
- type = req->ExtPageType;
- if (type <= MPI_CONFIG_PAGETYPE_MASK) {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_TYPE;
- goto out;
- }
-
- reply.ExtPageType = req->ExtPageType;
- }
-
- page = mptsas_find_config_page(type, req->PageNumber);
-
- switch(req->Action) {
- case MPI_CONFIG_ACTION_PAGE_DEFAULT:
- case MPI_CONFIG_ACTION_PAGE_HEADER:
- case MPI_CONFIG_ACTION_PAGE_READ_NVRAM:
- case MPI_CONFIG_ACTION_PAGE_READ_CURRENT:
- case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT:
- case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT:
- case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM:
- break;
-
- default:
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_ACTION;
- goto out;
- }
-
- if (!page) {
- page = mptsas_find_config_page(type, 1);
- if (page) {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
- } else {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_TYPE;
- }
- goto out;
- }
-
- if (req->Action == MPI_CONFIG_ACTION_PAGE_DEFAULT ||
- req->Action == MPI_CONFIG_ACTION_PAGE_HEADER) {
- length = page->mpt_config_build(s, NULL, req->PageAddress);
- if ((ssize_t)length < 0) {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
- goto out;
- } else {
- goto done;
- }
- }
-
- if (req->Action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
- req->Action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
- length = page->mpt_config_build(s, NULL, req->PageAddress);
- if ((ssize_t)length < 0) {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
- } else {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_CANT_COMMIT;
- }
- goto out;
- }
-
- flags_and_length = req->PageBufferSGE.FlagsLength;
- dmalen = flags_and_length & MPI_SGE_LENGTH_MASK;
- if (dmalen == 0) {
- length = page->mpt_config_build(s, NULL, req->PageAddress);
- if ((ssize_t)length < 0) {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
- goto out;
- } else {
- goto done;
- }
- }
-
- if (flags_and_length & MPI_SGE_FLAGS_64_BIT_ADDRESSING) {
- pa = req->PageBufferSGE.u.Address64;
- } else {
- pa = req->PageBufferSGE.u.Address32;
- }
-
- /* Only read actions left. */
- length = page->mpt_config_build(s, &data, req->PageAddress);
- if ((ssize_t)length < 0) {
- reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
- goto out;
- } else {
- assert(data[2] == page->number);
- pci_dma_write(pci, pa, data, MIN(length, dmalen));
- goto done;
- }
-
- abort();
-
-done:
- if (type > MPI_CONFIG_PAGETYPE_MASK) {
- reply.ExtPageLength = length / 4;
- reply.ExtPageType = req->ExtPageType;
- } else {
- reply.PageLength = length / 4;
- }
-
-out:
- mptsas_fix_config_reply_endianness(&reply);
- mptsas_reply(s, (MPIDefaultReply *)&reply);
- g_free(data);
-}