qemu

Форк
0
/
mptconfig.c 
904 строки · 26.3 Кб
1
/*
2
 * QEMU LSI SAS1068 Host Bus Adapter emulation - configuration pages
3
 *
4
 * Copyright (c) 2016 Red Hat, Inc.
5
 *
6
 * Author: Paolo Bonzini
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 */
18
#include "qemu/osdep.h"
19
#include "hw/pci/pci.h"
20
#include "hw/scsi/scsi.h"
21

22
#include "mptsas.h"
23
#include "mpi.h"
24
#include "trace.h"
25

26
/* Generic functions for marshaling and unmarshaling.  */
27

28
#define repl1(x) x
29
#define repl2(x) x x
30
#define repl3(x) x x x
31
#define repl4(x) x x x x
32
#define repl5(x) x x x x x
33
#define repl6(x) x x x x x x
34
#define repl7(x) x x x x x x x
35
#define repl8(x) x x x x x x x x
36

37
#define repl(n, x) glue(repl, n)(x)
38

39
typedef union PackValue {
40
    uint64_t ll;
41
    char *str;
42
} PackValue;
43

44
static size_t vfill(uint8_t *data, size_t size, const char *fmt, va_list ap)
45
{
46
    size_t ofs;
47
    PackValue val;
48
    const char *p;
49

50
    ofs = 0;
51
    p = fmt;
52
    while (*p) {
53
        memset(&val, 0, sizeof(val));
54
        switch (*p) {
55
        case '*':
56
            p++;
57
            break;
58
        case 'b':
59
        case 'w':
60
        case 'l':
61
            val.ll = va_arg(ap, int);
62
            break;
63
        case 'q':
64
            val.ll = va_arg(ap, int64_t);
65
            break;
66
        case 's':
67
            val.str = va_arg(ap, void *);
68
            break;
69
        }
70
        switch (*p++) {
71
        case 'b':
72
            if (data) {
73
                stb_p(data + ofs, val.ll);
74
            }
75
            ofs++;
76
            break;
77
        case 'w':
78
            if (data) {
79
                stw_le_p(data + ofs, val.ll);
80
            }
81
            ofs += 2;
82
            break;
83
        case 'l':
84
            if (data) {
85
                stl_le_p(data + ofs, val.ll);
86
            }
87
            ofs += 4;
88
            break;
89
        case 'q':
90
            if (data) {
91
                stq_le_p(data + ofs, val.ll);
92
            }
93
            ofs += 8;
94
            break;
95
        case 's':
96
            {
97
                int cnt = atoi(p);
98
                if (data) {
99
                    if (val.str) {
100
                        strncpy((void *)data + ofs, val.str, cnt);
101
                    } else {
102
                        memset((void *)data + ofs, 0, cnt);
103
                    }
104
                }
105
                ofs += cnt;
106
                break;
107
            }
108
        }
109
    }
110

111
    return ofs;
112
}
113

114
static size_t vpack(uint8_t **p_data, const char *fmt, va_list ap1)
115
{
116
    size_t size = 0;
117
    uint8_t *data = NULL;
118

119
    if (p_data) {
120
        va_list ap2;
121

122
        va_copy(ap2, ap1);
123
        size = vfill(NULL, 0, fmt, ap2);
124
        *p_data = data = g_malloc(size);
125
        va_end(ap2);
126
    }
127
    return vfill(data, size, fmt, ap1);
128
}
129

130
static size_t fill(uint8_t *data, size_t size, const char *fmt, ...)
131
{
132
    va_list ap;
133
    size_t ret;
134

135
    va_start(ap, fmt);
136
    ret = vfill(data, size, fmt, ap);
137
    va_end(ap);
138

139
    return ret;
140
}
141

142
/* Functions to build the page header and fill in the length, always used
143
 * through the macros.
144
 */
145

