Print this page
8368 remove warlock leftovers from usr/src/uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/aac/aac_ioctl.c
+++ new/usr/src/uts/common/io/aac/aac_ioctl.c
1 1 /*
2 2 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3 3 */
4 4
5 5 /*
6 6 * Copyright 2005-06 Adaptec, Inc.
7 7 * Copyright (c) 2005-06 Adaptec Inc., Achim Leubner
8 8 * Copyright (c) 2000 Michael Smith
9 9 * Copyright (c) 2001 Scott Long
10 10 * Copyright (c) 2000 BSDi
11 11 * All rights reserved.
12 12 *
13 13 * Redistribution and use in source and binary forms, with or without
14 14 * modification, are permitted provided that the following conditions
15 15 * are met:
16 16 * 1. Redistributions of source code must retain the above copyright
17 17 * notice, this list of conditions and the following disclaimer.
18 18 * 2. Redistributions in binary form must reproduce the above copyright
19 19 * notice, this list of conditions and the following disclaimer in the
20 20 * documentation and/or other materials provided with the distribution.
21 21 *
22 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 32 * SUCH DAMAGE.
33 33 */
34 34 #include <sys/modctl.h>
35 35 #include <sys/conf.h>
36 36 #include <sys/cmn_err.h>
37 37 #include <sys/ddi.h>
38 38 #include <sys/devops.h>
39 39 #include <sys/pci.h>
40 40 #include <sys/types.h>
41 41 #include <sys/ddidmareq.h>
42 42 #include <sys/scsi/scsi.h>
43 43 #include <sys/ksynch.h>
44 44 #include <sys/sunddi.h>
45 45 #include <sys/byteorder.h>
46 46 #include <sys/kmem.h>
47 47 #include "aac_regs.h"
48 48 #include "aac.h"
49 49 #include "aac_ioctl.h"
50 50
51 51 struct aac_umem_sge {
52 52 uint32_t bcount;
53 53 caddr_t addr;
54 54 struct aac_cmd acp;
55 55 };
56 56
57 57 /*
58 58 * External functions
59 59 */
60 60 extern int aac_sync_mbcommand(struct aac_softstate *, uint32_t, uint32_t,
61 61 uint32_t, uint32_t, uint32_t, uint32_t *);
62 62 extern int aac_cmd_dma_alloc(struct aac_softstate *, struct aac_cmd *,
63 63 struct buf *, int, int (*)(), caddr_t);
64 64 extern void aac_free_dmamap(struct aac_cmd *);
65 65 extern int aac_do_io(struct aac_softstate *, struct aac_cmd *);
66 66 extern void aac_cmd_fib_copy(struct aac_softstate *, struct aac_cmd *);
67 67 extern void aac_ioctl_complete(struct aac_softstate *, struct aac_cmd *);
68 68 extern int aac_return_aif_wait(struct aac_softstate *, struct aac_fib_context *,
69 69 struct aac_fib **);
70 70 extern int aac_return_aif(struct aac_softstate *, struct aac_fib_context *,
71 71 struct aac_fib **);
72 72
73 73 extern ddi_device_acc_attr_t aac_acc_attr;
74 74 extern int aac_check_dma_handle(ddi_dma_handle_t);
75 75
76 76 /*
77 77 * IOCTL command handling functions
78 78 */
79 79 static int aac_check_revision(struct aac_softstate *, intptr_t, int);
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
80 80 static int aac_ioctl_send_fib(struct aac_softstate *, intptr_t, int);
81 81 static int aac_open_getadapter_fib(struct aac_softstate *, intptr_t, int);
82 82 static int aac_next_getadapter_fib(struct aac_softstate *, intptr_t, int);
83 83 static int aac_close_getadapter_fib(struct aac_softstate *, intptr_t);
84 84 static int aac_send_raw_srb(struct aac_softstate *, dev_t, intptr_t, int);
85 85 static int aac_get_pci_info(struct aac_softstate *, intptr_t, int);
86 86 static int aac_query_disk(struct aac_softstate *, intptr_t, int);
87 87 static int aac_delete_disk(struct aac_softstate *, intptr_t, int);
88 88 static int aac_supported_features(struct aac_softstate *, intptr_t, int);
89 89
90 -/*
91 - * Warlock directives
92 - */
93 -_NOTE(SCHEME_PROTECTS_DATA("unique to each handling function", aac_features
94 - aac_pci_info aac_query_disk aac_revision aac_umem_sge))
95 -
96 90 int
97 91 aac_do_ioctl(struct aac_softstate *softs, dev_t dev, int cmd, intptr_t arg,
98 92 int mode)
99 93 {
100 94 int status;
101 95
102 96 switch (cmd) {
103 97 case FSACTL_MINIPORT_REV_CHECK:
104 98 AACDB_PRINT_IOCTL(softs, "FSACTL_MINIPORT_REV_CHECK");
105 99 status = aac_check_revision(softs, arg, mode);
106 100 break;
107 101 case FSACTL_SENDFIB:
108 102 AACDB_PRINT_IOCTL(softs, "FSACTL_SEND_LARGE_FIB");
109 103 goto send_fib;
110 104 case FSACTL_SEND_LARGE_FIB:
111 105 AACDB_PRINT_IOCTL(softs, "FSACTL_SEND_LARGE_FIB");
112 106 send_fib:
113 107 status = aac_ioctl_send_fib(softs, arg, mode);
114 108 break;
115 109 case FSACTL_OPEN_GET_ADAPTER_FIB:
116 110 AACDB_PRINT_IOCTL(softs, "FSACTL_OPEN_GET_ADAPTER_FIB");
117 111 status = aac_open_getadapter_fib(softs, arg, mode);
118 112 break;
119 113 case FSACTL_GET_NEXT_ADAPTER_FIB:
120 114 AACDB_PRINT_IOCTL(softs, "FSACTL_GET_NEXT_ADAPTER_FIB");
121 115 status = aac_next_getadapter_fib(softs, arg, mode);
122 116 break;
123 117 case FSACTL_CLOSE_GET_ADAPTER_FIB:
124 118 AACDB_PRINT_IOCTL(softs, "FSACTL_CLOSE_GET_ADAPTER_FIB");
125 119 status = aac_close_getadapter_fib(softs, arg);
126 120 break;
127 121 case FSACTL_SEND_RAW_SRB:
128 122 AACDB_PRINT_IOCTL(softs, "FSACTL_SEND_RAW_SRB");
129 123 status = aac_send_raw_srb(softs, dev, arg, mode);
130 124 break;
131 125 case FSACTL_GET_PCI_INFO:
132 126 AACDB_PRINT_IOCTL(softs, "FSACTL_GET_PCI_INFO");
133 127 status = aac_get_pci_info(softs, arg, mode);
134 128 break;
135 129 case FSACTL_QUERY_DISK:
136 130 AACDB_PRINT_IOCTL(softs, "FSACTL_QUERY_DISK");
137 131 status = aac_query_disk(softs, arg, mode);
138 132 break;
139 133 case FSACTL_DELETE_DISK:
140 134 AACDB_PRINT_IOCTL(softs, "FSACTL_DELETE_DISK");
141 135 status = aac_delete_disk(softs, arg, mode);
142 136 break;
143 137 case FSACTL_GET_FEATURES:
144 138 AACDB_PRINT_IOCTL(softs, "FSACTL_GET_FEATURES");
145 139 status = aac_supported_features(softs, arg, mode);
146 140 break;
147 141 default:
148 142 status = ENOTTY;
149 143 AACDB_PRINT(softs, CE_WARN,
150 144 "!IOCTL cmd 0x%x not supported", cmd);
151 145 break;
152 146 }
153 147
154 148 return (status);
155 149 }
156 150
157 151 /*ARGSUSED*/
158 152 static int
159 153 aac_check_revision(struct aac_softstate *softs, intptr_t arg, int mode)
160 154 {
161 155 union aac_revision_align un;
162 156 struct aac_revision *aac_rev = &un.d;
163 157
164 158 DBCALLED(softs, 2);
165 159
166 160 /* Copyin the revision struct from userspace */
167 161 if (ddi_copyin((void *)arg, aac_rev,
168 162 sizeof (struct aac_revision), mode) != 0)
169 163 return (EFAULT);
170 164
171 165 /* Doctor up the response struct */
172 166 aac_rev->compat = 1;
173 167 aac_rev->version =
174 168 ((uint32_t)AAC_DRIVER_MAJOR_VERSION << 24) |
175 169 ((uint32_t)AAC_DRIVER_MINOR_VERSION << 16) |
176 170 ((uint32_t)AAC_DRIVER_TYPE << 8) |
177 171 ((uint32_t)AAC_DRIVER_BUGFIX_LEVEL);
178 172 aac_rev->build = (uint32_t)AAC_DRIVER_BUILD;
179 173
180 174 if (ddi_copyout(aac_rev, (void *)arg,
181 175 sizeof (struct aac_revision), mode) != 0)
182 176 return (EFAULT);
183 177
184 178 return (0);
185 179 }
186 180
187 181 static int
188 182 aac_send_fib(struct aac_softstate *softs, struct aac_cmd *acp)
189 183 {
190 184 int rval;
191 185
192 186 acp->flags |= AAC_CMD_NO_CB | AAC_CMD_SYNC;
193 187 acp->ac_comp = aac_ioctl_complete;
194 188
195 189 mutex_enter(&softs->io_lock);
196 190 if (softs->state & AAC_STATE_DEAD) {
197 191 mutex_exit(&softs->io_lock);
198 192 return (ENXIO);
199 193 }
200 194
201 195 rval = aac_do_io(softs, acp);
202 196 if (rval == TRAN_ACCEPT) {
203 197 rval = 0;
204 198 } else if (rval == TRAN_BADPKT) {
205 199 AACDB_PRINT(softs, CE_CONT, "User SendFib failed ENXIO");
206 200 rval = ENXIO;
207 201 } else if (rval == TRAN_BUSY) {
208 202 AACDB_PRINT(softs, CE_CONT, "User SendFib failed EBUSY");
209 203 rval = EBUSY;
210 204 }
211 205 mutex_exit(&softs->io_lock);
212 206
213 207 return (rval);
214 208 }
215 209
216 210 static int
217 211 aac_ioctl_send_fib(struct aac_softstate *softs, intptr_t arg, int mode)
218 212 {
219 213 int hbalen;
220 214 struct aac_cmd *acp;
221 215 struct aac_fib *fibp;
222 216 uint16_t fib_command;
223 217 uint32_t fib_xfer_state;
224 218 uint16_t fib_data_size, fib_size;
225 219 uint16_t fib_sender_size;
226 220 int rval;
227 221
228 222 DBCALLED(softs, 2);
229 223
230 224 /* Copy in FIB header */
231 225 hbalen = sizeof (struct aac_cmd) + softs->aac_max_fib_size;
232 226 if ((acp = kmem_zalloc(hbalen, KM_NOSLEEP)) == NULL)
233 227 return (ENOMEM);
234 228
235 229 fibp = (struct aac_fib *)(acp + 1);
236 230 acp->fibp = fibp;
237 231 if (ddi_copyin((void *)arg, fibp,
238 232 sizeof (struct aac_fib_header), mode) != 0) {
239 233 rval = EFAULT;
240 234 goto finish;
241 235 }
242 236
243 237 fib_xfer_state = LE_32(fibp->Header.XferState);
244 238 fib_command = LE_16(fibp->Header.Command);
245 239 fib_data_size = LE_16(fibp->Header.Size);
246 240 fib_sender_size = LE_16(fibp->Header.SenderSize);
247 241
248 242 fib_size = fib_data_size + sizeof (struct aac_fib_header);
249 243 if (fib_size < fib_sender_size)
250 244 fib_size = fib_sender_size;
251 245 if (fib_size > softs->aac_max_fib_size) {
252 246 rval = EFAULT;
253 247 goto finish;
254 248 }
255 249
256 250 /* Copy in FIB data */
257 251 if (ddi_copyin(((struct aac_fib *)arg)->data, fibp->data,
258 252 fib_data_size, mode) != 0) {
259 253 rval = EFAULT;
260 254 goto finish;
261 255 }
262 256 acp->fib_size = fib_size;
263 257 fibp->Header.Size = LE_16(fib_size);
264 258
265 259 /* Process FIB */
266 260 if (fib_command == TakeABreakPt) {
267 261 #ifdef DEBUG
268 262 if (aac_dbflag_on(softs, AACDB_FLAGS_FIB) &&
269 263 (softs->debug_fib_flags & AACDB_FLAGS_FIB_IOCTL))
270 264 aac_printf(softs, CE_NOTE, "FIB> TakeABreakPt, sz=%d",
271 265 fib_size);
272 266 #endif
273 267 (void) aac_sync_mbcommand(softs, AAC_BREAKPOINT_REQ,
274 268 0, 0, 0, 0, NULL);
275 269 fibp->Header.XferState = LE_32(0);
276 270 } else {
277 271 ASSERT(!(fib_xfer_state & AAC_FIBSTATE_ASYNC));
278 272 fibp->Header.XferState = LE_32(fib_xfer_state | \
279 273 (AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_REXPECTED));
280 274
281 275 acp->timeout = AAC_IOCTL_TIMEOUT;
282 276 acp->aac_cmd_fib = aac_cmd_fib_copy;
283 277 #ifdef DEBUG
284 278 acp->fib_flags = AACDB_FLAGS_FIB_IOCTL;
285 279 #endif
286 280 if ((rval = aac_send_fib(softs, acp)) != 0)
287 281 goto finish;
288 282 }
289 283
290 284 if (acp->flags & AAC_CMD_ERR) {
291 285 AACDB_PRINT(softs, CE_CONT, "FIB data corrupt");
292 286 rval = EIO;
293 287 goto finish;
294 288 }
295 289
296 290 if (ddi_copyout(fibp, (void *)arg, acp->fib_size, mode) != 0) {
297 291 AACDB_PRINT(softs, CE_CONT, "FIB copyout failed");
298 292 rval = EFAULT;
299 293 goto finish;
300 294 }
301 295
302 296 rval = 0;
303 297 finish:
304 298 kmem_free(acp, hbalen);
305 299 return (rval);
306 300 }
307 301
308 302 static int
309 303 aac_open_getadapter_fib(struct aac_softstate *softs, intptr_t arg, int mode)
310 304 {
311 305 struct aac_fib_context *fibctx_p, *ctx_p;
312 306
313 307 DBCALLED(softs, 2);
314 308
315 309 fibctx_p = kmem_zalloc(sizeof (struct aac_fib_context), KM_NOSLEEP);
316 310 if (fibctx_p == NULL)
317 311 return (ENOMEM);
318 312
319 313 mutex_enter(&softs->aifq_mutex);
320 314 /* All elements are already 0, add to queue */
321 315 if (softs->fibctx_p == NULL) {
322 316 softs->fibctx_p = fibctx_p;
323 317 } else {
324 318 for (ctx_p = softs->fibctx_p; ctx_p->next; ctx_p = ctx_p->next)
325 319 ;
326 320 ctx_p->next = fibctx_p;
327 321 fibctx_p->prev = ctx_p;
328 322 }
329 323
330 324 /* Evaluate unique value */
331 325 fibctx_p->unique = (unsigned long)fibctx_p & 0xfffffffful;
332 326 ctx_p = softs->fibctx_p;
333 327 while (ctx_p != fibctx_p) {
334 328 if (ctx_p->unique == fibctx_p->unique) {
335 329 fibctx_p->unique++;
336 330 ctx_p = softs->fibctx_p;
337 331 } else {
338 332 ctx_p = ctx_p->next;
339 333 }
340 334 }
341 335
342 336 /* Set ctx_idx to the oldest AIF */
343 337 if (softs->aifq_wrap) {
344 338 fibctx_p->ctx_idx = softs->aifq_idx;
345 339 fibctx_p->ctx_filled = 1;
346 340 }
347 341 mutex_exit(&softs->aifq_mutex);
348 342
349 343 if (ddi_copyout(&fibctx_p->unique, (void *)arg,
350 344 sizeof (uint32_t), mode) != 0)
351 345 return (EFAULT);
352 346
353 347 return (0);
354 348 }
355 349
356 350 static int
357 351 aac_next_getadapter_fib(struct aac_softstate *softs, intptr_t arg, int mode)
358 352 {
359 353 union aac_get_adapter_fib_align un;
360 354 struct aac_get_adapter_fib *af = &un.d;
361 355 struct aac_fib_context *ctx_p;
362 356 struct aac_fib *fibp;
363 357 int rval;
364 358
365 359 DBCALLED(softs, 2);
366 360
367 361 if (ddi_copyin((void *)arg, af, sizeof (*af), mode) != 0)
368 362 return (EFAULT);
369 363
370 364 mutex_enter(&softs->aifq_mutex);
371 365 for (ctx_p = softs->fibctx_p; ctx_p; ctx_p = ctx_p->next) {
372 366 if (af->context == ctx_p->unique)
373 367 break;
374 368 }
375 369 mutex_exit(&softs->aifq_mutex);
376 370
377 371 if (ctx_p) {
378 372 if (af->wait)
379 373 rval = aac_return_aif_wait(softs, ctx_p, &fibp);
380 374 else
381 375 rval = aac_return_aif(softs, ctx_p, &fibp);
382 376 }
383 377 else
384 378 rval = EFAULT;
385 379
386 380 finish:
387 381 if (rval == 0) {
388 382 if (ddi_copyout(fibp,
389 383 #ifdef _LP64
390 384 (void *)(uint64_t)af->aif_fib,
391 385 #else
392 386 (void *)af->aif_fib,
393 387 #endif
394 388 sizeof (struct aac_fib), mode) != 0)
395 389 rval = EFAULT;
396 390 }
397 391 return (rval);
398 392 }
399 393
400 394 static int
401 395 aac_close_getadapter_fib(struct aac_softstate *softs, intptr_t arg)
402 396 {
403 397 struct aac_fib_context *ctx_p;
404 398
405 399 DBCALLED(softs, 2);
406 400
407 401 mutex_enter(&softs->aifq_mutex);
408 402 for (ctx_p = softs->fibctx_p; ctx_p; ctx_p = ctx_p->next) {
409 403 if (ctx_p->unique != (uint32_t)arg)
410 404 continue;
411 405
412 406 if (ctx_p == softs->fibctx_p)
413 407 softs->fibctx_p = ctx_p->next;
414 408 else
415 409 ctx_p->prev->next = ctx_p->next;
416 410 if (ctx_p->next)
417 411 ctx_p->next->prev = ctx_p->prev;
418 412 break;
419 413 }
420 414 mutex_exit(&softs->aifq_mutex);
421 415 if (ctx_p)
422 416 kmem_free(ctx_p, sizeof (struct aac_fib_context));
423 417
424 418 return (0);
425 419 }
426 420
427 421 /*
428 422 * The following function comes from Adaptec:
429 423 *
430 424 * SRB is required for the new management tools
431 425 * Note: SRB passed down from IOCTL is always in CPU endianness.
432 426 */
433 427 static int
434 428 aac_send_raw_srb(struct aac_softstate *softs, dev_t dev, intptr_t arg, int mode)
435 429 {
436 430 struct aac_cmd *acp;
437 431 struct aac_fib *fibp;
438 432 struct aac_srb *srb;
439 433 uint32_t usr_fib_size;
440 434 uint32_t srb_sgcount;
441 435 struct aac_umem_sge *usgt = NULL;
442 436 struct aac_umem_sge *usge;
443 437 ddi_umem_cookie_t cookie;
444 438 int umem_flags = 0;
445 439 int direct = 0;
446 440 int locked = 0;
447 441 caddr_t addrlo = (caddr_t)-1;
448 442 caddr_t addrhi = 0;
449 443 struct aac_sge *sge, *sge0;
450 444 int sg64;
451 445 int rval;
452 446
453 447 DBCALLED(softs, 2);
454 448
455 449 /* Read srb size */
456 450 if (ddi_copyin(&((struct aac_srb *)arg)->count, &usr_fib_size,
457 451 sizeof (uint32_t), mode) != 0)
458 452 return (EFAULT);
459 453 if (usr_fib_size > (softs->aac_max_fib_size - \
460 454 sizeof (struct aac_fib_header)))
461 455 return (EINVAL);
462 456
463 457 if ((acp = kmem_zalloc(sizeof (struct aac_cmd) + usr_fib_size + \
464 458 sizeof (struct aac_fib_header), KM_NOSLEEP)) == NULL)
465 459 return (ENOMEM);
466 460
467 461 acp->fibp = (struct aac_fib *)(acp + 1);
468 462 fibp = acp->fibp;
469 463 srb = (struct aac_srb *)fibp->data;
470 464
471 465 /* Copy in srb */
472 466 if (ddi_copyin((void *)arg, srb, usr_fib_size, mode) != 0) {
473 467 rval = EFAULT;
474 468 goto finish;
475 469 }
476 470
477 471 srb_sgcount = srb->sg.SgCount; /* No endianness conversion needed */
478 472 if (srb_sgcount == 0)
479 473 goto send_fib;
480 474
481 475 /* Check FIB size */
482 476 if (usr_fib_size == (sizeof (struct aac_srb) + \
483 477 srb_sgcount * sizeof (struct aac_sg_entry64) - \
484 478 sizeof (struct aac_sg_entry))) {
485 479 sg64 = 1;
486 480 } else if (usr_fib_size == (sizeof (struct aac_srb) + \
487 481 (srb_sgcount - 1) * sizeof (struct aac_sg_entry))) {
488 482 sg64 = 0;
489 483 } else {
490 484 rval = EINVAL;
491 485 goto finish;
492 486 }
493 487
494 488 /* Read user SG table */
495 489 if ((usgt = kmem_zalloc(sizeof (struct aac_umem_sge) * srb_sgcount,
496 490 KM_NOSLEEP)) == NULL) {
497 491 rval = ENOMEM;
498 492 goto finish;
499 493 }
500 494 for (usge = usgt; usge < &usgt[srb_sgcount]; usge++) {
501 495 if (sg64) {
502 496 struct aac_sg_entry64 *sg64p =
503 497 (struct aac_sg_entry64 *)srb->sg.SgEntry;
504 498
505 499 usge->bcount = sg64p->SgByteCount;
506 500 usge->addr = (caddr_t)
507 501 #ifndef _LP64
508 502 (uint32_t)
509 503 #endif
510 504 sg64p->SgAddress;
511 505 } else {
512 506 struct aac_sg_entry *sgp = srb->sg.SgEntry;
513 507
514 508 usge->bcount = sgp->SgByteCount;
515 509 usge->addr = (caddr_t)
516 510 #ifdef _LP64
517 511 (uint64_t)
518 512 #endif
519 513 sgp->SgAddress;
520 514 }
521 515 acp->bcount += usge->bcount;
522 516 if (usge->addr < addrlo)
523 517 addrlo = usge->addr;
524 518 if ((usge->addr + usge->bcount) > addrhi)
525 519 addrhi = usge->addr + usge->bcount;
526 520 }
527 521 if (acp->bcount > softs->buf_dma_attr.dma_attr_maxxfer) {
528 522 AACDB_PRINT(softs, CE_NOTE,
529 523 "large srb xfer size received %d\n", acp->bcount);
530 524 rval = EINVAL;
531 525 goto finish;
532 526 }
533 527
534 528 /* Lock user buffers */
535 529 if (srb->flags & SRB_DataIn) {
536 530 umem_flags |= DDI_UMEMLOCK_READ;
537 531 direct |= B_READ;
538 532 }
539 533 if (srb->flags & SRB_DataOut) {
540 534 umem_flags |= DDI_UMEMLOCK_WRITE;
541 535 direct |= B_WRITE;
542 536 }
543 537 addrlo = (caddr_t)((uintptr_t)addrlo & (uintptr_t)PAGEMASK);
544 538 rval = ddi_umem_lock(addrlo, (((size_t)addrhi + PAGEOFFSET) & \
545 539 PAGEMASK) - (size_t)addrlo, umem_flags, &cookie);
546 540 if (rval != 0) {
547 541 AACDB_PRINT(softs, CE_NOTE, "ddi_umem_lock failed: %d",
548 542 rval);
549 543 goto finish;
550 544 }
551 545 locked = 1;
552 546
553 547 /* Allocate DMA for user buffers */
554 548 for (usge = usgt; usge < &usgt[srb_sgcount]; usge++) {
555 549 struct buf *bp;
556 550
557 551 bp = ddi_umem_iosetup(cookie, (uintptr_t)usge->addr - \
558 552 (uintptr_t)addrlo, usge->bcount, direct, dev, 0, NULL,
559 553 DDI_UMEM_NOSLEEP);
560 554 if (bp == NULL) {
561 555 AACDB_PRINT(softs, CE_NOTE, "ddi_umem_iosetup failed");
562 556 rval = ENOMEM;
563 557 goto finish;
564 558 }
565 559 if (aac_cmd_dma_alloc(softs, &usge->acp, bp, 0, NULL_FUNC,
566 560 0) != AACOK) {
567 561 rval = EFAULT;
568 562 goto finish;
569 563 }
570 564 acp->left_cookien += usge->acp.left_cookien;
571 565 if (acp->left_cookien > softs->aac_sg_tablesize) {
572 566 AACDB_PRINT(softs, CE_NOTE, "large cookiec received %d",
573 567 acp->left_cookien);
574 568 rval = EINVAL;
575 569 goto finish;
576 570 }
577 571 }
578 572
579 573 /* Construct aac cmd SG table */
580 574 if ((sge = kmem_zalloc(sizeof (struct aac_sge) * acp->left_cookien,
581 575 KM_NOSLEEP)) == NULL) {
582 576 rval = ENOMEM;
583 577 goto finish;
584 578 }
585 579 acp->sgt = sge;
586 580 for (usge = usgt; usge < &usgt[srb_sgcount]; usge++) {
587 581 for (sge0 = usge->acp.sgt;
588 582 sge0 < &usge->acp.sgt[usge->acp.left_cookien];
589 583 sge0++, sge++)
590 584 *sge = *sge0;
591 585 }
592 586
593 587 send_fib:
594 588 acp->cmdlen = srb->cdb_size;
595 589 acp->timeout = srb->timeout;
596 590
597 591 /* Send FIB command */
598 592 acp->aac_cmd_fib = softs->aac_cmd_fib_scsi;
599 593 #ifdef DEBUG
600 594 acp->fib_flags = AACDB_FLAGS_FIB_SRB;
601 595 #endif
602 596 if ((rval = aac_send_fib(softs, acp)) != 0)
603 597 goto finish;
604 598
605 599 /* Status struct */
606 600 if (ddi_copyout((struct aac_srb_reply *)fibp->data,
607 601 ((uint8_t *)arg + usr_fib_size),
608 602 sizeof (struct aac_srb_reply), mode) != 0) {
609 603 rval = EFAULT;
610 604 goto finish;
611 605 }
612 606
613 607 rval = 0;
614 608 finish:
615 609 if (acp->sgt)
616 610 kmem_free(acp->sgt, sizeof (struct aac_sge) * \
617 611 acp->left_cookien);
618 612 if (usgt) {
619 613 for (usge = usgt; usge < &usgt[srb_sgcount]; usge++) {
620 614 if (usge->acp.sgt)
621 615 kmem_free(usge->acp.sgt,
622 616 sizeof (struct aac_sge) * \
623 617 usge->acp.left_cookien);
624 618 aac_free_dmamap(&usge->acp);
625 619 if (usge->acp.bp)
626 620 freerbuf(usge->acp.bp);
627 621 }
628 622 kmem_free(usgt, sizeof (struct aac_umem_sge) * srb_sgcount);
629 623 }
630 624 if (locked)
631 625 ddi_umem_unlock(cookie);
632 626 kmem_free(acp, sizeof (struct aac_cmd) + usr_fib_size + \
633 627 sizeof (struct aac_fib_header));
634 628 return (rval);
635 629 }
636 630
637 631 /*ARGSUSED*/
638 632 static int
639 633 aac_get_pci_info(struct aac_softstate *softs, intptr_t arg, int mode)
640 634 {
641 635 union aac_pci_info_align un;
642 636 struct aac_pci_info *resp = &un.d;
643 637 pci_regspec_t *pci_rp;
644 638 uint_t num;
645 639
646 640 DBCALLED(softs, 2);
647 641
648 642 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, softs->devinfo_p,
649 643 DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &num) !=
650 644 DDI_PROP_SUCCESS)
651 645 return (EINVAL);
652 646 if (num < (sizeof (pci_regspec_t) / sizeof (int))) {
653 647 ddi_prop_free(pci_rp);
654 648 return (EINVAL);
655 649 }
656 650
657 651 resp->bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
658 652 resp->slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
659 653 ddi_prop_free(pci_rp);
660 654
661 655 if (ddi_copyout(resp, (void *)arg,
662 656 sizeof (struct aac_pci_info), mode) != 0)
663 657 return (EFAULT);
664 658 return (0);
665 659 }
666 660
667 661 static int
668 662 aac_query_disk(struct aac_softstate *softs, intptr_t arg, int mode)
669 663 {
670 664 union aac_query_disk_align un;
671 665 struct aac_query_disk *qdisk = &un.d;
672 666 struct aac_container *dvp;
673 667
674 668 DBCALLED(softs, 2);
675 669
676 670 if (ddi_copyin((void *)arg, qdisk, sizeof (*qdisk), mode) != 0)
677 671 return (EFAULT);
678 672
679 673 if (qdisk->container_no == -1) {
680 674 qdisk->container_no = qdisk->target * 16 + qdisk->lun;
681 675 } else if (qdisk->bus == -1 && qdisk->target == -1 &&
682 676 qdisk->lun == -1) {
683 677 if (qdisk->container_no >= AAC_MAX_CONTAINERS)
684 678 return (EINVAL);
685 679 qdisk->bus = 0;
686 680 qdisk->target = (qdisk->container_no & 0xf);
687 681 qdisk->lun = (qdisk->container_no >> 4);
688 682 } else {
689 683 return (EINVAL);
690 684 }
691 685
692 686 mutex_enter(&softs->io_lock);
693 687 dvp = &softs->containers[qdisk->container_no];
694 688 qdisk->valid = AAC_DEV_IS_VALID(&dvp->dev);
695 689 qdisk->locked = dvp->locked;
696 690 qdisk->deleted = dvp->deleted;
697 691 mutex_exit(&softs->io_lock);
698 692
699 693 if (ddi_copyout(qdisk, (void *)arg, sizeof (*qdisk), mode) != 0)
700 694 return (EFAULT);
701 695 return (0);
702 696 }
703 697
704 698 static int
705 699 aac_delete_disk(struct aac_softstate *softs, intptr_t arg, int mode)
706 700 {
707 701 union aac_delete_disk_align un;
708 702 struct aac_delete_disk *ddisk = &un.d;
709 703 struct aac_container *dvp;
710 704 int rval = 0;
711 705
712 706 DBCALLED(softs, 2);
713 707
714 708 if (ddi_copyin((void *)arg, ddisk, sizeof (*ddisk), mode) != 0)
715 709 return (EFAULT);
716 710
717 711 if (ddisk->container_no >= AAC_MAX_CONTAINERS)
718 712 return (EINVAL);
719 713
720 714 mutex_enter(&softs->io_lock);
721 715 dvp = &softs->containers[ddisk->container_no];
722 716 /*
723 717 * We don't trust the userland to tell us when to delete
724 718 * a container, rather we rely on an AIF coming from the
725 719 * controller.
726 720 */
727 721 if (AAC_DEV_IS_VALID(&dvp->dev)) {
728 722 if (dvp->locked)
729 723 rval = EBUSY;
730 724 }
731 725 mutex_exit(&softs->io_lock);
732 726
733 727 return (rval);
734 728 }
735 729
736 730 /*
737 731 * The following function comes from Adaptec to support creation of arrays
738 732 * bigger than 2TB.
739 733 */
740 734 static int
741 735 aac_supported_features(struct aac_softstate *softs, intptr_t arg, int mode)
742 736 {
743 737 union aac_features_align un;
744 738 struct aac_features *f = &un.d;
745 739
746 740 DBCALLED(softs, 2);
747 741
748 742 if (ddi_copyin((void *)arg, f, sizeof (*f), mode) != 0)
749 743 return (EFAULT);
750 744
751 745 /*
752 746 * When the management driver receives FSACTL_GET_FEATURES ioctl with
753 747 * ALL zero in the featuresState, the driver will return the current
754 748 * state of all the supported features, the data field will not be
755 749 * valid.
756 750 * When the management driver receives FSACTL_GET_FEATURES ioctl with
757 751 * a specific bit set in the featuresState, the driver will return the
758 752 * current state of this specific feature and whatever data that are
759 753 * associated with the feature in the data field or perform whatever
760 754 * action needed indicates in the data field.
761 755 */
762 756 if (f->feat.fValue == 0) {
763 757 f->feat.fBits.largeLBA =
764 758 (softs->flags & AAC_FLAGS_LBA_64BIT) ? 1 : 0;
765 759 f->feat.fBits.JBODSupport =
766 760 (softs->flags & AAC_FLAGS_JBOD) ? 1 : 0;
767 761 /* TODO: In the future, add other features state here as well */
768 762 } else {
769 763 if (f->feat.fBits.largeLBA)
770 764 f->feat.fBits.largeLBA =
771 765 (softs->flags & AAC_FLAGS_LBA_64BIT) ? 1 : 0;
772 766 if (f->feat.fBits.JBODSupport)
773 767 f->feat.fBits.JBODSupport =
774 768 (softs->flags & AAC_FLAGS_JBOD) ? 1 : 0;
775 769 /* TODO: Add other features state and data in the future */
776 770 }
777 771
778 772 if (ddi_copyout(f, (void *)arg, sizeof (*f), mode) != 0)
779 773 return (EFAULT);
780 774 return (0);
781 775 }
↓ open down ↓ |
676 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX