1e351b826SPaolo Bonzini /* 2e351b826SPaolo Bonzini * QEMU LSI SAS1068 Host Bus Adapter emulation - configuration pages 3e351b826SPaolo Bonzini * 4e351b826SPaolo Bonzini * Copyright (c) 2016 Red Hat, Inc. 5e351b826SPaolo Bonzini * 6e351b826SPaolo Bonzini * Author: Paolo Bonzini 7e351b826SPaolo Bonzini * 8e351b826SPaolo Bonzini * This library is free software; you can redistribute it and/or 9e351b826SPaolo Bonzini * modify it under the terms of the GNU Lesser General Public 10e351b826SPaolo Bonzini * License as published by the Free Software Foundation; either 11e351b826SPaolo Bonzini * version 2 of the License, or (at your option) any later version. 12e351b826SPaolo Bonzini * 13e351b826SPaolo Bonzini * This library is distributed in the hope that it will be useful, 14e351b826SPaolo Bonzini * but WITHOUT ANY WARRANTY; without even the implied warranty of 15e351b826SPaolo Bonzini * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16e351b826SPaolo Bonzini * Lesser General Public License for more details. 17e351b826SPaolo Bonzini */ 18e351b826SPaolo Bonzini #include "qemu/osdep.h" 19e351b826SPaolo Bonzini #include "hw/hw.h" 20e351b826SPaolo Bonzini #include "hw/pci/pci.h" 21e351b826SPaolo Bonzini #include "hw/scsi/scsi.h" 22e351b826SPaolo Bonzini 23e351b826SPaolo Bonzini #include "mptsas.h" 24e351b826SPaolo Bonzini #include "mpi.h" 25e351b826SPaolo Bonzini #include "trace.h" 26e351b826SPaolo Bonzini 27e351b826SPaolo Bonzini /* Generic functions for marshaling and unmarshaling. */ 28e351b826SPaolo Bonzini 29e351b826SPaolo Bonzini #define repl1(x) x 30e351b826SPaolo Bonzini #define repl2(x) x x 31e351b826SPaolo Bonzini #define repl3(x) x x x 32e351b826SPaolo Bonzini #define repl4(x) x x x x 33e351b826SPaolo Bonzini #define repl5(x) x x x x x 34e351b826SPaolo Bonzini #define repl6(x) x x x x x x 35e351b826SPaolo Bonzini #define repl7(x) x x x x x x x 36e351b826SPaolo Bonzini #define repl8(x) x x x x x x x x 37e351b826SPaolo Bonzini 38e351b826SPaolo Bonzini #define repl(n, x) glue(repl, n)(x) 39e351b826SPaolo Bonzini 40e351b826SPaolo Bonzini typedef union PackValue { 41e351b826SPaolo Bonzini uint64_t ll; 42e351b826SPaolo Bonzini char *str; 43e351b826SPaolo Bonzini } PackValue; 44e351b826SPaolo Bonzini 45e351b826SPaolo Bonzini static size_t vfill(uint8_t *data, size_t size, const char *fmt, va_list ap) 46e351b826SPaolo Bonzini { 47e351b826SPaolo Bonzini size_t ofs; 48e351b826SPaolo Bonzini PackValue val; 49e351b826SPaolo Bonzini const char *p; 50e351b826SPaolo Bonzini 51e351b826SPaolo Bonzini ofs = 0; 52e351b826SPaolo Bonzini p = fmt; 53e351b826SPaolo Bonzini while (*p) { 54e351b826SPaolo Bonzini memset(&val, 0, sizeof(val)); 55e351b826SPaolo Bonzini switch (*p) { 56e351b826SPaolo Bonzini case '*': 57e351b826SPaolo Bonzini p++; 58e351b826SPaolo Bonzini break; 59e351b826SPaolo Bonzini case 'b': 60e351b826SPaolo Bonzini case 'w': 61e351b826SPaolo Bonzini case 'l': 62e351b826SPaolo Bonzini val.ll = va_arg(ap, int); 63e351b826SPaolo Bonzini break; 64e351b826SPaolo Bonzini case 'q': 65e351b826SPaolo Bonzini val.ll = va_arg(ap, int64_t); 66e351b826SPaolo Bonzini break; 67e351b826SPaolo Bonzini case 's': 68e351b826SPaolo Bonzini val.str = va_arg(ap, void *); 69e351b826SPaolo Bonzini break; 70e351b826SPaolo Bonzini } 71e351b826SPaolo Bonzini switch (*p++) { 72e351b826SPaolo Bonzini case 'b': 73e351b826SPaolo Bonzini if (data) { 74e351b826SPaolo Bonzini stb_p(data + ofs, val.ll); 75e351b826SPaolo Bonzini } 76e351b826SPaolo Bonzini ofs++; 77e351b826SPaolo Bonzini break; 78e351b826SPaolo Bonzini case 'w': 79e351b826SPaolo Bonzini if (data) { 80e351b826SPaolo Bonzini stw_le_p(data + ofs, val.ll); 81e351b826SPaolo Bonzini } 82e351b826SPaolo Bonzini ofs += 2; 83e351b826SPaolo Bonzini break; 84e351b826SPaolo Bonzini case 'l': 85e351b826SPaolo Bonzini if (data) { 86e351b826SPaolo Bonzini stl_le_p(data + ofs, val.ll); 87e351b826SPaolo Bonzini } 88e351b826SPaolo Bonzini ofs += 4; 89e351b826SPaolo Bonzini break; 90e351b826SPaolo Bonzini case 'q': 91e351b826SPaolo Bonzini if (data) { 92e351b826SPaolo Bonzini stq_le_p(data + ofs, val.ll); 93e351b826SPaolo Bonzini } 94e351b826SPaolo Bonzini ofs += 8; 95e351b826SPaolo Bonzini break; 96e351b826SPaolo Bonzini case 's': 97e351b826SPaolo Bonzini { 98e351b826SPaolo Bonzini int cnt = atoi(p); 99e351b826SPaolo Bonzini if (data) { 100e351b826SPaolo Bonzini if (val.str) { 101e351b826SPaolo Bonzini strncpy((void *)data + ofs, val.str, cnt); 102e351b826SPaolo Bonzini } else { 103e351b826SPaolo Bonzini memset((void *)data + ofs, 0, cnt); 104e351b826SPaolo Bonzini } 105e351b826SPaolo Bonzini } 106e351b826SPaolo Bonzini ofs += cnt; 107e351b826SPaolo Bonzini break; 108e351b826SPaolo Bonzini } 109e351b826SPaolo Bonzini } 110e351b826SPaolo Bonzini } 111e351b826SPaolo Bonzini 112e351b826SPaolo Bonzini return ofs; 113e351b826SPaolo Bonzini } 114e351b826SPaolo Bonzini 115e351b826SPaolo Bonzini static size_t vpack(uint8_t **p_data, const char *fmt, va_list ap1) 116e351b826SPaolo Bonzini { 117e351b826SPaolo Bonzini size_t size = 0; 118e351b826SPaolo Bonzini uint8_t *data = NULL; 119e351b826SPaolo Bonzini 120e351b826SPaolo Bonzini if (p_data) { 121e351b826SPaolo Bonzini va_list ap2; 122e351b826SPaolo Bonzini 123e351b826SPaolo Bonzini va_copy(ap2, ap1); 124e351b826SPaolo Bonzini size = vfill(NULL, 0, fmt, ap2); 125e351b826SPaolo Bonzini *p_data = data = g_malloc(size); 126b44bbeb4SPaolo Bonzini va_end(ap2); 127e351b826SPaolo Bonzini } 128e351b826SPaolo Bonzini return vfill(data, size, fmt, ap1); 129e351b826SPaolo Bonzini } 130e351b826SPaolo Bonzini 131e351b826SPaolo Bonzini static size_t fill(uint8_t *data, size_t size, const char *fmt, ...) 132e351b826SPaolo Bonzini { 133e351b826SPaolo Bonzini va_list ap; 134e351b826SPaolo Bonzini size_t ret; 135e351b826SPaolo Bonzini 136e351b826SPaolo Bonzini va_start(ap, fmt); 137e351b826SPaolo Bonzini ret = vfill(data, size, fmt, ap); 138e351b826SPaolo Bonzini va_end(ap); 139e351b826SPaolo Bonzini 140e351b826SPaolo Bonzini return ret; 141e351b826SPaolo Bonzini } 142e351b826SPaolo Bonzini 143e351b826SPaolo Bonzini /* Functions to build the page header and fill in the length, always used 144e351b826SPaolo Bonzini * through the macros. 145e351b826SPaolo Bonzini */ 146e351b826SPaolo Bonzini 147e351b826SPaolo Bonzini #define MPTSAS_CONFIG_PACK(number, type, version, fmt, ...) \ 148e351b826SPaolo Bonzini mptsas_config_pack(data, "b*bbb" fmt, version, number, type, \ 149e351b826SPaolo Bonzini ## __VA_ARGS__) 150e351b826SPaolo Bonzini 151e351b826SPaolo Bonzini static size_t mptsas_config_pack(uint8_t **data, const char *fmt, ...) 152e351b826SPaolo Bonzini { 153e351b826SPaolo Bonzini va_list ap; 154e351b826SPaolo Bonzini size_t ret; 155e351b826SPaolo Bonzini 156e351b826SPaolo Bonzini va_start(ap, fmt); 157e351b826SPaolo Bonzini ret = vpack(data, fmt, ap); 158e351b826SPaolo Bonzini va_end(ap); 159e351b826SPaolo Bonzini 160e351b826SPaolo Bonzini if (data) { 161cf2bce20SPrasad J Pandit assert(ret / 4 < 256 && (ret % 4) == 0); 162e351b826SPaolo Bonzini stb_p(*data + 1, ret / 4); 163e351b826SPaolo Bonzini } 164e351b826SPaolo Bonzini return ret; 165e351b826SPaolo Bonzini } 166e351b826SPaolo Bonzini 167e351b826SPaolo Bonzini #define MPTSAS_CONFIG_PACK_EXT(number, type, version, fmt, ...) \ 168e351b826SPaolo Bonzini mptsas_config_pack_ext(data, "b*bbb*wb*b" fmt, version, number, \ 169e351b826SPaolo Bonzini MPI_CONFIG_PAGETYPE_EXTENDED, type, ## __VA_ARGS__) 170e351b826SPaolo Bonzini 171e351b826SPaolo Bonzini static size_t mptsas_config_pack_ext(uint8_t **data, const char *fmt, ...) 172e351b826SPaolo Bonzini { 173e351b826SPaolo Bonzini va_list ap; 174e351b826SPaolo Bonzini size_t ret; 175e351b826SPaolo Bonzini 176e351b826SPaolo Bonzini va_start(ap, fmt); 177e351b826SPaolo Bonzini ret = vpack(data, fmt, ap); 178e351b826SPaolo Bonzini va_end(ap); 179e351b826SPaolo Bonzini 180e351b826SPaolo Bonzini if (data) { 181e351b826SPaolo Bonzini assert(ret < 65536 && (ret % 4) == 0); 182e351b826SPaolo Bonzini stw_le_p(*data + 4, ret / 4); 183e351b826SPaolo Bonzini } 184e351b826SPaolo Bonzini return ret; 185e351b826SPaolo Bonzini } 186e351b826SPaolo Bonzini 187e351b826SPaolo Bonzini /* Manufacturing pages */ 188e351b826SPaolo Bonzini 189e351b826SPaolo Bonzini static 190e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_0(MPTSASState *s, uint8_t **data, int address) 191e351b826SPaolo Bonzini { 192e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 193e351b826SPaolo Bonzini "s16s8s16s16s16", 194e351b826SPaolo Bonzini "QEMU MPT Fusion", 195e351b826SPaolo Bonzini "2.5", 196e351b826SPaolo Bonzini "QEMU MPT Fusion", 197e351b826SPaolo Bonzini "QEMU", 198e351b826SPaolo Bonzini "0000111122223333"); 199e351b826SPaolo Bonzini } 200e351b826SPaolo Bonzini 201e351b826SPaolo Bonzini static 202e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_1(MPTSASState *s, uint8_t **data, int address) 203e351b826SPaolo Bonzini { 204e351b826SPaolo Bonzini /* VPD - all zeros */ 205e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 206*65a8e1f6SPaolo Bonzini "*s256"); 207e351b826SPaolo Bonzini } 208e351b826SPaolo Bonzini 209e351b826SPaolo Bonzini static 210e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_2(MPTSASState *s, uint8_t **data, int address) 211e351b826SPaolo Bonzini { 212e351b826SPaolo Bonzini PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s); 213e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 214e351b826SPaolo Bonzini "wb*b*l", 215e351b826SPaolo Bonzini pcic->device_id, pcic->revision); 216e351b826SPaolo Bonzini } 217e351b826SPaolo Bonzini 218e351b826SPaolo Bonzini static 219e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_3(MPTSASState *s, uint8_t **data, int address) 220e351b826SPaolo Bonzini { 221e351b826SPaolo Bonzini PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s); 222e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 223e351b826SPaolo Bonzini "wb*b*l", 224e351b826SPaolo Bonzini pcic->device_id, pcic->revision); 225e351b826SPaolo Bonzini } 226e351b826SPaolo Bonzini 227e351b826SPaolo Bonzini static 228e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_4(MPTSASState *s, uint8_t **data, int address) 229e351b826SPaolo Bonzini { 230e351b826SPaolo Bonzini /* All zeros */ 231e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x05, 232e351b826SPaolo Bonzini "*l*b*b*b*b*b*b*w*s56*l*l*l*l*l*l" 233e351b826SPaolo Bonzini "*b*b*w*b*b*w*l*l"); 234e351b826SPaolo Bonzini } 235e351b826SPaolo Bonzini 236e351b826SPaolo Bonzini static 237e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_5(MPTSASState *s, uint8_t **data, int address) 238e351b826SPaolo Bonzini { 239e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(5, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x02, 240e351b826SPaolo Bonzini "q*b*b*w*l*l", s->sas_addr); 241e351b826SPaolo Bonzini } 242e351b826SPaolo Bonzini 243e351b826SPaolo Bonzini static 244e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_6(MPTSASState *s, uint8_t **data, int address) 245e351b826SPaolo Bonzini { 246e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(6, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 247e351b826SPaolo Bonzini "*l"); 248e351b826SPaolo Bonzini } 249e351b826SPaolo Bonzini 250e351b826SPaolo Bonzini static 251e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_7(MPTSASState *s, uint8_t **data, int address) 252e351b826SPaolo Bonzini { 253e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(7, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 254e351b826SPaolo Bonzini "*l*l*l*s16*b*b*w", MPTSAS_NUM_PORTS); 255e351b826SPaolo Bonzini } 256e351b826SPaolo Bonzini 257e351b826SPaolo Bonzini static 258e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_8(MPTSASState *s, uint8_t **data, int address) 259e351b826SPaolo Bonzini { 260e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(8, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 261e351b826SPaolo Bonzini "*l"); 262e351b826SPaolo Bonzini } 263e351b826SPaolo Bonzini 264e351b826SPaolo Bonzini static 265e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_9(MPTSASState *s, uint8_t **data, int address) 266e351b826SPaolo Bonzini { 267e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(9, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 268e351b826SPaolo Bonzini "*l"); 269e351b826SPaolo Bonzini } 270e351b826SPaolo Bonzini 271e351b826SPaolo Bonzini static 272e351b826SPaolo Bonzini size_t mptsas_config_manufacturing_10(MPTSASState *s, uint8_t **data, int address) 273e351b826SPaolo Bonzini { 274e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(10, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00, 275e351b826SPaolo Bonzini "*l"); 276e351b826SPaolo Bonzini } 277e351b826SPaolo Bonzini 278e351b826SPaolo Bonzini /* I/O unit pages */ 279e351b826SPaolo Bonzini 280e351b826SPaolo Bonzini static 281e351b826SPaolo Bonzini size_t mptsas_config_io_unit_0(MPTSASState *s, uint8_t **data, int address) 282e351b826SPaolo Bonzini { 283e351b826SPaolo Bonzini PCIDevice *pci = PCI_DEVICE(s); 284e351b826SPaolo Bonzini uint64_t unique_value = 0x53504D554D4551LL; /* "QEMUMPTx" */ 285e351b826SPaolo Bonzini 286e351b826SPaolo Bonzini unique_value |= (uint64_t)pci->devfn << 56; 287e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x00, 288e351b826SPaolo Bonzini "q", unique_value); 289e351b826SPaolo Bonzini } 290e351b826SPaolo Bonzini 291e351b826SPaolo Bonzini static 292e351b826SPaolo Bonzini size_t mptsas_config_io_unit_1(MPTSASState *s, uint8_t **data, int address) 293e351b826SPaolo Bonzini { 294e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x02, "l", 295e351b826SPaolo Bonzini 0x41 /* single function, RAID disabled */ ); 296e351b826SPaolo Bonzini } 297e351b826SPaolo Bonzini 298e351b826SPaolo Bonzini static 299e351b826SPaolo Bonzini size_t mptsas_config_io_unit_2(MPTSASState *s, uint8_t **data, int address) 300e351b826SPaolo Bonzini { 301e351b826SPaolo Bonzini PCIDevice *pci = PCI_DEVICE(s); 302e351b826SPaolo Bonzini uint8_t devfn = pci->devfn; 303e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x02, 304e351b826SPaolo Bonzini "llbbw*b*b*w*b*b*w*b*b*w*l", 305e351b826SPaolo Bonzini 0, 0x100, 0 /* pci bus? */, devfn, 0); 306e351b826SPaolo Bonzini } 307e351b826SPaolo Bonzini 308e351b826SPaolo Bonzini static 309e351b826SPaolo Bonzini size_t mptsas_config_io_unit_3(MPTSASState *s, uint8_t **data, int address) 310e351b826SPaolo Bonzini { 311e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x01, 312e351b826SPaolo Bonzini "*b*b*w*l"); 313e351b826SPaolo Bonzini } 314e351b826SPaolo Bonzini 315e351b826SPaolo Bonzini static 316e351b826SPaolo Bonzini size_t mptsas_config_io_unit_4(MPTSASState *s, uint8_t **data, int address) 317e351b826SPaolo Bonzini { 318e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x00, "*l*l*q"); 319e351b826SPaolo Bonzini } 320e351b826SPaolo Bonzini 321e351b826SPaolo Bonzini /* I/O controller pages */ 322e351b826SPaolo Bonzini 323e351b826SPaolo Bonzini static 324e351b826SPaolo Bonzini size_t mptsas_config_ioc_0(MPTSASState *s, uint8_t **data, int address) 325e351b826SPaolo Bonzini { 326e351b826SPaolo Bonzini PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s); 327e351b826SPaolo Bonzini 328e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_IOC, 0x01, 329e351b826SPaolo Bonzini "*l*lwwb*b*b*blww", 330e351b826SPaolo Bonzini pcic->vendor_id, pcic->device_id, pcic->revision, 331*65a8e1f6SPaolo Bonzini pcic->class_id, pcic->subsystem_vendor_id, 332e351b826SPaolo Bonzini pcic->subsystem_id); 333e351b826SPaolo Bonzini } 334e351b826SPaolo Bonzini 335e351b826SPaolo Bonzini static 336e351b826SPaolo Bonzini size_t mptsas_config_ioc_1(MPTSASState *s, uint8_t **data, int address) 337e351b826SPaolo Bonzini { 338e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_IOC, 0x03, 339e351b826SPaolo Bonzini "*l*l*b*b*b*b"); 340e351b826SPaolo Bonzini } 341e351b826SPaolo Bonzini 342e351b826SPaolo Bonzini static 343e351b826SPaolo Bonzini size_t mptsas_config_ioc_2(MPTSASState *s, uint8_t **data, int address) 344e351b826SPaolo Bonzini { 345e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_IOC, 0x04, 346e351b826SPaolo Bonzini "*l*b*b*b*b"); 347e351b826SPaolo Bonzini } 348e351b826SPaolo Bonzini 349e351b826SPaolo Bonzini static 350e351b826SPaolo Bonzini size_t mptsas_config_ioc_3(MPTSASState *s, uint8_t **data, int address) 351e351b826SPaolo Bonzini { 352e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_IOC, 0x00, 353e351b826SPaolo Bonzini "*b*b*w"); 354e351b826SPaolo Bonzini } 355e351b826SPaolo Bonzini 356e351b826SPaolo Bonzini static 357e351b826SPaolo Bonzini size_t mptsas_config_ioc_4(MPTSASState *s, uint8_t **data, int address) 358e351b826SPaolo Bonzini { 359e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_IOC, 0x00, 360e351b826SPaolo Bonzini "*b*b*w"); 361e351b826SPaolo Bonzini } 362e351b826SPaolo Bonzini 363e351b826SPaolo Bonzini static 364e351b826SPaolo Bonzini size_t mptsas_config_ioc_5(MPTSASState *s, uint8_t **data, int address) 365e351b826SPaolo Bonzini { 366e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(5, MPI_CONFIG_PAGETYPE_IOC, 0x00, 367e351b826SPaolo Bonzini "*l*b*b*w"); 368e351b826SPaolo Bonzini } 369e351b826SPaolo Bonzini 370e351b826SPaolo Bonzini static 371e351b826SPaolo Bonzini size_t mptsas_config_ioc_6(MPTSASState *s, uint8_t **data, int address) 372e351b826SPaolo Bonzini { 373e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK(6, MPI_CONFIG_PAGETYPE_IOC, 0x01, 374e351b826SPaolo Bonzini "*l*b*b*b*b*b*b*b*b*b*b*w*l*l*l*l*b*b*w" 375e351b826SPaolo Bonzini "*w*w*w*w*l*l*l"); 376e351b826SPaolo Bonzini } 377e351b826SPaolo Bonzini 378e351b826SPaolo Bonzini /* SAS I/O unit pages (extended) */ 379e351b826SPaolo Bonzini 380e351b826SPaolo Bonzini #define MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE 16 381e351b826SPaolo Bonzini 382e351b826SPaolo Bonzini #define MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION 0x02 383e351b826SPaolo Bonzini #define MPI_SAS_IOUNIT0_RATE_1_5 0x08 384e351b826SPaolo Bonzini #define MPI_SAS_IOUNIT0_RATE_3_0 0x09 385e351b826SPaolo Bonzini 386e351b826SPaolo Bonzini #define MPI_SAS_DEVICE_INFO_NO_DEVICE 0x00000000 387e351b826SPaolo Bonzini #define MPI_SAS_DEVICE_INFO_END_DEVICE 0x00000001 388e351b826SPaolo Bonzini #define MPI_SAS_DEVICE_INFO_SSP_TARGET 0x00000400 389e351b826SPaolo Bonzini 390e351b826SPaolo Bonzini #define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS 0x00 391e351b826SPaolo Bonzini 392e351b826SPaolo Bonzini #define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT 0x0001 393e351b826SPaolo Bonzini #define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED 0x0002 394e351b826SPaolo Bonzini #define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT 0x0004 395e351b826SPaolo Bonzini 396e351b826SPaolo Bonzini 397e351b826SPaolo Bonzini 398e351b826SPaolo Bonzini static SCSIDevice *mptsas_phy_get_device(MPTSASState *s, int i, 399e351b826SPaolo Bonzini int *phy_handle, int *dev_handle) 400e351b826SPaolo Bonzini { 401e351b826SPaolo Bonzini SCSIDevice *d = scsi_device_find(&s->bus, 0, i, 0); 402e351b826SPaolo Bonzini 403e351b826SPaolo Bonzini if (phy_handle) { 404e351b826SPaolo Bonzini *phy_handle = i + 1; 405e351b826SPaolo Bonzini } 406e351b826SPaolo Bonzini if (dev_handle) { 407e351b826SPaolo Bonzini *dev_handle = d ? i + 1 + MPTSAS_NUM_PORTS : 0; 408e351b826SPaolo Bonzini } 409e351b826SPaolo Bonzini return d; 410e351b826SPaolo Bonzini } 411e351b826SPaolo Bonzini 412e351b826SPaolo Bonzini static 413e351b826SPaolo Bonzini size_t mptsas_config_sas_io_unit_0(MPTSASState *s, uint8_t **data, int address) 414e351b826SPaolo Bonzini { 415e351b826SPaolo Bonzini size_t size = MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x04, 416e351b826SPaolo Bonzini "*w*wb*b*w" 417e351b826SPaolo Bonzini repl(MPTSAS_NUM_PORTS, "*s16"), 418e351b826SPaolo Bonzini MPTSAS_NUM_PORTS); 419e351b826SPaolo Bonzini 420e351b826SPaolo Bonzini if (data) { 421e351b826SPaolo Bonzini size_t ofs = size - MPTSAS_NUM_PORTS * MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE; 422e351b826SPaolo Bonzini int i; 423e351b826SPaolo Bonzini 424e351b826SPaolo Bonzini for (i = 0; i < MPTSAS_NUM_PORTS; i++) { 425e351b826SPaolo Bonzini int phy_handle, dev_handle; 426e351b826SPaolo Bonzini SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle); 427e351b826SPaolo Bonzini 428e351b826SPaolo Bonzini fill(*data + ofs, MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE, 429e351b826SPaolo Bonzini "bbbblwwl", i, 0, 0, 430e351b826SPaolo Bonzini (dev 431e351b826SPaolo Bonzini ? MPI_SAS_IOUNIT0_RATE_3_0 432e351b826SPaolo Bonzini : MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION), 433e351b826SPaolo Bonzini (dev 434e351b826SPaolo Bonzini ? MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET 435e351b826SPaolo Bonzini : MPI_SAS_DEVICE_INFO_NO_DEVICE), 436e351b826SPaolo Bonzini dev_handle, 437e351b826SPaolo Bonzini dev_handle, 438e351b826SPaolo Bonzini 0); 439e351b826SPaolo Bonzini ofs += MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE; 440e351b826SPaolo Bonzini } 441e351b826SPaolo Bonzini assert(ofs == size); 442e351b826SPaolo Bonzini } 443e351b826SPaolo Bonzini return size; 444e351b826SPaolo Bonzini } 445e351b826SPaolo Bonzini 446e351b826SPaolo Bonzini #define MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE 12 447e351b826SPaolo Bonzini 448e351b826SPaolo Bonzini static 449e351b826SPaolo Bonzini size_t mptsas_config_sas_io_unit_1(MPTSASState *s, uint8_t **data, int address) 450e351b826SPaolo Bonzini { 451e351b826SPaolo Bonzini size_t size = MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x07, 452e351b826SPaolo Bonzini "*w*w*w*wb*b*b*b" 453e351b826SPaolo Bonzini repl(MPTSAS_NUM_PORTS, "*s12"), 454e351b826SPaolo Bonzini MPTSAS_NUM_PORTS); 455e351b826SPaolo Bonzini 456e351b826SPaolo Bonzini if (data) { 457e351b826SPaolo Bonzini size_t ofs = size - MPTSAS_NUM_PORTS * MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE; 458e351b826SPaolo Bonzini int i; 459e351b826SPaolo Bonzini 460e351b826SPaolo Bonzini for (i = 0; i < MPTSAS_NUM_PORTS; i++) { 461e351b826SPaolo Bonzini SCSIDevice *dev = mptsas_phy_get_device(s, i, NULL, NULL); 462e351b826SPaolo Bonzini fill(*data + ofs, MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE, 463e351b826SPaolo Bonzini "bbbblww", i, 0, 0, 464e351b826SPaolo Bonzini (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5, 465e351b826SPaolo Bonzini (dev 466e351b826SPaolo Bonzini ? MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET 467e351b826SPaolo Bonzini : MPI_SAS_DEVICE_INFO_NO_DEVICE), 468e351b826SPaolo Bonzini 0, 0); 469e351b826SPaolo Bonzini ofs += MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE; 470e351b826SPaolo Bonzini } 471e351b826SPaolo Bonzini assert(ofs == size); 472e351b826SPaolo Bonzini } 473e351b826SPaolo Bonzini return size; 474e351b826SPaolo Bonzini } 475e351b826SPaolo Bonzini 476e351b826SPaolo Bonzini static 477e351b826SPaolo Bonzini size_t mptsas_config_sas_io_unit_2(MPTSASState *s, uint8_t **data, int address) 478e351b826SPaolo Bonzini { 479e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK_EXT(2, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x06, 480e351b826SPaolo Bonzini "*b*b*w*w*w*b*b*w"); 481e351b826SPaolo Bonzini } 482e351b826SPaolo Bonzini 483e351b826SPaolo Bonzini static 484e351b826SPaolo Bonzini size_t mptsas_config_sas_io_unit_3(MPTSASState *s, uint8_t **data, int address) 485e351b826SPaolo Bonzini { 486e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK_EXT(3, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x06, 487e351b826SPaolo Bonzini "*l*l*l*l*l*l*l*l*l"); 488e351b826SPaolo Bonzini } 489e351b826SPaolo Bonzini 490e351b826SPaolo Bonzini /* SAS PHY pages (extended) */ 491e351b826SPaolo Bonzini 492e351b826SPaolo Bonzini static int mptsas_phy_addr_get(MPTSASState *s, int address) 493e351b826SPaolo Bonzini { 494e351b826SPaolo Bonzini int i; 495e351b826SPaolo Bonzini if ((address >> MPI_SAS_PHY_PGAD_FORM_SHIFT) == 0) { 496e351b826SPaolo Bonzini i = address & 255; 497e351b826SPaolo Bonzini } else if ((address >> MPI_SAS_PHY_PGAD_FORM_SHIFT) == 1) { 498e351b826SPaolo Bonzini i = address & 65535; 499e351b826SPaolo Bonzini } else { 500e351b826SPaolo Bonzini return -EINVAL; 501e351b826SPaolo Bonzini } 502e351b826SPaolo Bonzini 503e351b826SPaolo Bonzini if (i >= MPTSAS_NUM_PORTS) { 504e351b826SPaolo Bonzini return -EINVAL; 505e351b826SPaolo Bonzini } 506e351b826SPaolo Bonzini 507e351b826SPaolo Bonzini return i; 508e351b826SPaolo Bonzini } 509e351b826SPaolo Bonzini 510e351b826SPaolo Bonzini static 511e351b826SPaolo Bonzini size_t mptsas_config_phy_0(MPTSASState *s, uint8_t **data, int address) 512e351b826SPaolo Bonzini { 513e351b826SPaolo Bonzini int phy_handle = -1; 514e351b826SPaolo Bonzini int dev_handle = -1; 515e351b826SPaolo Bonzini int i = mptsas_phy_addr_get(s, address); 516e351b826SPaolo Bonzini SCSIDevice *dev; 517e351b826SPaolo Bonzini 518e351b826SPaolo Bonzini if (i < 0) { 519e351b826SPaolo Bonzini trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 0); 520e351b826SPaolo Bonzini return i; 521e351b826SPaolo Bonzini } 522e351b826SPaolo Bonzini 523e351b826SPaolo Bonzini dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle); 524e351b826SPaolo Bonzini trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 0); 525e351b826SPaolo Bonzini 526e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0x01, 527e351b826SPaolo Bonzini "w*wqwb*blbb*b*b*l", 528e351b826SPaolo Bonzini dev_handle, s->sas_addr, dev_handle, i, 529e351b826SPaolo Bonzini (dev 530e351b826SPaolo Bonzini ? MPI_SAS_DEVICE_INFO_END_DEVICE /* | MPI_SAS_DEVICE_INFO_SSP_TARGET?? */ 531e351b826SPaolo Bonzini : MPI_SAS_DEVICE_INFO_NO_DEVICE), 532e351b826SPaolo Bonzini (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5, 533e351b826SPaolo Bonzini (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5); 534e351b826SPaolo Bonzini } 535e351b826SPaolo Bonzini 536e351b826SPaolo Bonzini static 537e351b826SPaolo Bonzini size_t mptsas_config_phy_1(MPTSASState *s, uint8_t **data, int address) 538e351b826SPaolo Bonzini { 539e351b826SPaolo Bonzini int phy_handle = -1; 540e351b826SPaolo Bonzini int dev_handle = -1; 541e351b826SPaolo Bonzini int i = mptsas_phy_addr_get(s, address); 542e351b826SPaolo Bonzini 543e351b826SPaolo Bonzini if (i < 0) { 544e351b826SPaolo Bonzini trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 1); 545e351b826SPaolo Bonzini return i; 546e351b826SPaolo Bonzini } 547e351b826SPaolo Bonzini 548e351b826SPaolo Bonzini (void) mptsas_phy_get_device(s, i, &phy_handle, &dev_handle); 549e351b826SPaolo Bonzini trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 1); 550e351b826SPaolo Bonzini 551e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0x01, 552e351b826SPaolo Bonzini "*l*l*l*l*l"); 553e351b826SPaolo Bonzini } 554e351b826SPaolo Bonzini 555e351b826SPaolo Bonzini /* SAS device pages (extended) */ 556e351b826SPaolo Bonzini 557e351b826SPaolo Bonzini static int mptsas_device_addr_get(MPTSASState *s, int address) 558e351b826SPaolo Bonzini { 559e351b826SPaolo Bonzini uint32_t handle, i; 560e351b826SPaolo Bonzini uint32_t form = address >> MPI_SAS_PHY_PGAD_FORM_SHIFT; 561e351b826SPaolo Bonzini if (form == MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) { 562e351b826SPaolo Bonzini handle = address & MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK; 563e351b826SPaolo Bonzini do { 564e351b826SPaolo Bonzini if (handle == 65535) { 565e351b826SPaolo Bonzini handle = MPTSAS_NUM_PORTS + 1; 566e351b826SPaolo Bonzini } else { 567e351b826SPaolo Bonzini ++handle; 568e351b826SPaolo Bonzini } 569e351b826SPaolo Bonzini i = handle - 1 - MPTSAS_NUM_PORTS; 570e351b826SPaolo Bonzini } while (i < MPTSAS_NUM_PORTS && !scsi_device_find(&s->bus, 0, i, 0)); 571e351b826SPaolo Bonzini 572e351b826SPaolo Bonzini } else if (form == MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID) { 573e351b826SPaolo Bonzini if (address & MPI_SAS_DEVICE_PGAD_BT_BUS_MASK) { 574e351b826SPaolo Bonzini return -EINVAL; 575e351b826SPaolo Bonzini } 576e351b826SPaolo Bonzini i = address & MPI_SAS_DEVICE_PGAD_BT_TID_MASK; 577e351b826SPaolo Bonzini 578e351b826SPaolo Bonzini } else if (form == MPI_SAS_DEVICE_PGAD_FORM_HANDLE) { 579e351b826SPaolo Bonzini handle = address & MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK; 580e351b826SPaolo Bonzini i = handle - 1 - MPTSAS_NUM_PORTS; 581e351b826SPaolo Bonzini 582e351b826SPaolo Bonzini } else { 583e351b826SPaolo Bonzini return -EINVAL; 584e351b826SPaolo Bonzini } 585e351b826SPaolo Bonzini 586e351b826SPaolo Bonzini if (i >= MPTSAS_NUM_PORTS) { 587e351b826SPaolo Bonzini return -EINVAL; 588e351b826SPaolo Bonzini } 589e351b826SPaolo Bonzini 590e351b826SPaolo Bonzini return i; 591e351b826SPaolo Bonzini } 592e351b826SPaolo Bonzini 593e351b826SPaolo Bonzini static 594e351b826SPaolo Bonzini size_t mptsas_config_sas_device_0(MPTSASState *s, uint8_t **data, int address) 595e351b826SPaolo Bonzini { 596e351b826SPaolo Bonzini int phy_handle = -1; 597e351b826SPaolo Bonzini int dev_handle = -1; 598e351b826SPaolo Bonzini int i = mptsas_device_addr_get(s, address); 599e351b826SPaolo Bonzini SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle); 600e351b826SPaolo Bonzini 601e351b826SPaolo Bonzini trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 0); 602e351b826SPaolo Bonzini if (!dev) { 603e351b826SPaolo Bonzini return -ENOENT; 604e351b826SPaolo Bonzini } 605e351b826SPaolo Bonzini 606e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x05, 607e351b826SPaolo Bonzini "*w*wqwbbwbblwb*b", 608e351b826SPaolo Bonzini dev->wwn, phy_handle, i, 609e351b826SPaolo Bonzini MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS, 610e351b826SPaolo Bonzini dev_handle, i, 0, 611e351b826SPaolo Bonzini MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET, 612e351b826SPaolo Bonzini (MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT | 613e351b826SPaolo Bonzini MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED | 614e351b826SPaolo Bonzini MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT), i); 615e351b826SPaolo Bonzini } 616e351b826SPaolo Bonzini 617e351b826SPaolo Bonzini static 618e351b826SPaolo Bonzini size_t mptsas_config_sas_device_1(MPTSASState *s, uint8_t **data, int address) 619e351b826SPaolo Bonzini { 620e351b826SPaolo Bonzini int phy_handle = -1; 621e351b826SPaolo Bonzini int dev_handle = -1; 622e351b826SPaolo Bonzini int i = mptsas_device_addr_get(s, address); 623e351b826SPaolo Bonzini SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle); 624e351b826SPaolo Bonzini 625e351b826SPaolo Bonzini trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 1); 626e351b826SPaolo Bonzini if (!dev) { 627e351b826SPaolo Bonzini return -ENOENT; 628e351b826SPaolo Bonzini } 629e351b826SPaolo Bonzini 630e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x00, 631e351b826SPaolo Bonzini "*lq*lwbb*s20", 632e351b826SPaolo Bonzini dev->wwn, dev_handle, i, 0); 633e351b826SPaolo Bonzini } 634e351b826SPaolo Bonzini 635e351b826SPaolo Bonzini static 636e351b826SPaolo Bonzini size_t mptsas_config_sas_device_2(MPTSASState *s, uint8_t **data, int address) 637e351b826SPaolo Bonzini { 638e351b826SPaolo Bonzini int phy_handle = -1; 639e351b826SPaolo Bonzini int dev_handle = -1; 640e351b826SPaolo Bonzini int i = mptsas_device_addr_get(s, address); 641e351b826SPaolo Bonzini SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle); 642e351b826SPaolo Bonzini 643e351b826SPaolo Bonzini trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 2); 644e351b826SPaolo Bonzini if (!dev) { 645e351b826SPaolo Bonzini return -ENOENT; 646e351b826SPaolo Bonzini } 647e351b826SPaolo Bonzini 648e351b826SPaolo Bonzini return MPTSAS_CONFIG_PACK_EXT(2, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x01, 649e351b826SPaolo Bonzini "ql", dev->wwn, 0); 650e351b826SPaolo Bonzini } 651e351b826SPaolo Bonzini 652e351b826SPaolo Bonzini typedef struct MPTSASConfigPage { 653e351b826SPaolo Bonzini uint8_t number; 654e351b826SPaolo Bonzini uint8_t type; 655e351b826SPaolo Bonzini size_t (*mpt_config_build)(MPTSASState *s, uint8_t **data, int address); 656e351b826SPaolo Bonzini } MPTSASConfigPage; 657e351b826SPaolo Bonzini 658e351b826SPaolo Bonzini static const MPTSASConfigPage mptsas_config_pages[] = { 659e351b826SPaolo Bonzini { 660e351b826SPaolo Bonzini 0, MPI_CONFIG_PAGETYPE_MANUFACTURING, 661e351b826SPaolo Bonzini mptsas_config_manufacturing_0, 662e351b826SPaolo Bonzini }, { 663e351b826SPaolo Bonzini 1, MPI_CONFIG_PAGETYPE_MANUFACTURING, 664e351b826SPaolo Bonzini mptsas_config_manufacturing_1, 665e351b826SPaolo Bonzini }, { 666e351b826SPaolo Bonzini 2, MPI_CONFIG_PAGETYPE_MANUFACTURING, 667e351b826SPaolo Bonzini mptsas_config_manufacturing_2, 668e351b826SPaolo Bonzini }, { 669e351b826SPaolo Bonzini 3, MPI_CONFIG_PAGETYPE_MANUFACTURING, 670e351b826SPaolo Bonzini mptsas_config_manufacturing_3, 671e351b826SPaolo Bonzini }, { 672e351b826SPaolo Bonzini 4, MPI_CONFIG_PAGETYPE_MANUFACTURING, 673e351b826SPaolo Bonzini mptsas_config_manufacturing_4, 674e351b826SPaolo Bonzini }, { 675e351b826SPaolo Bonzini 5, MPI_CONFIG_PAGETYPE_MANUFACTURING, 676e351b826SPaolo Bonzini mptsas_config_manufacturing_5, 677e351b826SPaolo Bonzini }, { 678e351b826SPaolo Bonzini 6, MPI_CONFIG_PAGETYPE_MANUFACTURING, 679e351b826SPaolo Bonzini mptsas_config_manufacturing_6, 680e351b826SPaolo Bonzini }, { 681e351b826SPaolo Bonzini 7, MPI_CONFIG_PAGETYPE_MANUFACTURING, 682e351b826SPaolo Bonzini mptsas_config_manufacturing_7, 683e351b826SPaolo Bonzini }, { 684e351b826SPaolo Bonzini 8, MPI_CONFIG_PAGETYPE_MANUFACTURING, 685e351b826SPaolo Bonzini mptsas_config_manufacturing_8, 686e351b826SPaolo Bonzini }, { 687e351b826SPaolo Bonzini 9, MPI_CONFIG_PAGETYPE_MANUFACTURING, 688e351b826SPaolo Bonzini mptsas_config_manufacturing_9, 689e351b826SPaolo Bonzini }, { 690e351b826SPaolo Bonzini 10, MPI_CONFIG_PAGETYPE_MANUFACTURING, 691e351b826SPaolo Bonzini mptsas_config_manufacturing_10, 692e351b826SPaolo Bonzini }, { 693e351b826SPaolo Bonzini 0, MPI_CONFIG_PAGETYPE_IO_UNIT, 694e351b826SPaolo Bonzini mptsas_config_io_unit_0, 695e351b826SPaolo Bonzini }, { 696e351b826SPaolo Bonzini 1, MPI_CONFIG_PAGETYPE_IO_UNIT, 697e351b826SPaolo Bonzini mptsas_config_io_unit_1, 698e351b826SPaolo Bonzini }, { 699e351b826SPaolo Bonzini 2, MPI_CONFIG_PAGETYPE_IO_UNIT, 700e351b826SPaolo Bonzini mptsas_config_io_unit_2, 701e351b826SPaolo Bonzini }, { 702e351b826SPaolo Bonzini 3, MPI_CONFIG_PAGETYPE_IO_UNIT, 703e351b826SPaolo Bonzini mptsas_config_io_unit_3, 704e351b826SPaolo Bonzini }, { 705e351b826SPaolo Bonzini 4, MPI_CONFIG_PAGETYPE_IO_UNIT, 706e351b826SPaolo Bonzini mptsas_config_io_unit_4, 707e351b826SPaolo Bonzini }, { 708e351b826SPaolo Bonzini 0, MPI_CONFIG_PAGETYPE_IOC, 709e351b826SPaolo Bonzini mptsas_config_ioc_0, 710e351b826SPaolo Bonzini }, { 711e351b826SPaolo Bonzini 1, MPI_CONFIG_PAGETYPE_IOC, 712e351b826SPaolo Bonzini mptsas_config_ioc_1, 713e351b826SPaolo Bonzini }, { 714e351b826SPaolo Bonzini 2, MPI_CONFIG_PAGETYPE_IOC, 715e351b826SPaolo Bonzini mptsas_config_ioc_2, 716e351b826SPaolo Bonzini }, { 717e351b826SPaolo Bonzini 3, MPI_CONFIG_PAGETYPE_IOC, 718e351b826SPaolo Bonzini mptsas_config_ioc_3, 719e351b826SPaolo Bonzini }, { 720e351b826SPaolo Bonzini 4, MPI_CONFIG_PAGETYPE_IOC, 721e351b826SPaolo Bonzini mptsas_config_ioc_4, 722e351b826SPaolo Bonzini }, { 723e351b826SPaolo Bonzini 5, MPI_CONFIG_PAGETYPE_IOC, 724e351b826SPaolo Bonzini mptsas_config_ioc_5, 725e351b826SPaolo Bonzini }, { 726e351b826SPaolo Bonzini 6, MPI_CONFIG_PAGETYPE_IOC, 727e351b826SPaolo Bonzini mptsas_config_ioc_6, 728e351b826SPaolo Bonzini }, { 729e351b826SPaolo Bonzini 0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 730e351b826SPaolo Bonzini mptsas_config_sas_io_unit_0, 731e351b826SPaolo Bonzini }, { 732e351b826SPaolo Bonzini 1, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 733e351b826SPaolo Bonzini mptsas_config_sas_io_unit_1, 734e351b826SPaolo Bonzini }, { 735e351b826SPaolo Bonzini 2, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 736e351b826SPaolo Bonzini mptsas_config_sas_io_unit_2, 737e351b826SPaolo Bonzini }, { 738e351b826SPaolo Bonzini 3, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 739e351b826SPaolo Bonzini mptsas_config_sas_io_unit_3, 740e351b826SPaolo Bonzini }, { 741e351b826SPaolo Bonzini 0, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 742e351b826SPaolo Bonzini mptsas_config_phy_0, 743e351b826SPaolo Bonzini }, { 744e351b826SPaolo Bonzini 1, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 745e351b826SPaolo Bonzini mptsas_config_phy_1, 746e351b826SPaolo Bonzini }, { 747e351b826SPaolo Bonzini 0, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 748e351b826SPaolo Bonzini mptsas_config_sas_device_0, 749e351b826SPaolo Bonzini }, { 750e351b826SPaolo Bonzini 1, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 751e351b826SPaolo Bonzini mptsas_config_sas_device_1, 752e351b826SPaolo Bonzini }, { 753e351b826SPaolo Bonzini 2, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 754e351b826SPaolo Bonzini mptsas_config_sas_device_2, 755e351b826SPaolo Bonzini } 756e351b826SPaolo Bonzini }; 757e351b826SPaolo Bonzini 758e351b826SPaolo Bonzini static const MPTSASConfigPage *mptsas_find_config_page(int type, int number) 759e351b826SPaolo Bonzini { 760e351b826SPaolo Bonzini const MPTSASConfigPage *page; 761e351b826SPaolo Bonzini int i; 762e351b826SPaolo Bonzini 763e351b826SPaolo Bonzini for (i = 0; i < ARRAY_SIZE(mptsas_config_pages); i++) { 764e351b826SPaolo Bonzini page = &mptsas_config_pages[i]; 765e351b826SPaolo Bonzini if (page->type == type && page->number == number) { 766e351b826SPaolo Bonzini return page; 767e351b826SPaolo Bonzini } 768e351b826SPaolo Bonzini } 769e351b826SPaolo Bonzini 770e351b826SPaolo Bonzini return NULL; 771e351b826SPaolo Bonzini } 772e351b826SPaolo Bonzini 773e351b826SPaolo Bonzini void mptsas_process_config(MPTSASState *s, MPIMsgConfig *req) 774e351b826SPaolo Bonzini { 775e351b826SPaolo Bonzini PCIDevice *pci = PCI_DEVICE(s); 776e351b826SPaolo Bonzini 777e351b826SPaolo Bonzini MPIMsgConfigReply reply; 778e351b826SPaolo Bonzini const MPTSASConfigPage *page; 779e351b826SPaolo Bonzini size_t length; 780e351b826SPaolo Bonzini uint8_t type; 781e351b826SPaolo Bonzini uint8_t *data = NULL; 782e351b826SPaolo Bonzini uint32_t flags_and_length; 783e351b826SPaolo Bonzini uint32_t dmalen; 784e351b826SPaolo Bonzini uint64_t pa; 785e351b826SPaolo Bonzini 786e351b826SPaolo Bonzini mptsas_fix_config_endianness(req); 787e351b826SPaolo Bonzini 788e351b826SPaolo Bonzini QEMU_BUILD_BUG_ON(sizeof(s->doorbell_msg) < sizeof(*req)); 789e351b826SPaolo Bonzini QEMU_BUILD_BUG_ON(sizeof(s->doorbell_reply) < sizeof(reply)); 790e351b826SPaolo Bonzini 791e351b826SPaolo Bonzini /* Copy common bits from the request into the reply. */ 792e351b826SPaolo Bonzini memset(&reply, 0, sizeof(reply)); 793e351b826SPaolo Bonzini reply.Action = req->Action; 794e351b826SPaolo Bonzini reply.Function = req->Function; 795e351b826SPaolo Bonzini reply.MsgContext = req->MsgContext; 796e351b826SPaolo Bonzini reply.MsgLength = sizeof(reply) / 4; 797e351b826SPaolo Bonzini reply.PageType = req->PageType; 798e351b826SPaolo Bonzini reply.PageNumber = req->PageNumber; 799e351b826SPaolo Bonzini reply.PageLength = req->PageLength; 800e351b826SPaolo Bonzini reply.PageVersion = req->PageVersion; 801e351b826SPaolo Bonzini 802e351b826SPaolo Bonzini type = req->PageType & MPI_CONFIG_PAGETYPE_MASK; 803e351b826SPaolo Bonzini if (type == MPI_CONFIG_PAGETYPE_EXTENDED) { 804e351b826SPaolo Bonzini type = req->ExtPageType; 805e351b826SPaolo Bonzini if (type <= MPI_CONFIG_PAGETYPE_MASK) { 806e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_TYPE; 807e351b826SPaolo Bonzini goto out; 808e351b826SPaolo Bonzini } 809e351b826SPaolo Bonzini 810e351b826SPaolo Bonzini reply.ExtPageType = req->ExtPageType; 811e351b826SPaolo Bonzini } 812e351b826SPaolo Bonzini 813e351b826SPaolo Bonzini page = mptsas_find_config_page(type, req->PageNumber); 814e351b826SPaolo Bonzini 815e351b826SPaolo Bonzini switch(req->Action) { 816e351b826SPaolo Bonzini case MPI_CONFIG_ACTION_PAGE_DEFAULT: 817e351b826SPaolo Bonzini case MPI_CONFIG_ACTION_PAGE_HEADER: 818e351b826SPaolo Bonzini case MPI_CONFIG_ACTION_PAGE_READ_NVRAM: 819e351b826SPaolo Bonzini case MPI_CONFIG_ACTION_PAGE_READ_CURRENT: 820e351b826SPaolo Bonzini case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT: 821e351b826SPaolo Bonzini case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT: 822e351b826SPaolo Bonzini case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM: 823e351b826SPaolo Bonzini break; 824e351b826SPaolo Bonzini 825e351b826SPaolo Bonzini default: 826e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_ACTION; 827e351b826SPaolo Bonzini goto out; 828e351b826SPaolo Bonzini } 829e351b826SPaolo Bonzini 830e351b826SPaolo Bonzini if (!page) { 831e351b826SPaolo Bonzini page = mptsas_find_config_page(type, 1); 832e351b826SPaolo Bonzini if (page) { 833e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE; 834e351b826SPaolo Bonzini } else { 835e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_TYPE; 836e351b826SPaolo Bonzini } 837e351b826SPaolo Bonzini goto out; 838e351b826SPaolo Bonzini } 839e351b826SPaolo Bonzini 840e351b826SPaolo Bonzini if (req->Action == MPI_CONFIG_ACTION_PAGE_DEFAULT || 841e351b826SPaolo Bonzini req->Action == MPI_CONFIG_ACTION_PAGE_HEADER) { 842e351b826SPaolo Bonzini length = page->mpt_config_build(s, NULL, req->PageAddress); 843e351b826SPaolo Bonzini if ((ssize_t)length < 0) { 844e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE; 845e351b826SPaolo Bonzini goto out; 846e351b826SPaolo Bonzini } else { 847e351b826SPaolo Bonzini goto done; 848e351b826SPaolo Bonzini } 849e351b826SPaolo Bonzini } 850e351b826SPaolo Bonzini 851e351b826SPaolo Bonzini if (req->Action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT || 852e351b826SPaolo Bonzini req->Action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM) { 853e351b826SPaolo Bonzini length = page->mpt_config_build(s, NULL, req->PageAddress); 854e351b826SPaolo Bonzini if ((ssize_t)length < 0) { 855e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE; 856e351b826SPaolo Bonzini } else { 857e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_CANT_COMMIT; 858e351b826SPaolo Bonzini } 859e351b826SPaolo Bonzini goto out; 860e351b826SPaolo Bonzini } 861e351b826SPaolo Bonzini 862e351b826SPaolo Bonzini flags_and_length = req->PageBufferSGE.FlagsLength; 863e351b826SPaolo Bonzini dmalen = flags_and_length & MPI_SGE_LENGTH_MASK; 864e351b826SPaolo Bonzini if (dmalen == 0) { 865e351b826SPaolo Bonzini length = page->mpt_config_build(s, NULL, req->PageAddress); 866e351b826SPaolo Bonzini if ((ssize_t)length < 0) { 867e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE; 868e351b826SPaolo Bonzini goto out; 869e351b826SPaolo Bonzini } else { 870e351b826SPaolo Bonzini goto done; 871e351b826SPaolo Bonzini } 872e351b826SPaolo Bonzini } 873e351b826SPaolo Bonzini 874e351b826SPaolo Bonzini if (flags_and_length & MPI_SGE_FLAGS_64_BIT_ADDRESSING) { 875e351b826SPaolo Bonzini pa = req->PageBufferSGE.u.Address64; 876e351b826SPaolo Bonzini } else { 877e351b826SPaolo Bonzini pa = req->PageBufferSGE.u.Address32; 878e351b826SPaolo Bonzini } 879e351b826SPaolo Bonzini 880e351b826SPaolo Bonzini /* Only read actions left. */ 881e351b826SPaolo Bonzini length = page->mpt_config_build(s, &data, req->PageAddress); 882e351b826SPaolo Bonzini if ((ssize_t)length < 0) { 883e351b826SPaolo Bonzini reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE; 884e351b826SPaolo Bonzini goto out; 885e351b826SPaolo Bonzini } else { 886e351b826SPaolo Bonzini assert(data[2] == page->number); 887e351b826SPaolo Bonzini pci_dma_write(pci, pa, data, MIN(length, dmalen)); 888e351b826SPaolo Bonzini goto done; 889e351b826SPaolo Bonzini } 890e351b826SPaolo Bonzini 891e351b826SPaolo Bonzini abort(); 892e351b826SPaolo Bonzini 893e351b826SPaolo Bonzini done: 894e351b826SPaolo Bonzini if (type > MPI_CONFIG_PAGETYPE_MASK) { 895e351b826SPaolo Bonzini reply.ExtPageLength = length / 4; 896e351b826SPaolo Bonzini reply.ExtPageType = req->ExtPageType; 897e351b826SPaolo Bonzini } else { 898e351b826SPaolo Bonzini reply.PageLength = length / 4; 899e351b826SPaolo Bonzini } 900e351b826SPaolo Bonzini 901e351b826SPaolo Bonzini out: 902e351b826SPaolo Bonzini mptsas_fix_config_reply_endianness(&reply); 903e351b826SPaolo Bonzini mptsas_reply(s, (MPIDefaultReply *)&reply); 904e351b826SPaolo Bonzini g_free(data); 905e351b826SPaolo Bonzini } 906