146
#define MPTSAS_CONFIG_PACK(number, type, version, fmt, ...)                  \
147
    mptsas_config_pack(data, "b*bbb" fmt, version, number, type,             \
148
                       ## __VA_ARGS__)
149

150
static size_t mptsas_config_pack(uint8_t **data, const char *fmt, ...)
151
{
152
    va_list ap;
153
    size_t ret;
154

155
    va_start(ap, fmt);
156
    ret = vpack(data, fmt, ap);
157
    va_end(ap);
158

159
    if (data) {
160
        assert(ret / 4 < 256 && (ret % 4) == 0);
161
        stb_p(*data + 1, ret / 4);
162
    }
163
    return ret;
164
}
165

166
#define MPTSAS_CONFIG_PACK_EXT(number, type, version, fmt, ...)              \
167
    mptsas_config_pack_ext(data, "b*bbb*wb*b" fmt, version, number,          \
168
                           MPI_CONFIG_PAGETYPE_EXTENDED, type, ## __VA_ARGS__)
169

170
static size_t mptsas_config_pack_ext(uint8_t **data, const char *fmt, ...)
171
{
172
    va_list ap;
173
    size_t ret;
174

175
    va_start(ap, fmt);
176
    ret = vpack(data, fmt, ap);
177
    va_end(ap);
178

179
    if (data) {
180
        assert(ret < 65536 && (ret % 4) == 0);
181
        stw_le_p(*data + 4, ret / 4);
182
    }
183
    return ret;
184
}
185

186
/* Manufacturing pages */
187

188
static
189
size_t mptsas_config_manufacturing_0(MPTSASState *s, uint8_t **data, int address)
190
{
191
    return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
192
                              "s16s8s16s16s16",
193
                              "QEMU MPT Fusion",
194
                              "2.5",
195
                              "QEMU MPT Fusion",
196
                              "QEMU",
197
                              "0000111122223333");
198
}
199

200
static
201
size_t mptsas_config_manufacturing_1(MPTSASState *s, uint8_t **data, int address)
202
{
203
    /* VPD - all zeros */
204
    return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
205
                              "*s256");
206
}
207

208
static
209
size_t mptsas_config_manufacturing_2(MPTSASState *s, uint8_t **data, int address)
210
{
211
    PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s);
212
    return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
213
                              "wb*b*l",
214
                              pcic->device_id, pcic->revision);
215
}
216

217
static
218
size_t mptsas_config_manufacturing_3(MPTSASState *s, uint8_t **data, int address)
219
{
220
    PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s);
221
    return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
222
                              "wb*b*l",
223
                              pcic->device_id, pcic->revision);
224
}
225

226
static
227
size_t mptsas_config_manufacturing_4(MPTSASState *s, uint8_t **data, int address)
228
{
229
    /* All zeros */
230
    return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x05,
231
                              "*l*b*b*b*b*b*b*w*s56*l*l*l*l*l*l"
232
                              "*b*b*w*b*b*w*l*l");
233
}
234

235
static
236
size_t mptsas_config_manufacturing_5(MPTSASState *s, uint8_t **data, int address)
237
{
238
    return MPTSAS_CONFIG_PACK(5, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x02,
239
                              "q*b*b*w*l*l", s->sas_addr);
240
}
241

242
static
243
size_t mptsas_config_manufacturing_6(MPTSASState *s, uint8_t **data, int address)
244
{
245
    return MPTSAS_CONFIG_PACK(6, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
246
                              "*l");
247
}
248

249
static
250
size_t mptsas_config_manufacturing_7(MPTSASState *s, uint8_t **data, int address)
251
{
252
    return MPTSAS_CONFIG_PACK(7, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
253
                              "*l*l*l*s16*b*b*w", MPTSAS_NUM_PORTS);
254
}
255

256
static
257
size_t mptsas_config_manufacturing_8(MPTSASState *s, uint8_t **data, int address)
258
{
259
    return MPTSAS_CONFIG_PACK(8, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
260
                              "*l");
261
}
262

263
static
264
size_t mptsas_config_manufacturing_9(MPTSASState *s, uint8_t **data, int address)
265
{
266
    return MPTSAS_CONFIG_PACK(9, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
267
                              "*l");
268
}
269

