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