Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/cam/cam.c
39475 views
1
/*-
2
* Generic utility routines for the Common Access Method layer.
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*
6
* Copyright (c) 1997 Justin T. Gibbs.
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions, and the following disclaimer,
14
* without modification, immediately at the beginning of the file.
15
* 2. The name of the author may not be used to endorse or promote products
16
* derived from this software without specific prior written permission.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*/
30
31
#include <sys/param.h>
32
#ifdef _KERNEL
33
#include <sys/systm.h>
34
#include <sys/kernel.h>
35
#include <sys/memdesc.h>
36
#include <sys/sysctl.h>
37
#else /* _KERNEL */
38
#include <stdlib.h>
39
#include <stdio.h>
40
#include <string.h>
41
#include <camlib.h>
42
#endif /* _KERNEL */
43
44
#include <cam/cam.h>
45
#include <cam/cam_ccb.h>
46
#include <cam/scsi/scsi_all.h>
47
#include <cam/scsi/smp_all.h>
48
#include <sys/sbuf.h>
49
50
#ifdef _KERNEL
51
#include <sys/libkern.h>
52
#include <machine/bus.h>
53
#include <cam/cam_queue.h>
54
#include <cam/cam_xpt.h>
55
56
FEATURE(scbus, "SCSI devices support");
57
58
#endif
59
60
static int camstatusentrycomp(const void *key, const void *member);
61
62
const struct cam_status_entry cam_status_table[] = {
63
{ CAM_REQ_INPROG, "CCB request is in progress" },
64
{ CAM_REQ_CMP, "CCB request completed without error" },
65
{ CAM_REQ_ABORTED, "CCB request aborted by the host" },
66
{ CAM_UA_ABORT, "Unable to abort CCB request" },
67
{ CAM_REQ_CMP_ERR, "CCB request completed with an error" },
68
{ CAM_BUSY, "CAM subsystem is busy" },
69
{ CAM_REQ_INVALID, "CCB request was invalid" },
70
{ CAM_PATH_INVALID, "Supplied Path ID is invalid" },
71
{ CAM_DEV_NOT_THERE, "Device Not Present" },
72
{ CAM_UA_TERMIO, "Unable to terminate I/O CCB request" },
73
{ CAM_SEL_TIMEOUT, "Selection Timeout" },
74
{ CAM_CMD_TIMEOUT, "Command timeout" },
75
{ CAM_SCSI_STATUS_ERROR, "SCSI Status Error" },
76
{ CAM_MSG_REJECT_REC, "Message Reject Reveived" },
77
{ CAM_SCSI_BUS_RESET, "SCSI Bus Reset Sent/Received" },
78
{ CAM_UNCOR_PARITY, "Uncorrectable parity/CRC error" },
79
{ CAM_AUTOSENSE_FAIL, "Auto-Sense Retrieval Failed" },
80
{ CAM_NO_HBA, "No HBA Detected" },
81
{ CAM_DATA_RUN_ERR, "Data Overrun error" },
82
{ CAM_UNEXP_BUSFREE, "Unexpected Bus Free" },
83
{ CAM_SEQUENCE_FAIL, "Target Bus Phase Sequence Failure" },
84
{ CAM_CCB_LEN_ERR, "CCB length supplied is inadequate" },
85
{ CAM_PROVIDE_FAIL, "Unable to provide requested capability" },
86
{ CAM_BDR_SENT, "SCSI BDR Message Sent" },
87
{ CAM_REQ_TERMIO, "CCB request terminated by the host" },
88
{ CAM_UNREC_HBA_ERROR, "Unrecoverable Host Bus Adapter Error" },
89
{ CAM_REQ_TOO_BIG, "The request was too large for this host" },
90
{ CAM_REQUEUE_REQ, "Unconditionally Re-queue Request" },
91
{ CAM_ATA_STATUS_ERROR, "ATA Status Error" },
92
{ CAM_SCSI_IT_NEXUS_LOST,"Initiator/Target Nexus Lost" },
93
{ CAM_SMP_STATUS_ERROR, "SMP Status Error" },
94
{ CAM_REQ_SOFTTIMEOUT, "Completed w/o error, but took too long" },
95
{ CAM_NVME_STATUS_ERROR, "NVME Status Error" },
96
{ CAM_IDE, "Initiator Detected Error Message Received" },
97
{ CAM_RESRC_UNAVAIL, "Resource Unavailable" },
98
{ CAM_UNACKED_EVENT, "Unacknowledged Event by Host" },
99
{ CAM_MESSAGE_RECV, "Message Received in Host Target Mode" },
100
{ CAM_INVALID_CDB, "Invalid CDB received in Host Target Mode" },
101
{ CAM_LUN_INVALID, "Invalid Lun" },
102
{ CAM_TID_INVALID, "Invalid Target ID" },
103
{ CAM_FUNC_NOTAVAIL, "Function Not Available" },
104
{ CAM_NO_NEXUS, "Nexus Not Established" },
105
{ CAM_IID_INVALID, "Invalid Initiator ID" },
106
{ CAM_CDB_RECVD, "CDB Received" },
107
{ CAM_LUN_ALRDY_ENA, "LUN Already Enabled for Target Mode" },
108
{ CAM_SCSI_BUSY, "SCSI Bus Busy" },
109
};
110
111
#ifdef _KERNEL
112
SYSCTL_NODE(_kern, OID_AUTO, cam, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
113
"CAM Subsystem");
114
115
#ifndef CAM_DEFAULT_SORT_IO_QUEUES
116
#define CAM_DEFAULT_SORT_IO_QUEUES 1
117
#endif
118
119
int cam_sort_io_queues = CAM_DEFAULT_SORT_IO_QUEUES;
120
SYSCTL_INT(_kern_cam, OID_AUTO, sort_io_queues, CTLFLAG_RWTUN,
121
&cam_sort_io_queues, 0, "Sort IO queues to try and optimise disk access patterns");
122
#endif
123
124
void
125
cam_strvis(uint8_t *dst, const uint8_t *src, int srclen, int dstlen)
126
{
127
cam_strvis_flag(dst, src, srclen, dstlen,
128
CAM_STRVIS_FLAG_NONASCII_ESC);
129
}
130
131
void
132
cam_strvis_flag(uint8_t *dst, const uint8_t *src, int srclen, int dstlen,
133
uint32_t flags)
134
{
135
struct sbuf sb;
136
137
sbuf_new(&sb, dst, dstlen, SBUF_FIXEDLEN);
138
cam_strvis_sbuf(&sb, src, srclen, flags);
139
sbuf_finish(&sb);
140
}
141
142
void
143
cam_strvis_sbuf(struct sbuf *sb, const uint8_t *src, int srclen,
144
uint32_t flags)
145
{
146
147
/* Trim leading/trailing spaces, nulls. */
148
while (srclen > 0 && src[0] == ' ')
149
src++, srclen--;
150
while (srclen > 0
151
&& (src[srclen-1] == ' ' || src[srclen-1] == '\0'))
152
srclen--;
153
154
while (srclen > 0) {
155
if (*src < 0x20 || *src >= 0x80) {
156
/* SCSI-II Specifies that these should never occur. */
157
/* non-printable character */
158
switch (flags & CAM_STRVIS_FLAG_NONASCII_MASK) {
159
case CAM_STRVIS_FLAG_NONASCII_ESC:
160
sbuf_printf(sb, "\\%c%c%c",
161
((*src & 0300) >> 6) + '0',
162
((*src & 0070) >> 3) + '0',
163
((*src & 0007) >> 0) + '0');
164
break;
165
case CAM_STRVIS_FLAG_NONASCII_RAW:
166
/*
167
* If we run into a NUL, just transform it
168
* into a space.
169
*/
170
if (*src != 0x00)
171
sbuf_putc(sb, *src);
172
else
173
sbuf_putc(sb, ' ');
174
break;
175
case CAM_STRVIS_FLAG_NONASCII_SPC:
176
sbuf_putc(sb, ' ');
177
break;
178
case CAM_STRVIS_FLAG_NONASCII_TRIM:
179
default:
180
break;
181
}
182
} else {
183
/* normal character */
184
sbuf_putc(sb, *src);
185
}
186
src++;
187
srclen--;
188
}
189
}
190
191
/*
192
* Compare string with pattern, returning 0 on match.
193
* Short pattern matches trailing blanks in name,
194
* Shell globbing rules apply: * matches 0 or more characters,
195
* ? matchces one character, [...] denotes a set to match one char,
196
* [^...] denotes a complimented set to match one character.
197
* Spaces in str used to match anything in the pattern string
198
* but was removed because it's a bug. No current patterns require
199
* it, as far as I know, but it's impossible to know what drives
200
* returned.
201
*
202
* Each '*' generates recursion, so keep the number of * in check.
203
*/
204
int
205
cam_strmatch(const uint8_t *str, const uint8_t *pattern, int str_len)
206
{
207
208
while (*pattern != '\0' && str_len > 0) {
209
if (*pattern == '*') {
210
pattern++;
211
if (*pattern == '\0')
212
return (0);
213
do {
214
if (cam_strmatch(str, pattern, str_len) == 0)
215
return (0);
216
str++;
217
str_len--;
218
} while (str_len > 0);
219
return (1);
220
} else if (*pattern == '[') {
221
int negate_range, ok;
222
uint8_t pc = UCHAR_MAX;
223
uint8_t sc;
224
225
ok = 0;
226
sc = *str++;
227
str_len--;
228
pattern++;
229
if ((negate_range = (*pattern == '^')) != 0)
230
pattern++;
231
while ((*pattern != ']') && *pattern != '\0') {
232
if (*pattern == '-') {
233
if (pattern[1] == '\0') /* Bad pattern */
234
return (1);
235
if (sc >= pc && sc <= pattern[1])
236
ok = 1;
237
pattern++;
238
} else if (*pattern == sc)
239
ok = 1;
240
pc = *pattern;
241
pattern++;
242
}
243
if (ok == negate_range)
244
return (1);
245
pattern++;
246
} else if (*pattern == '?') {
247
/*
248
* NB: || *str == ' ' of the old code is a bug and was
249
* removed. If you add it back, keep this the last if
250
* before the naked else */
251
pattern++;
252
str++;
253
str_len--;
254
} else {
255
if (*str != *pattern)
256
return (1);
257
pattern++;
258
str++;
259
str_len--;
260
}
261
}
262
263
/* '*' is allowed to match nothing, so gobble it */
264
while (*pattern == '*')
265
pattern++;
266
267
if ( *pattern != '\0') {
268
/* Pattern not fully consumed. Not a match */
269
return (1);
270
}
271
272
/* Eat trailing spaces, which get added by SAT */
273
while (str_len > 0 && *str == ' ') {
274
str++;
275
str_len--;
276
}
277
278
return (str_len);
279
}
280
281
caddr_t
282
cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
283
int entry_size, cam_quirkmatch_t *comp_func)
284
{
285
for (; num_entries > 0; num_entries--, quirk_table += entry_size) {
286
if ((*comp_func)(target, quirk_table) == 0)
287
return (quirk_table);
288
}
289
return (NULL);
290
}
291
292
const struct cam_status_entry*
293
cam_fetch_status_entry(cam_status status)
294
{
295
status &= CAM_STATUS_MASK;
296
return (bsearch(&status, &cam_status_table,
297
nitems(cam_status_table),
298
sizeof(*cam_status_table),
299
camstatusentrycomp));
300
}
301
302
static int
303
camstatusentrycomp(const void *key, const void *member)
304
{
305
cam_status status;
306
const struct cam_status_entry *table_entry;
307
308
status = *(const cam_status *)key;
309
table_entry = (const struct cam_status_entry *)member;
310
311
return (status - table_entry->status_code);
312
}
313
314
#ifdef _KERNEL
315
char *
316
cam_error_string(union ccb *ccb, char *str, int str_len,
317
cam_error_string_flags flags,
318
cam_error_proto_flags proto_flags)
319
#else /* !_KERNEL */
320
char *
321
cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
322
int str_len, cam_error_string_flags flags,
323
cam_error_proto_flags proto_flags)
324
#endif /* _KERNEL/!_KERNEL */
325
{
326
char path_str[64];
327
struct sbuf sb;
328
329
if ((ccb == NULL)
330
|| (str == NULL)
331
|| (str_len <= 0))
332
return(NULL);
333
334
if (flags == CAM_ESF_NONE)
335
return(NULL);
336
337
switch (ccb->ccb_h.func_code) {
338
case XPT_ATA_IO:
339
switch (proto_flags & CAM_EPF_LEVEL_MASK) {
340
case CAM_EPF_NONE:
341
break;
342
case CAM_EPF_ALL:
343
case CAM_EPF_NORMAL:
344
proto_flags |= CAM_EAF_PRINT_RESULT;
345
/* FALLTHROUGH */
346
case CAM_EPF_MINIMAL:
347
proto_flags |= CAM_EAF_PRINT_STATUS;
348
/* FALLTHROUGH */
349
default:
350
break;
351
}
352
break;
353
case XPT_SCSI_IO:
354
switch (proto_flags & CAM_EPF_LEVEL_MASK) {
355
case CAM_EPF_NONE:
356
break;
357
case CAM_EPF_ALL:
358
case CAM_EPF_NORMAL:
359
proto_flags |= CAM_ESF_PRINT_SENSE;
360
/* FALLTHROUGH */
361
case CAM_EPF_MINIMAL:
362
proto_flags |= CAM_ESF_PRINT_STATUS;
363
/* FALLTHROUGH */
364
default:
365
break;
366
}
367
break;
368
case XPT_SMP_IO:
369
switch (proto_flags & CAM_EPF_LEVEL_MASK) {
370
case CAM_EPF_NONE:
371
break;
372
case CAM_EPF_ALL:
373
proto_flags |= CAM_ESMF_PRINT_FULL_CMD;
374
/* FALLTHROUGH */
375
case CAM_EPF_NORMAL:
376
case CAM_EPF_MINIMAL:
377
proto_flags |= CAM_ESMF_PRINT_STATUS;
378
/* FALLTHROUGH */
379
default:
380
break;
381
}
382
break;
383
case XPT_NVME_IO:
384
case XPT_NVME_ADMIN:
385
switch (proto_flags & CAM_EPF_LEVEL_MASK) {
386
case CAM_EPF_NONE:
387
break;
388
case CAM_EPF_ALL:
389
case CAM_EPF_NORMAL:
390
case CAM_EPF_MINIMAL:
391
proto_flags |= CAM_ENF_PRINT_STATUS;
392
/* FALLTHROUGH */
393
default:
394
break;
395
}
396
break;
397
default:
398
break;
399
}
400
#ifdef _KERNEL
401
xpt_path_string(ccb->csio.ccb_h.path, path_str, sizeof(path_str));
402
#else /* !_KERNEL */
403
cam_path_string(device, path_str, sizeof(path_str));
404
#endif /* _KERNEL/!_KERNEL */
405
406
sbuf_new(&sb, str, str_len, 0);
407
408
if (flags & CAM_ESF_COMMAND) {
409
sbuf_cat(&sb, path_str);
410
switch (ccb->ccb_h.func_code) {
411
case XPT_ATA_IO:
412
ata_command_sbuf(&ccb->ataio, &sb);
413
break;
414
case XPT_SCSI_IO:
415
#ifdef _KERNEL
416
scsi_command_string(&ccb->csio, &sb);
417
#else /* !_KERNEL */
418
scsi_command_string(device, &ccb->csio, &sb);
419
#endif /* _KERNEL/!_KERNEL */
420
break;
421
case XPT_SMP_IO:
422
smp_command_sbuf(&ccb->smpio, &sb, path_str, 79 -
423
strlen(path_str), (proto_flags &
424
CAM_ESMF_PRINT_FULL_CMD) ? 79 : 0);
425
break;
426
case XPT_NVME_IO:
427
case XPT_NVME_ADMIN:
428
nvme_command_sbuf(&ccb->nvmeio, &sb);
429
break;
430
default:
431
sbuf_printf(&sb, "CAM func %#x",
432
ccb->ccb_h.func_code);
433
break;
434
}
435
sbuf_putc(&sb, '\n');
436
}
437
438
if (flags & CAM_ESF_CAM_STATUS) {
439
cam_status status;
440
const struct cam_status_entry *entry;
441
442
sbuf_cat(&sb, path_str);
443
444
status = ccb->ccb_h.status & CAM_STATUS_MASK;
445
446
entry = cam_fetch_status_entry(status);
447
448
if (entry == NULL)
449
sbuf_printf(&sb, "CAM status: Unknown (%#x)\n",
450
ccb->ccb_h.status);
451
else
452
sbuf_printf(&sb, "CAM status: %s\n",
453
entry->status_text);
454
}
455
456
if (flags & CAM_ESF_PROTO_STATUS) {
457
458
switch (ccb->ccb_h.func_code) {
459
case XPT_ATA_IO:
460
if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
461
CAM_ATA_STATUS_ERROR)
462
break;
463
if (proto_flags & CAM_EAF_PRINT_STATUS) {
464
sbuf_cat(&sb, path_str);
465
ata_status_sbuf(&ccb->ataio, &sb);
466
sbuf_putc(&sb, '\n');
467
}
468
if (proto_flags & CAM_EAF_PRINT_RESULT) {
469
sbuf_cat(&sb, path_str);
470
sbuf_cat(&sb, "RES: ");
471
ata_res_sbuf(&ccb->ataio.res, &sb);
472
sbuf_putc(&sb, '\n');
473
}
474
475
break;
476
case XPT_SCSI_IO:
477
if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
478
CAM_SCSI_STATUS_ERROR)
479
break;
480
481
if (proto_flags & CAM_ESF_PRINT_STATUS) {
482
sbuf_cat(&sb, path_str);
483
sbuf_printf(&sb, "SCSI status: %s\n",
484
scsi_status_string(&ccb->csio));
485
}
486
487
if ((proto_flags & CAM_ESF_PRINT_SENSE)
488
&& (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
489
&& (ccb->ccb_h.status & CAM_AUTOSNS_VALID)) {
490
#ifdef _KERNEL
491
scsi_sense_sbuf(&ccb->csio, &sb,
492
SSS_FLAG_NONE);
493
#else /* !_KERNEL */
494
scsi_sense_sbuf(device, &ccb->csio, &sb,
495
SSS_FLAG_NONE);
496
#endif /* _KERNEL/!_KERNEL */
497
}
498
break;
499
case XPT_SMP_IO:
500
if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
501
CAM_SMP_STATUS_ERROR)
502
break;
503
504
if (proto_flags & CAM_ESF_PRINT_STATUS) {
505
sbuf_cat(&sb, path_str);
506
sbuf_printf(&sb, "SMP status: %s (%#x)\n",
507
smp_error_desc(ccb->smpio.smp_response[2]),
508
ccb->smpio.smp_response[2]);
509
}
510
/* There is no SMP equivalent to SCSI sense. */
511
break;
512
case XPT_NVME_IO:
513
case XPT_NVME_ADMIN:
514
if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
515
CAM_NVME_STATUS_ERROR)
516
break;
517
518
if (proto_flags & CAM_ESF_PRINT_STATUS) {
519
sbuf_cat(&sb, path_str);
520
sbuf_cat(&sb, "NVMe status: ");
521
nvme_status_sbuf(&ccb->nvmeio, &sb);
522
sbuf_putc(&sb, '\n');
523
}
524
525
break;
526
default:
527
break;
528
}
529
}
530
531
sbuf_finish(&sb);
532
533
return(sbuf_data(&sb));
534
}
535
536
#ifdef _KERNEL
537
538
void
539
cam_error_print(union ccb *ccb, cam_error_string_flags flags,
540
cam_error_proto_flags proto_flags)
541
{
542
char str[512];
543
544
printf("%s", cam_error_string(ccb, str, sizeof(str), flags,
545
proto_flags));
546
}
547
548
#else /* !_KERNEL */
549
550
void
551
cam_error_print(struct cam_device *device, union ccb *ccb,
552
cam_error_string_flags flags, cam_error_proto_flags proto_flags,
553
FILE *ofile)
554
{
555
char str[512];
556
557
if ((device == NULL) || (ccb == NULL) || (ofile == NULL))
558
return;
559
560
fprintf(ofile, "%s", cam_error_string(device, ccb, str, sizeof(str),
561
flags, proto_flags));
562
}
563
564
#endif /* _KERNEL/!_KERNEL */
565
566
/*
567
* Common calculate geometry fuction
568
*
569
* Caller should set ccg->volume_size and block_size.
570
* The extended parameter should be zero if extended translation
571
* should not be used.
572
*/
573
void
574
cam_calc_geometry(struct ccb_calc_geometry *ccg, int extended)
575
{
576
uint32_t size_mb, secs_per_cylinder;
577
578
if (ccg->block_size == 0) {
579
ccg->ccb_h.status = CAM_REQ_CMP_ERR;
580
return;
581
}
582
size_mb = (1024L * 1024L) / ccg->block_size;
583
if (size_mb == 0) {
584
ccg->ccb_h.status = CAM_REQ_CMP_ERR;
585
return;
586
}
587
size_mb = ccg->volume_size / size_mb;
588
if (size_mb > 1024 && extended) {
589
ccg->heads = 255;
590
ccg->secs_per_track = 63;
591
} else {
592
ccg->heads = 64;
593
ccg->secs_per_track = 32;
594
}
595
secs_per_cylinder = ccg->heads * ccg->secs_per_track;
596
if (secs_per_cylinder == 0) {
597
ccg->ccb_h.status = CAM_REQ_CMP_ERR;
598
return;
599
}
600
ccg->cylinders = ccg->volume_size / secs_per_cylinder;
601
ccg->ccb_h.status = CAM_REQ_CMP;
602
}
603
604
#ifdef _KERNEL
605
struct memdesc
606
memdesc_ccb(union ccb *ccb)
607
{
608
struct ccb_hdr *ccb_h;
609
void *data_ptr;
610
uint32_t dxfer_len;
611
uint16_t sglist_cnt;
612
613
ccb_h = &ccb->ccb_h;
614
switch (ccb_h->func_code) {
615
case XPT_SCSI_IO: {
616
struct ccb_scsiio *csio;
617
618
csio = &ccb->csio;
619
data_ptr = csio->data_ptr;
620
dxfer_len = csio->dxfer_len;
621
sglist_cnt = csio->sglist_cnt;
622
break;
623
}
624
case XPT_CONT_TARGET_IO: {
625
struct ccb_scsiio *ctio;
626
627
ctio = &ccb->ctio;
628
data_ptr = ctio->data_ptr;
629
dxfer_len = ctio->dxfer_len;
630
sglist_cnt = ctio->sglist_cnt;
631
break;
632
}
633
case XPT_ATA_IO: {
634
struct ccb_ataio *ataio;
635
636
ataio = &ccb->ataio;
637
data_ptr = ataio->data_ptr;
638
dxfer_len = ataio->dxfer_len;
639
sglist_cnt = 0;
640
break;
641
}
642
case XPT_NVME_IO:
643
case XPT_NVME_ADMIN: {
644
struct ccb_nvmeio *nvmeio;
645
646
nvmeio = &ccb->nvmeio;
647
data_ptr = nvmeio->data_ptr;
648
dxfer_len = nvmeio->dxfer_len;
649
sglist_cnt = nvmeio->sglist_cnt;
650
break;
651
}
652
default:
653
panic("%s: Unsupported func code %d", __func__,
654
ccb_h->func_code);
655
}
656
657
switch ((ccb_h->flags & CAM_DATA_MASK)) {
658
case CAM_DATA_VADDR:
659
return (memdesc_vaddr(data_ptr, dxfer_len));
660
case CAM_DATA_PADDR:
661
return (memdesc_paddr((vm_paddr_t)(uintptr_t)data_ptr,
662
dxfer_len));
663
case CAM_DATA_SG:
664
return (memdesc_vlist(data_ptr, sglist_cnt));
665
case CAM_DATA_SG_PADDR:
666
return (memdesc_plist(data_ptr, sglist_cnt));
667
case CAM_DATA_BIO:
668
return (memdesc_bio(data_ptr));
669
default:
670
panic("%s: flags 0x%X unimplemented", __func__, ccb_h->flags);
671
}
672
}
673
674
int
675
bus_dmamap_load_ccb(bus_dma_tag_t dmat, bus_dmamap_t map, union ccb *ccb,
676
bus_dmamap_callback_t *callback, void *callback_arg,
677
int flags)
678
{
679
struct ccb_hdr *ccb_h;
680
struct memdesc mem;
681
682
ccb_h = &ccb->ccb_h;
683
if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) {
684
callback(callback_arg, NULL, 0, 0);
685
return (0);
686
}
687
688
mem = memdesc_ccb(ccb);
689
return (bus_dmamap_load_mem(dmat, map, &mem, callback, callback_arg,
690
flags));
691
}
692
#endif
693
694