270
static
271
size_t mptsas_config_manufacturing_10(MPTSASState *s, uint8_t **data, int address)
272
{
273
    return MPTSAS_CONFIG_PACK(10, MPI_CONFIG_PAGETYPE_MANUFACTURING, 0x00,
274
                              "*l");
275
}
276

277
/* I/O unit pages */
278

279
static
280
size_t mptsas_config_io_unit_0(MPTSASState *s, uint8_t **data, int address)
281
{
282
    PCIDevice *pci = PCI_DEVICE(s);
283
    uint64_t unique_value = 0x53504D554D4551LL;  /* "QEMUMPTx" */
284

285
    unique_value |= (uint64_t)pci->devfn << 56;
286
    return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x00,
287
                              "q", unique_value);
288
}
289

290
static
291
size_t mptsas_config_io_unit_1(MPTSASState *s, uint8_t **data, int address)
292
{
293
    return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x02, "l",
294
                              0x41 /* single function, RAID disabled */ );
295
}
296

297
static
298
size_t mptsas_config_io_unit_2(MPTSASState *s, uint8_t **data, int address)
299
{
300
    PCIDevice *pci = PCI_DEVICE(s);
301
    uint8_t devfn = pci->devfn;
302
    return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x02,
303
                              "llbbw*b*b*w*b*b*w*b*b*w*l",
304
                              0, 0x100, 0 /* pci bus? */, devfn, 0);
305
}
306

307
static
308
size_t mptsas_config_io_unit_3(MPTSASState *s, uint8_t **data, int address)
309
{
310
    return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x01,
311
                              "*b*b*w*l");
312
}
313

314
static
315
size_t mptsas_config_io_unit_4(MPTSASState *s, uint8_t **data, int address)
316
{
317
    return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_IO_UNIT, 0x00, "*l*l*q");
318
}
319

320
/* I/O controller pages */
321

322
static
323
size_t mptsas_config_ioc_0(MPTSASState *s, uint8_t **data, int address)
324
{
325
    PCIDeviceClass *pcic = PCI_DEVICE_GET_CLASS(s);
326

327
    return MPTSAS_CONFIG_PACK(0, MPI_CONFIG_PAGETYPE_IOC, 0x01,
328
                              "*l*lwwb*b*b*blww",
329
                              pcic->vendor_id, pcic->device_id, pcic->revision,
330
                              pcic->class_id, pcic->subsystem_vendor_id,
331
                              pcic->subsystem_id);
332
}
333

334
static
335
size_t mptsas_config_ioc_1(MPTSASState *s, uint8_t **data, int address)
336
{
337
    return MPTSAS_CONFIG_PACK(1, MPI_CONFIG_PAGETYPE_IOC, 0x03,
338
                              "*l*l*b*b*b*b");
339
}
340

341
static
342
size_t mptsas_config_ioc_2(MPTSASState *s, uint8_t **data, int address)
343
{
344
    return MPTSAS_CONFIG_PACK(2, MPI_CONFIG_PAGETYPE_IOC, 0x04,
345
                              "*l*b*b*b*b");
346
}
347

348
static
349
size_t mptsas_config_ioc_3(MPTSASState *s, uint8_t **data, int address)
350
{
351
    return MPTSAS_CONFIG_PACK(3, MPI_CONFIG_PAGETYPE_IOC, 0x00,
352
                              "*b*b*w");
353
}
354

355
static
356
size_t mptsas_config_ioc_4(MPTSASState *s, uint8_t **data, int address)
357
{
358
    return MPTSAS_CONFIG_PACK(4, MPI_CONFIG_PAGETYPE_IOC, 0x00,
359
                              "*b*b*w");
360
}
361

362
static
363
size_t mptsas_config_ioc_5(MPTSASState *s, uint8_t **data, int address)
364
{
365
    return MPTSAS_CONFIG_PACK(5, MPI_CONFIG_PAGETYPE_IOC, 0x00,
366
                              "*l*b*b*w");
367
}
368

