Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ahci/ahciem.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2012 Alexander Motin <[email protected]>
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer,
12
* without modification, immediately at the beginning of the file.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
#include <sys/param.h>
30
#include <sys/module.h>
31
#include <sys/systm.h>
32
#include <sys/kernel.h>
33
#include <sys/bus.h>
34
#include <sys/conf.h>
35
#include <sys/endian.h>
36
#include <sys/malloc.h>
37
#include <sys/lock.h>
38
#include <sys/mutex.h>
39
#include <sys/stdarg.h>
40
#include <machine/resource.h>
41
#include <machine/bus.h>
42
#include <sys/rman.h>
43
#include <dev/led/led.h>
44
#include <dev/pci/pcivar.h>
45
#include <dev/pci/pcireg.h>
46
#include "ahci.h"
47
48
#include <cam/cam.h>
49
#include <cam/cam_ccb.h>
50
#include <cam/cam_sim.h>
51
#include <cam/cam_xpt_sim.h>
52
#include <cam/cam_debug.h>
53
#include <cam/scsi/scsi_ses.h>
54
55
/* local prototypes */
56
static void ahciemaction(struct cam_sim *sim, union ccb *ccb);
57
static void ahciempoll(struct cam_sim *sim);
58
static int ahci_em_reset(device_t dev);
59
static void ahci_em_led(void *priv, int onoff);
60
static void ahci_em_setleds(device_t dev, int c);
61
62
static int
63
ahci_em_probe(device_t dev)
64
{
65
66
device_set_desc(dev, "AHCI enclosure management bridge");
67
return (BUS_PROBE_DEFAULT);
68
}
69
70
static int
71
ahci_em_attach(device_t dev)
72
{
73
device_t parent = device_get_parent(dev);
74
struct ahci_controller *ctlr = device_get_softc(parent);
75
struct ahci_enclosure *enc = device_get_softc(dev);
76
struct cam_devq *devq;
77
int i, c, rid, error;
78
char buf[32];
79
80
enc->dev = dev;
81
enc->quirks = ctlr->quirks;
82
enc->channels = ctlr->channels;
83
enc->ichannels = ctlr->ichannels;
84
mtx_init(&enc->mtx, "AHCI enclosure lock", NULL, MTX_DEF);
85
rid = 0;
86
if ((enc->r_memc = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
87
&rid, RF_ACTIVE)) != NULL) {
88
enc->capsem = ATA_INL(enc->r_memc, 0);
89
rid = 1;
90
if (!(enc->r_memt = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
91
&rid, RF_ACTIVE))) {
92
error = ENXIO;
93
goto err0;
94
}
95
} else {
96
enc->capsem = AHCI_EM_XMT | AHCI_EM_SMB | AHCI_EM_LED;
97
enc->r_memt = NULL;
98
}
99
if ((enc->capsem & (AHCI_EM_XMT | AHCI_EM_SMB)) == 0) {
100
rid = 2;
101
if (!(enc->r_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
102
&rid, RF_ACTIVE))) {
103
error = ENXIO;
104
goto err0;
105
}
106
} else
107
enc->r_memr = NULL;
108
mtx_lock(&enc->mtx);
109
if (ahci_em_reset(dev) != 0) {
110
error = ENXIO;
111
goto err1;
112
}
113
rid = ATA_IRQ_RID;
114
/* Create the device queue for our SIM. */
115
devq = cam_simq_alloc(1);
116
if (devq == NULL) {
117
device_printf(dev, "Unable to allocate SIM queue\n");
118
error = ENOMEM;
119
goto err1;
120
}
121
/* Construct SIM entry */
122
enc->sim = cam_sim_alloc(ahciemaction, ahciempoll, "ahciem", enc,
123
device_get_unit(dev), &enc->mtx,
124
1, 0, devq);
125
if (enc->sim == NULL) {
126
cam_simq_free(devq);
127
device_printf(dev, "Unable to allocate SIM\n");
128
error = ENOMEM;
129
goto err1;
130
}
131
if (xpt_bus_register(enc->sim, dev, 0) != CAM_SUCCESS) {
132
device_printf(dev, "unable to register xpt bus\n");
133
error = ENXIO;
134
goto err2;
135
}
136
if (xpt_create_path(&enc->path, /*periph*/NULL, cam_sim_path(enc->sim),
137
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
138
device_printf(dev, "Unable to create path\n");
139
error = ENXIO;
140
goto err3;
141
}
142
mtx_unlock(&enc->mtx);
143
if (bootverbose) {
144
device_printf(dev, "Caps:%s%s%s%s%s%s%s%s\n",
145
(enc->capsem & AHCI_EM_PM) ? " PM":"",
146
(enc->capsem & AHCI_EM_ALHD) ? " ALHD":"",
147
(enc->capsem & AHCI_EM_XMT) ? " XMT":"",
148
(enc->capsem & AHCI_EM_SMB) ? " SMB":"",
149
(enc->capsem & AHCI_EM_SGPIO) ? " SGPIO":"",
150
(enc->capsem & AHCI_EM_SES2) ? " SES-2":"",
151
(enc->capsem & AHCI_EM_SAFTE) ? " SAF-TE":"",
152
(enc->capsem & AHCI_EM_LED) ? " LED":"");
153
}
154
if ((enc->capsem & AHCI_EM_LED)) {
155
for (c = 0; c < enc->channels; c++) {
156
if ((enc->ichannels & (1 << c)) == 0)
157
continue;
158
for (i = 0; i < AHCI_NUM_LEDS; i++) {
159
enc->leds[c * AHCI_NUM_LEDS + i].dev = dev;
160
enc->leds[c * AHCI_NUM_LEDS + i].num =
161
c * AHCI_NUM_LEDS + i;
162
}
163
if ((enc->capsem & AHCI_EM_ALHD) == 0) {
164
snprintf(buf, sizeof(buf), "%s.%d.act",
165
device_get_nameunit(parent), c);
166
enc->leds[c * AHCI_NUM_LEDS + 0].led =
167
led_create(ahci_em_led,
168
&enc->leds[c * AHCI_NUM_LEDS + 0], buf);
169
}
170
snprintf(buf, sizeof(buf), "%s.%d.locate",
171
device_get_nameunit(parent), c);
172
enc->leds[c * AHCI_NUM_LEDS + 1].led =
173
led_create(ahci_em_led,
174
&enc->leds[c * AHCI_NUM_LEDS + 1], buf);
175
snprintf(buf, sizeof(buf), "%s.%d.fault",
176
device_get_nameunit(parent), c);
177
enc->leds[c * AHCI_NUM_LEDS + 2].led =
178
led_create(ahci_em_led,
179
&enc->leds[c * AHCI_NUM_LEDS + 2], buf);
180
}
181
}
182
return (0);
183
184
err3:
185
xpt_bus_deregister(cam_sim_path(enc->sim));
186
err2:
187
cam_sim_free(enc->sim, /*free_devq*/TRUE);
188
err1:
189
mtx_unlock(&enc->mtx);
190
if (enc->r_memr)
191
bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr);
192
err0:
193
if (enc->r_memt)
194
bus_release_resource(dev, SYS_RES_MEMORY, 1, enc->r_memt);
195
if (enc->r_memc)
196
bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc);
197
mtx_destroy(&enc->mtx);
198
return (error);
199
}
200
201
static int
202
ahci_em_detach(device_t dev)
203
{
204
struct ahci_enclosure *enc = device_get_softc(dev);
205
int i;
206
207
for (i = 0; i < enc->channels * AHCI_NUM_LEDS; i++) {
208
if (enc->leds[i].led)
209
led_destroy(enc->leds[i].led);
210
}
211
mtx_lock(&enc->mtx);
212
xpt_async(AC_LOST_DEVICE, enc->path, NULL);
213
xpt_free_path(enc->path);
214
xpt_bus_deregister(cam_sim_path(enc->sim));
215
cam_sim_free(enc->sim, /*free_devq*/TRUE);
216
mtx_unlock(&enc->mtx);
217
218
if (enc->r_memc)
219
bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc);
220
if (enc->r_memt)
221
bus_release_resource(dev, SYS_RES_MEMORY, 1, enc->r_memt);
222
if (enc->r_memr)
223
bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr);
224
mtx_destroy(&enc->mtx);
225
return (0);
226
}
227
228
static int
229
ahci_em_reset(device_t dev)
230
{
231
struct ahci_enclosure *enc;
232
int i, timeout;
233
234
enc = device_get_softc(dev);
235
if (enc->r_memc == NULL)
236
return (0);
237
ATA_OUTL(enc->r_memc, 0, AHCI_EM_RST);
238
timeout = 1000;
239
while ((ATA_INL(enc->r_memc, 0) & AHCI_EM_RST) &&
240
--timeout > 0)
241
DELAY(1000);
242
if (timeout == 0) {
243
device_printf(dev, "EM timeout\n");
244
return (1);
245
}
246
for (i = 0; i < enc->channels; i++)
247
ahci_em_setleds(dev, i);
248
return (0);
249
}
250
251
static int
252
ahci_em_suspend(device_t dev)
253
{
254
struct ahci_enclosure *enc = device_get_softc(dev);
255
256
mtx_lock(&enc->mtx);
257
xpt_freeze_simq(enc->sim, 1);
258
mtx_unlock(&enc->mtx);
259
return (0);
260
}
261
262
static int
263
ahci_em_resume(device_t dev)
264
{
265
struct ahci_enclosure *enc = device_get_softc(dev);
266
267
mtx_lock(&enc->mtx);
268
ahci_em_reset(dev);
269
xpt_release_simq(enc->sim, TRUE);
270
mtx_unlock(&enc->mtx);
271
return (0);
272
}
273
274
static device_method_t ahciem_methods[] = {
275
DEVMETHOD(device_probe, ahci_em_probe),
276
DEVMETHOD(device_attach, ahci_em_attach),
277
DEVMETHOD(device_detach, ahci_em_detach),
278
DEVMETHOD(device_suspend, ahci_em_suspend),
279
DEVMETHOD(device_resume, ahci_em_resume),
280
DEVMETHOD_END
281
};
282
static driver_t ahciem_driver = {
283
"ahciem",
284
ahciem_methods,
285
sizeof(struct ahci_enclosure)
286
};
287
DRIVER_MODULE(ahciem, ahci, ahciem_driver, NULL, NULL);
288
289
static void
290
ahci_em_setleds(device_t dev, int c)
291
{
292
struct ahci_enclosure *enc;
293
int timeout;
294
int16_t val;
295
296
enc = device_get_softc(dev);
297
if (enc->r_memc == NULL)
298
return;
299
300
val = 0;
301
if (enc->status[c][2] & SESCTL_RQSACT) /* Activity */
302
val |= (1 << 0);
303
if (enc->status[c][1] & SESCTL_RQSRR) /* Rebuild */
304
val |= (1 << 6) | (1 << 3);
305
else if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
306
val |= (1 << 3);
307
else if (enc->status[c][3] & SESCTL_RQSFLT) /* Fault */
308
val |= (1 << 6);
309
310
timeout = 10000;
311
while (ATA_INL(enc->r_memc, 0) & (AHCI_EM_TM | AHCI_EM_RST) &&
312
--timeout > 0)
313
DELAY(100);
314
if (timeout == 0)
315
device_printf(dev, "Transmit timeout\n");
316
ATA_OUTL(enc->r_memt, 0, (1 << 8) | (0 << 16) | (0 << 24));
317
ATA_OUTL(enc->r_memt, 4, c | (0 << 8) | (val << 16));
318
ATA_OUTL(enc->r_memc, 0, AHCI_EM_TM);
319
}
320
321
static void
322
ahci_em_led(void *priv, int onoff)
323
{
324
struct ahci_led *led;
325
struct ahci_enclosure *enc;
326
int c, l;
327
328
led = (struct ahci_led *)priv;
329
enc = device_get_softc(led->dev);
330
c = led->num / AHCI_NUM_LEDS;
331
l = led->num % AHCI_NUM_LEDS;
332
333
if (l == 0) {
334
if (onoff)
335
enc->status[c][2] |= 0x80;
336
else
337
enc->status[c][2] &= ~0x80;
338
} else if (l == 1) {
339
if (onoff)
340
enc->status[c][2] |= SESCTL_RQSID;
341
else
342
enc->status[c][2] &= ~SESCTL_RQSID;
343
} else if (l == 2) {
344
if (onoff)
345
enc->status[c][3] |= SESCTL_RQSFLT;
346
else
347
enc->status[c][3] &= SESCTL_RQSFLT;
348
}
349
ahci_em_setleds(led->dev, c);
350
}
351
352
static int
353
ahci_check_ids(union ccb *ccb)
354
{
355
356
if (ccb->ccb_h.target_id != 0) {
357
ccb->ccb_h.status = CAM_TID_INVALID;
358
xpt_done(ccb);
359
return (-1);
360
}
361
if (ccb->ccb_h.target_lun != 0) {
362
ccb->ccb_h.status = CAM_LUN_INVALID;
363
xpt_done(ccb);
364
return (-1);
365
}
366
return (0);
367
}
368
369
static void
370
ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
371
{
372
struct ahci_enclosure *enc;
373
struct ahci_channel *ch;
374
struct ses_status_page *page;
375
struct ses_status_array_dev_slot *ads, *ads0;
376
struct ses_elm_desc_hdr *elmd;
377
struct ses_elm_addlstatus_eip_hdr *elma;
378
struct ses_elm_ata_hdr *elmb;
379
uint8_t *buf;
380
int i;
381
382
enc = device_get_softc(dev);
383
buf = ccb->ataio.data_ptr;
384
385
/* General request validation. */
386
if (ccb->ataio.cmd.command != ATA_SEP_ATTN ||
387
ccb->ataio.dxfer_len < ccb->ataio.cmd.sector_count * 4) {
388
ccb->ccb_h.status = CAM_REQ_INVALID;
389
goto out;
390
}
391
392
/* SEMB IDENTIFY */
393
if (ccb->ataio.cmd.features == 0xEC &&
394
ccb->ataio.cmd.sector_count >= 16) {
395
bzero(buf, ccb->ataio.dxfer_len);
396
buf[0] = 64; /* Valid bytes. */
397
buf[2] = 0x30; /* NAA Locally Assigned. */
398
strncpy(&buf[3], device_get_nameunit(dev), 7);
399
strncpy(&buf[10], "AHCI ", SID_VENDOR_SIZE);
400
strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE);
401
strncpy(&buf[34], "2.00", SID_REVISION_SIZE);
402
strncpy(&buf[39], "0001", 4);
403
strncpy(&buf[43], "S-E-S ", 6);
404
strncpy(&buf[49], "2.00", 4);
405
ccb->ccb_h.status = CAM_REQ_CMP;
406
goto out;
407
}
408
409
/* SEMB RECEIVE DIAGNOSTIC RESULT (0) */
410
page = (struct ses_status_page *)buf;
411
if (ccb->ataio.cmd.lba_low == 0x02 &&
412
ccb->ataio.cmd.features == 0x00 &&
413
ccb->ataio.cmd.sector_count >= 3) {
414
bzero(buf, ccb->ataio.dxfer_len);
415
page->hdr.page_code = 0;
416
scsi_ulto2b(5, page->hdr.length);
417
buf[4] = 0x00;
418
buf[5] = 0x01;
419
buf[6] = 0x02;
420
buf[7] = 0x07;
421
buf[8] = 0x0a;
422
ccb->ccb_h.status = CAM_REQ_CMP;
423
goto out;
424
}
425
426
/* SEMB RECEIVE DIAGNOSTIC RESULT (1) */
427
if (ccb->ataio.cmd.lba_low == 0x02 &&
428
ccb->ataio.cmd.features == 0x01 &&
429
ccb->ataio.cmd.sector_count >= 16) {
430
struct ses_enc_desc *ed;
431
struct ses_elm_type_desc *td;
432
433
bzero(buf, ccb->ataio.dxfer_len);
434
page->hdr.page_code = 0x01;
435
scsi_ulto2b(4 + sizeof(*ed) + sizeof(*td) + 11,
436
page->hdr.length);
437
ed = (struct ses_enc_desc *)&buf[8];
438
ed->byte0 = 0x11;
439
ed->subenc_id = 0;
440
ed->num_types = 1;
441
ed->length = 36;
442
ed->logical_id[0] = 0x30; /* NAA Locally Assigned. */
443
strncpy(&ed->logical_id[1], device_get_nameunit(dev), 7);
444
strncpy(ed->vendor_id, "AHCI ", SID_VENDOR_SIZE);
445
strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE);
446
strncpy(ed->product_rev, "2.00", SID_REVISION_SIZE);
447
td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed);
448
td->etype_elm_type = 0x17;
449
td->etype_maxelt = enc->channels;
450
td->etype_subenc = 0;
451
td->etype_txt_len = 11;
452
snprintf((char *)(td + 1), 12, "Drive Slots");
453
ccb->ccb_h.status = CAM_REQ_CMP;
454
goto out;
455
}
456
457
/* SEMB RECEIVE DIAGNOSTIC RESULT (2) */
458
if (ccb->ataio.cmd.lba_low == 0x02 &&
459
ccb->ataio.cmd.features == 0x02 &&
460
ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
461
bzero(buf, ccb->ataio.dxfer_len);
462
page->hdr.page_code = 0x02;
463
scsi_ulto2b(4 + 4 * (1 + enc->channels),
464
page->hdr.length);
465
for (i = 0; i < enc->channels; i++) {
466
ads = &page->elements[i + 1].array_dev_slot;
467
memcpy(ads, enc->status[i], 4);
468
ch = ahci_getch(device_get_parent(dev), i);
469
if (ch == NULL) {
470
ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
471
continue;
472
}
473
if (ch->pm_present)
474
ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
475
else if (ch->devices)
476
ads->common.bytes[0] |= SES_OBJSTAT_OK;
477
else if (ch->disablephy)
478
ads->common.bytes[0] |= SES_OBJSTAT_NOTAVAIL;
479
else
480
ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED;
481
if (ch->disablephy)
482
ads->common.bytes[3] |= SESCTL_DEVOFF;
483
ahci_putch(ch);
484
}
485
ccb->ccb_h.status = CAM_REQ_CMP;
486
goto out;
487
}
488
489
/* SEMB SEND DIAGNOSTIC (2) */
490
if (ccb->ataio.cmd.lba_low == 0x82 &&
491
ccb->ataio.cmd.features == 0x02 &&
492
ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
493
ads0 = &page->elements[0].array_dev_slot;
494
for (i = 0; i < enc->channels; i++) {
495
ads = &page->elements[i + 1].array_dev_slot;
496
if (ads->common.bytes[0] & SESCTL_CSEL) {
497
enc->status[i][0] = 0;
498
enc->status[i][1] = ads->bytes[0] &
499
SESCTL_RQSRR;
500
enc->status[i][2] = ads->bytes[1] &
501
(SESCTL_RQSACT | SESCTL_RQSID);
502
enc->status[i][3] = ads->bytes[2] &
503
SESCTL_RQSFLT;
504
ahci_em_setleds(dev, i);
505
} else if (ads0->common.bytes[0] & SESCTL_CSEL) {
506
enc->status[i][0] = 0;
507
enc->status[i][1] = ads0->bytes[0] &
508
SESCTL_RQSRR;
509
enc->status[i][2] = ads0->bytes[1] &
510
(SESCTL_RQSACT | SESCTL_RQSID);
511
enc->status[i][3] = ads0->bytes[2] &
512
SESCTL_RQSFLT;
513
ahci_em_setleds(dev, i);
514
}
515
}
516
ccb->ccb_h.status = CAM_REQ_CMP;
517
goto out;
518
}
519
520
/* SEMB RECEIVE DIAGNOSTIC RESULT (7) */
521
if (ccb->ataio.cmd.lba_low == 0x02 &&
522
ccb->ataio.cmd.features == 0x07 &&
523
ccb->ataio.cmd.sector_count >= (6 + 3 * enc->channels)) {
524
bzero(buf, ccb->ataio.dxfer_len);
525
page->hdr.page_code = 0x07;
526
scsi_ulto2b(4 + 15 + 11 * enc->channels, page->hdr.length);
527
elmd = (struct ses_elm_desc_hdr *)&buf[8];
528
scsi_ulto2b(11, elmd->length);
529
snprintf((char *)(elmd + 1), 12, "Drive Slots");
530
for (i = 0; i < enc->channels; i++) {
531
elmd = (struct ses_elm_desc_hdr *)&buf[8 + 15 + 11 * i];
532
scsi_ulto2b(7, elmd->length);
533
snprintf((char *)(elmd + 1), 8, "Slot %02d", i);
534
}
535
ccb->ccb_h.status = CAM_REQ_CMP;
536
goto out;
537
}
538
539
/* SEMB RECEIVE DIAGNOSTIC RESULT (a) */
540
if (ccb->ataio.cmd.lba_low == 0x02 &&
541
ccb->ataio.cmd.features == 0x0a &&
542
ccb->ataio.cmd.sector_count >= (2 + 3 * enc->channels)) {
543
bzero(buf, ccb->ataio.dxfer_len);
544
page->hdr.page_code = 0x0a;
545
scsi_ulto2b(4 + (sizeof(*elma) + sizeof(*elmb)) * enc->channels,
546
page->hdr.length);
547
for (i = 0; i < enc->channels; i++) {
548
elma = (struct ses_elm_addlstatus_eip_hdr *)&buf[
549
8 + (sizeof(*elma) + sizeof(*elmb)) * i];
550
elma->base.byte0 = 0x10 | SPSP_PROTO_ATA;
551
elma->base.length = 2 + sizeof(*elmb);
552
elma->byte2 = 0x01;
553
elma->element_index = 1 + i;
554
ch = ahci_getch(device_get_parent(dev), i);
555
if (ch == NULL) {
556
elma->base.byte0 |= 0x80;
557
continue;
558
}
559
if (ch->devices == 0 || ch->pm_present)
560
elma->base.byte0 |= 0x80;
561
elmb = (struct ses_elm_ata_hdr *)(elma + 1);
562
scsi_ulto4b(cam_sim_path(ch->sim), elmb->bus);
563
scsi_ulto4b(0, elmb->target);
564
ahci_putch(ch);
565
}
566
ccb->ccb_h.status = CAM_REQ_CMP;
567
goto out;
568
}
569
570
ccb->ccb_h.status = CAM_REQ_INVALID;
571
out:
572
xpt_done(ccb);
573
}
574
575
static void
576
ahci_em_begin_transaction(device_t dev, union ccb *ccb)
577
{
578
struct ahci_enclosure *enc;
579
struct ata_res *res;
580
581
enc = device_get_softc(dev);
582
res = &ccb->ataio.res;
583
bzero(res, sizeof(*res));
584
if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
585
(ccb->ataio.cmd.control & ATA_A_RESET)) {
586
res->lba_high = 0xc3;
587
res->lba_mid = 0x3c;
588
ccb->ccb_h.status = CAM_REQ_CMP;
589
xpt_done(ccb);
590
return;
591
}
592
593
if (enc->capsem & AHCI_EM_LED) {
594
ahci_em_emulate_ses_on_led(dev, ccb);
595
return;
596
} else
597
device_printf(dev, "Unsupported enclosure interface\n");
598
599
ccb->ccb_h.status = CAM_REQ_INVALID;
600
xpt_done(ccb);
601
}
602
603
static void
604
ahciemaction(struct cam_sim *sim, union ccb *ccb)
605
{
606
device_t dev, parent;
607
struct ahci_enclosure *enc;
608
609
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
610
("ahciemaction func_code=%x\n", ccb->ccb_h.func_code));
611
612
enc = cam_sim_softc(sim);
613
dev = enc->dev;
614
switch (ccb->ccb_h.func_code) {
615
case XPT_ATA_IO: /* Execute the requested I/O operation */
616
if (ahci_check_ids(ccb))
617
return;
618
ahci_em_begin_transaction(dev, ccb);
619
return;
620
case XPT_RESET_BUS: /* Reset the specified bus */
621
case XPT_RESET_DEV: /* Bus Device Reset the specified device */
622
ahci_em_reset(dev);
623
ccb->ccb_h.status = CAM_REQ_CMP;
624
break;
625
case XPT_PATH_INQ: /* Path routing inquiry */
626
{
627
struct ccb_pathinq *cpi = &ccb->cpi;
628
629
parent = device_get_parent(dev);
630
cpi->version_num = 1; /* XXX??? */
631
cpi->hba_inquiry = PI_SDTR_ABLE;
632
cpi->target_sprt = 0;
633
cpi->hba_misc = PIM_SEQSCAN;
634
cpi->hba_eng_cnt = 0;
635
cpi->max_target = 0;
636
cpi->max_lun = 0;
637
cpi->initiator_id = 0;
638
cpi->bus_id = cam_sim_bus(sim);
639
cpi->base_transfer_speed = 150000;
640
strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
641
strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN);
642
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
643
cpi->unit_number = cam_sim_unit(sim);
644
cpi->transport = XPORT_SATA;
645
cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
646
cpi->protocol = PROTO_ATA;
647
cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
648
cpi->maxio = maxphys;
649
cpi->hba_vendor = pci_get_vendor(parent);
650
cpi->hba_device = pci_get_device(parent);
651
cpi->hba_subvendor = pci_get_subvendor(parent);
652
cpi->hba_subdevice = pci_get_subdevice(parent);
653
cpi->ccb_h.status = CAM_REQ_CMP;
654
break;
655
}
656
default:
657
ccb->ccb_h.status = CAM_REQ_INVALID;
658
break;
659
}
660
xpt_done(ccb);
661
}
662
663
static void
664
ahciempoll(struct cam_sim *sim)
665
{
666
667
}
668
669