369
static
370
size_t mptsas_config_ioc_6(MPTSASState *s, uint8_t **data, int address)
371
{
372
    return MPTSAS_CONFIG_PACK(6, MPI_CONFIG_PAGETYPE_IOC, 0x01,
373
                              "*l*b*b*b*b*b*b*b*b*b*b*w*l*l*l*l*b*b*w"
374
                              "*w*w*w*w*l*l*l");
375
}
376

377
/* SAS I/O unit pages (extended) */
378

379
#define MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE 16
380

381
#define MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION 0x02
382
#define MPI_SAS_IOUNIT0_RATE_1_5                      0x08
383
#define MPI_SAS_IOUNIT0_RATE_3_0                      0x09
384

385
#define MPI_SAS_DEVICE_INFO_NO_DEVICE                 0x00000000
386
#define MPI_SAS_DEVICE_INFO_END_DEVICE                0x00000001
387
#define MPI_SAS_DEVICE_INFO_SSP_TARGET                0x00000400
388

389
#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS             0x00
390

391
#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT          0x0001
392
#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED           0x0002
393
#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT      0x0004
394

395

396

397
static SCSIDevice *mptsas_phy_get_device(MPTSASState *s, int i,
398
                                         int *phy_handle, int *dev_handle)
399
{
400
    SCSIDevice *d = scsi_device_find(&s->bus, 0, i, 0);
401

402
    if (phy_handle) {
403
        *phy_handle = i + 1;
404
    }
405
    if (dev_handle) {
406
        *dev_handle = d ? i + 1 + MPTSAS_NUM_PORTS : 0;
407
    }
408
    return d;
409
}
410

411
static
412
size_t mptsas_config_sas_io_unit_0(MPTSASState *s, uint8_t **data, int address)
413
{
414
    size_t size = MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x04,
415
                                         "*w*wb*b*w"
416
                                         repl(MPTSAS_NUM_PORTS, "*s16"),
417
                                         MPTSAS_NUM_PORTS);
418

419
    if (data) {
420
        size_t ofs = size - MPTSAS_NUM_PORTS * MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE;
421
        int i;
422

423
        for (i = 0; i < MPTSAS_NUM_PORTS; i++) {
424
            int phy_handle, dev_handle;
425
            SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
426

427
            fill(*data + ofs, MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE,
428
                 "bbbblwwl", i, 0, 0,
429
                 (dev
430
                  ? MPI_SAS_IOUNIT0_RATE_3_0
431
                  : MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION),
432
                 (dev
433
                  ? MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET
434
                  : MPI_SAS_DEVICE_INFO_NO_DEVICE),
435
                 dev_handle,
436
                 dev_handle,
437
                 0);
438
            ofs += MPTSAS_CONFIG_SAS_IO_UNIT_0_SIZE;
439
        }
440
        assert(ofs == size);
441
    }
442
    return size;
443
}
444

445
#define MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE 12
446

447
static
448
size_t mptsas_config_sas_io_unit_1(MPTSASState *s, uint8_t **data, int address)
449
{
450
    size_t size = MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x07,
451
                                         "*w*w*w*wb*b*b*b"
452
                                         repl(MPTSAS_NUM_PORTS, "*s12"),
453
                                         MPTSAS_NUM_PORTS);
454

455
    if (data) {
456
        size_t ofs = size - MPTSAS_NUM_PORTS * MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE;
457
        int i;
458

459
        for (i = 0; i < MPTSAS_NUM_PORTS; i++) {
460
            SCSIDevice *dev = mptsas_phy_get_device(s, i, NULL, NULL);
461
            fill(*data + ofs, MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE,
462
                 "bbbblww", i, 0, 0,
463
                 (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5,
464
                 (dev
465
                  ? MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET
466
                  : MPI_SAS_DEVICE_INFO_NO_DEVICE),
467
                 0, 0);
468
            ofs += MPTSAS_CONFIG_SAS_IO_UNIT_1_SIZE;
469
        }
470
        assert(ofs == size);
471
    }
472
    return size;
473
}
474

475
static
476
size_t mptsas_config_sas_io_unit_2(MPTSASState *s, uint8_t **data, int address)
477
{
478
    return MPTSAS_CONFIG_PACK_EXT(2, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x06,
479
                                  "*b*b*w*w*w*b*b*w");
480
}
481

482
static
483
size_t mptsas_config_sas_io_unit_3(MPTSASState *s, uint8_t **data, int address)
484
{
485
    return MPTSAS_CONFIG_PACK_EXT(3, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, 0x06,
486
                                  "*l*l*l*l*l*l*l*l*l");
487
}
488

489
/* SAS PHY pages (extended) */
490

491
static int mptsas_phy_addr_get(MPTSASState *s, int address)
492
{
493
    int i;
494
    if ((address >> MPI_SAS_PHY_PGAD_FORM_SHIFT) == 0) {
495
        i = address & 255;
496
    } else if ((address >> MPI_SAS_PHY_PGAD_FORM_SHIFT) == 1) {
497
        i = address & 65535;
498
    } else {
499
        return -EINVAL;
500
    }
501

502
    if (i >= MPTSAS_NUM_PORTS) {
503
        return -EINVAL;
504
    }
505

506
    return i;
507
}
508

509
static
510
size_t mptsas_config_phy_0(MPTSASState *s, uint8_t **data, int address)
511
{
512
    int phy_handle = -1;
513
    int dev_handle = -1;
514
    int i = mptsas_phy_addr_get(s, address);
515
    SCSIDevice *dev;
516

517
    if (i < 0) {
518
        trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 0);
519
        return i;
520
    }
521

522
    dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
523
    trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 0);
524

525
    return MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0x01,
526
                                  "w*wqwb*blbb*b*b*l",
527
                                  dev_handle, s->sas_addr, dev_handle, i,
528
                                  (dev
529
                                   ? MPI_SAS_DEVICE_INFO_END_DEVICE /* | MPI_SAS_DEVICE_INFO_SSP_TARGET?? */
530
                                   : MPI_SAS_DEVICE_INFO_NO_DEVICE),
531
                                  (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5,
532
                                  (MPI_SAS_IOUNIT0_RATE_3_0 << 4) | MPI_SAS_IOUNIT0_RATE_1_5);
533
}
534

535
static
536
size_t mptsas_config_phy_1(MPTSASState *s, uint8_t **data, int address)
537
{
538
    int phy_handle = -1;
539
    int dev_handle = -1;
540
    int i = mptsas_phy_addr_get(s, address);
541

542
    if (i < 0) {
543
        trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 1);
544
        return i;
545
    }
546

547
    (void) mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
548
    trace_mptsas_config_sas_phy(s, address, i, phy_handle, dev_handle, 1);
549

550
    return MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_PHY, 0x01,
551
                                  "*l*l*l*l*l");
552
}
553

554
/* SAS device pages (extended) */
555

556
static int mptsas_device_addr_get(MPTSASState *s, int address)
557
{
558
    uint32_t handle, i;
559
    uint32_t form = address >> MPI_SAS_PHY_PGAD_FORM_SHIFT;
560
    if (form == MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) {
561
        handle = address & MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK;
562
        do {
563
            if (handle == 65535) {
564
                handle = MPTSAS_NUM_PORTS + 1;
565
            } else {
566
                ++handle;
567
            }
568
            i = handle - 1 - MPTSAS_NUM_PORTS;
569
        } while (i < MPTSAS_NUM_PORTS && !scsi_device_find(&s->bus, 0, i, 0));
570

571
    } else if (form == MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID) {
572
        if (address & MPI_SAS_DEVICE_PGAD_BT_BUS_MASK) {
573
            return -EINVAL;
574
        }
575
        i = address & MPI_SAS_DEVICE_PGAD_BT_TID_MASK;
576

577
    } else if (form == MPI_SAS_DEVICE_PGAD_FORM_HANDLE) {
578
        handle = address & MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK;
579
        i = handle - 1 - MPTSAS_NUM_PORTS;
580

581
    } else {
582
        return -EINVAL;
583
    }
584

585
    if (i >= MPTSAS_NUM_PORTS) {
586
        return -EINVAL;
587
    }
588

589
    return i;
590
}
591

592
static
593
size_t mptsas_config_sas_device_0(MPTSASState *s, uint8_t **data, int address)
594
{
595
    int phy_handle = -1;
596
    int dev_handle = -1;
597
    int i = mptsas_device_addr_get(s, address);
598
    SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
599

600
    trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 0);
601
    if (!dev) {
602
        return -ENOENT;
603
    }
604

605
    return MPTSAS_CONFIG_PACK_EXT(0, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x05,
606
                                  "*w*wqwbbwbblwb*b",
607
                                  dev->wwn, phy_handle, i,
608
                                  MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS,
609
                                  dev_handle, i, 0,
610
                                  MPI_SAS_DEVICE_INFO_END_DEVICE | MPI_SAS_DEVICE_INFO_SSP_TARGET,
611
                                  (MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT |
612
                                   MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED |
613
                                   MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT), i);
614
}
615

616
static
617
size_t mptsas_config_sas_device_1(MPTSASState *s, uint8_t **data, int address)
618
{
619
    int phy_handle = -1;
620
    int dev_handle = -1;
621
    int i = mptsas_device_addr_get(s, address);
622
    SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
623

624
    trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 1);
625
    if (!dev) {
626
        return -ENOENT;
627
    }
628

629
    return MPTSAS_CONFIG_PACK_EXT(1, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x00,
630
                                  "*lq*lwbb*s20",
631
                                  dev->wwn, dev_handle, i, 0);
632
}
633

634
static
635
size_t mptsas_config_sas_device_2(MPTSASState *s, uint8_t **data, int address)
636
{
637
    int phy_handle = -1;
638
    int dev_handle = -1;
639
    int i = mptsas_device_addr_get(s, address);
640
    SCSIDevice *dev = mptsas_phy_get_device(s, i, &phy_handle, &dev_handle);
641

642
    trace_mptsas_config_sas_device(s, address, i, phy_handle, dev_handle, 2);
643
    if (!dev) {
644
        return -ENOENT;
645
    }
646

647
    return MPTSAS_CONFIG_PACK_EXT(2, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE, 0x01,
648
                                  "ql", dev->wwn, 0);
649
}
650

651
typedef struct MPTSASConfigPage {
652
    uint8_t number;
653
    uint8_t type;
654
    size_t (*mpt_config_build)(MPTSASState *s, uint8_t **data, int address);
655
} MPTSASConfigPage;
656

657
static const MPTSASConfigPage mptsas_config_pages[] = {
658
    {
659
        0, MPI_CONFIG_PAGETYPE_MANUFACTURING,
660
        mptsas_config_manufacturing_0,
661
    }, {
662
        1, MPI_CONFIG_PAGETYPE_MANUFACTURING,
663
        mptsas_config_manufacturing_1,
664
    }, {
665
        2, MPI_CONFIG_PAGETYPE_MANUFACTURING,
666
        mptsas_config_manufacturing_2,
667
    }, {
668
        3, MPI_CONFIG_PAGETYPE_MANUFACTURING,
669
        mptsas_config_manufacturing_3,
670
    }, {
671
        4, MPI_CONFIG_PAGETYPE_MANUFACTURING,
672
        mptsas_config_manufacturing_4,
673
    }, {
674
        5, MPI_CONFIG_PAGETYPE_MANUFACTURING,
675
        mptsas_config_manufacturing_5,
676
    }, {
677
        6, MPI_CONFIG_PAGETYPE_MANUFACTURING,
678
        mptsas_config_manufacturing_6,
679
    }, {
680
        7, MPI_CONFIG_PAGETYPE_MANUFACTURING,
681
        mptsas_config_manufacturing_7,
682
    }, {
683
        8, MPI_CONFIG_PAGETYPE_MANUFACTURING,
684
        mptsas_config_manufacturing_8,
685
    }, {
686
        9, MPI_CONFIG_PAGETYPE_MANUFACTURING,
687
        mptsas_config_manufacturing_9,
688
    }, {
689
        10, MPI_CONFIG_PAGETYPE_MANUFACTURING,
690
        mptsas_config_manufacturing_10,
691
    }, {
692
        0, MPI_CONFIG_PAGETYPE_IO_UNIT,
693
        mptsas_config_io_unit_0,
694
    }, {
695
        1, MPI_CONFIG_PAGETYPE_IO_UNIT,
696
        mptsas_config_io_unit_1,
697
    }, {
698
        2, MPI_CONFIG_PAGETYPE_IO_UNIT,
699
        mptsas_config_io_unit_2,
700
    }, {
701
        3, MPI_CONFIG_PAGETYPE_IO_UNIT,
702
        mptsas_config_io_unit_3,
703
    }, {
704
        4, MPI_CONFIG_PAGETYPE_IO_UNIT,
705
        mptsas_config_io_unit_4,
706
    }, {
707
        0, MPI_CONFIG_PAGETYPE_IOC,
708
        mptsas_config_ioc_0,
709
    }, {
710
        1, MPI_CONFIG_PAGETYPE_IOC,
711
        mptsas_config_ioc_1,
712
    }, {
713
        2, MPI_CONFIG_PAGETYPE_IOC,
714
        mptsas_config_ioc_2,
715
    }, {
716
        3, MPI_CONFIG_PAGETYPE_IOC,
717
        mptsas_config_ioc_3,
718
    }, {
719
        4, MPI_CONFIG_PAGETYPE_IOC,
720
        mptsas_config_ioc_4,
721
    }, {
722
        5, MPI_CONFIG_PAGETYPE_IOC,
723
        mptsas_config_ioc_5,
724
    }, {
725
        6, MPI_CONFIG_PAGETYPE_IOC,
726
        mptsas_config_ioc_6,
727
    }, {
728
        0, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
729
        mptsas_config_sas_io_unit_0,
730
    }, {
731
        1, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
732
        mptsas_config_sas_io_unit_1,
733
    }, {
734
        2, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
735
        mptsas_config_sas_io_unit_2,
736
    }, {
737
        3, MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT,
738
        mptsas_config_sas_io_unit_3,
739
    }, {
740
        0, MPI_CONFIG_EXTPAGETYPE_SAS_PHY,
741
        mptsas_config_phy_0,
742
    }, {
743
        1, MPI_CONFIG_EXTPAGETYPE_SAS_PHY,
744
        mptsas_config_phy_1,
745
    }, {
746
        0, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
747
        mptsas_config_sas_device_0,
748
    }, {
749
        1, MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
750
        mptsas_config_sas_device_1,
751
    }, {
752
       2,  MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE,
753
        mptsas_config_sas_device_2,
754
    }
755
};
756

757
static const MPTSASConfigPage *mptsas_find_config_page(int type, int number)
758
{
759
    const MPTSASConfigPage *page;
760
    int i;
761

762
    for (i = 0; i < ARRAY_SIZE(mptsas_config_pages); i++) {
763
        page = &mptsas_config_pages[i];
764
        if (page->type == type && page->number == number) {
765
            return page;
766
        }
767
    }
768

769
    return NULL;
770
}
771

772
void mptsas_process_config(MPTSASState *s, MPIMsgConfig *req)
773
{
774
    PCIDevice *pci = PCI_DEVICE(s);
775

776
    MPIMsgConfigReply reply;
777
    const MPTSASConfigPage *page;
778
    size_t length;
779
    uint8_t type;
780
    uint8_t *data = NULL;
781
    uint32_t flags_and_length;
782
    uint32_t dmalen;
783
    uint64_t pa;
784

785
    mptsas_fix_config_endianness(req);
786

787
    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_msg) < sizeof(*req));
788
    QEMU_BUILD_BUG_ON(sizeof(s->doorbell_reply) < sizeof(reply));
789

790
    /* Copy common bits from the request into the reply. */
791
    memset(&reply, 0, sizeof(reply));
792
    reply.Action      = req->Action;
793
    reply.Function    = req->Function;
794
    reply.MsgContext  = req->MsgContext;
795
    reply.MsgLength   = sizeof(reply) / 4;
796
    reply.PageType    = req->PageType;
797
    reply.PageNumber  = req->PageNumber;
798
    reply.PageLength  = req->PageLength;
799
    reply.PageVersion = req->PageVersion;
800

801
    type = req->PageType & MPI_CONFIG_PAGETYPE_MASK;
802
    if (type == MPI_CONFIG_PAGETYPE_EXTENDED) {
803
        type = req->ExtPageType;
804
        if (type <= MPI_CONFIG_PAGETYPE_MASK) {
805
            reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_TYPE;
806
            goto out;
807
        }
808

809
        reply.ExtPageType = req->ExtPageType;
810
    }
811

812
    page = mptsas_find_config_page(type, req->PageNumber);
813

814
    switch(req->Action) {
815
    case MPI_CONFIG_ACTION_PAGE_DEFAULT:
816
    case MPI_CONFIG_ACTION_PAGE_HEADER:
817
    case MPI_CONFIG_ACTION_PAGE_READ_NVRAM:
818
    case MPI_CONFIG_ACTION_PAGE_READ_CURRENT:
819
    case MPI_CONFIG_ACTION_PAGE_READ_DEFAULT:
820
    case MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT:
821
    case MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM:
822
        break;
823

824
    default:
825
        reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_ACTION;
826
        goto out;
827
    }
828

829
    if (!page) {
830
        page = mptsas_find_config_page(type, 1);
831
        if (page) {
832
            reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
833
        } else {
834
            reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_TYPE;
835
        }
836
        goto out;
837
    }
838

839
    if (req->Action == MPI_CONFIG_ACTION_PAGE_DEFAULT ||
840
        req->Action == MPI_CONFIG_ACTION_PAGE_HEADER) {
841
        length = page->mpt_config_build(s, NULL, req->PageAddress);
842
        if ((ssize_t)length < 0) {
843
            reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
844
            goto out;
845
        } else {
846
            goto done;
847
        }
848
    }
849

850
    if (req->Action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT ||
851
        req->Action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM) {
852
        length = page->mpt_config_build(s, NULL, req->PageAddress);
853
        if ((ssize_t)length < 0) {
854
            reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
855
        } else {
856
            reply.IOCStatus = MPI_IOCSTATUS_CONFIG_CANT_COMMIT;
857
        }
858
        goto out;
859
    }
860

861
    flags_and_length = req->PageBufferSGE.FlagsLength;
862
    dmalen = flags_and_length & MPI_SGE_LENGTH_MASK;
863
    if (dmalen == 0) {
864
        length = page->mpt_config_build(s, NULL, req->PageAddress);
865
        if ((ssize_t)length < 0) {
866
            reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
867
            goto out;
868
        } else {
869
            goto done;
870
        }
871
    }
872

873
    if (flags_and_length & MPI_SGE_FLAGS_64_BIT_ADDRESSING) {
874
        pa = req->PageBufferSGE.u.Address64;
875
    } else {
876
        pa = req->PageBufferSGE.u.Address32;
877
    }
878

879
    /* Only read actions left.  */
880
    length = page->mpt_config_build(s, &data, req->PageAddress);
881
    if ((ssize_t)length < 0) {
882
        reply.IOCStatus = MPI_IOCSTATUS_CONFIG_INVALID_PAGE;
883
        goto out;
884
    } else {
885
        assert(data[2] == page->number);
886
        pci_dma_write(pci, pa, data, MIN(length, dmalen));
887
        goto done;
888
    }
889

890
    abort();
891

892
done:
893
    if (type > MPI_CONFIG_PAGETYPE_MASK) {
894
        reply.ExtPageLength = length / 4;
895
        reply.ExtPageType   = req->ExtPageType;
896
    } else {
897
        reply.PageLength    = length / 4;
898
    }
899

900
out:
901
    mptsas_fix_config_reply_endianness(&reply);
902
    mptsas_reply(s, (MPIDefaultReply *)&reply);
903
    g_free(data);
904
}
905

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.