Print this page
style updates to uts/intel/io
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/dktp/disk/cmdk.c
+++ new/usr/src/uts/intel/io/dktp/disk/cmdk.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <sys/scsi/scsi.h>
27 27 #include <sys/dktp/cm.h>
28 28 #include <sys/dktp/quetypes.h>
29 29 #include <sys/dktp/queue.h>
30 30 #include <sys/dktp/fctypes.h>
31 31 #include <sys/dktp/flowctrl.h>
32 32 #include <sys/dktp/cmdev.h>
33 33 #include <sys/dkio.h>
34 34 #include <sys/dktp/tgdk.h>
35 35 #include <sys/dktp/dadk.h>
36 36 #include <sys/dktp/bbh.h>
37 37 #include <sys/dktp/altsctr.h>
38 38 #include <sys/dktp/cmdk.h>
39 39
40 40 #include <sys/stat.h>
41 41 #include <sys/vtoc.h>
42 42 #include <sys/file.h>
43 43 #include <sys/dktp/dadkio.h>
44 44 #include <sys/aio_req.h>
45 45
46 46 #include <sys/cmlb.h>
47 47
48 48 /*
49 49 * Local Static Data
50 50 */
51 51 #ifdef CMDK_DEBUG
52 52 #define DENT 0x0001
53 53 #define DIO 0x0002
54 54
55 55 static int cmdk_debug = DIO;
56 56 #endif
57 57
58 58 #ifndef TRUE
59 59 #define TRUE 1
60 60 #endif
61 61
62 62 #ifndef FALSE
63 63 #define FALSE 0
64 64 #endif
65 65
66 66 /*
67 67 * NDKMAP is the base number for accessing the fdisk partitions.
68 68 * c?d?p0 --> cmdk@?,?:q
69 69 */
70 70 #define PARTITION0_INDEX (NDKMAP + 0)
71 71
72 72 #define DKTP_DATA (dkp->dk_tgobjp)->tg_data
73 73 #define DKTP_EXT (dkp->dk_tgobjp)->tg_ext
74 74
75 75 void *cmdk_state;
76 76
77 77 /*
78 78 * the cmdk_attach_mutex protects cmdk_max_instance in multi-threaded
79 79 * attach situations
80 80 */
81 81 static kmutex_t cmdk_attach_mutex;
82 82 static int cmdk_max_instance = 0;
83 83
84 84 /*
85 85 * Panic dumpsys state
86 86 * There is only a single flag that is not mutex locked since
87 87 * the system is prevented from thread switching and cmdk_dump
88 88 * will only be called in a single threaded operation.
89 89 */
90 90 static int cmdk_indump;
91 91
92 92 /*
93 93 * Local Function Prototypes
94 94 */
95 95 static int cmdk_create_obj(dev_info_t *dip, struct cmdk *dkp);
96 96 static void cmdk_destroy_obj(dev_info_t *dip, struct cmdk *dkp);
97 97 static void cmdkmin(struct buf *bp);
98 98 static int cmdkrw(dev_t dev, struct uio *uio, int flag);
99 99 static int cmdkarw(dev_t dev, struct aio_req *aio, int flag);
100 100
101 101 /*
102 102 * Bad Block Handling Functions Prototypes
103 103 */
104 104 static void cmdk_bbh_reopen(struct cmdk *dkp);
105 105 static opaque_t cmdk_bbh_gethandle(opaque_t bbh_data, struct buf *bp);
106 106 static bbh_cookie_t cmdk_bbh_htoc(opaque_t bbh_data, opaque_t handle);
107 107 static void cmdk_bbh_freehandle(opaque_t bbh_data, opaque_t handle);
↓ open down ↓ |
107 lines elided |
↑ open up ↑ |
108 108 static void cmdk_bbh_close(struct cmdk *dkp);
109 109 static void cmdk_bbh_setalts_idx(struct cmdk *dkp);
110 110 static int cmdk_bbh_bsearch(struct alts_ent *buf, int cnt, daddr32_t key);
111 111
112 112 static struct bbh_objops cmdk_bbh_ops = {
113 113 nulldev,
114 114 nulldev,
115 115 cmdk_bbh_gethandle,
116 116 cmdk_bbh_htoc,
117 117 cmdk_bbh_freehandle,
118 - 0, 0
118 + { NULL, NULL }
119 119 };
120 120
121 121 static int cmdkopen(dev_t *dev_p, int flag, int otyp, cred_t *credp);
122 122 static int cmdkclose(dev_t dev, int flag, int otyp, cred_t *credp);
123 123 static int cmdkstrategy(struct buf *bp);
124 124 static int cmdkdump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk);
125 125 static int cmdkioctl(dev_t, int, intptr_t, int, cred_t *, int *);
126 126 static int cmdkread(dev_t dev, struct uio *uio, cred_t *credp);
127 127 static int cmdkwrite(dev_t dev, struct uio *uio, cred_t *credp);
128 128 static int cmdk_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
129 129 int mod_flags, char *name, caddr_t valuep, int *lengthp);
130 130 static int cmdkaread(dev_t dev, struct aio_req *aio, cred_t *credp);
131 131 static int cmdkawrite(dev_t dev, struct aio_req *aio, cred_t *credp);
132 132
133 133 /*
134 134 * Device driver ops vector
135 135 */
136 136
137 137 static struct cb_ops cmdk_cb_ops = {
138 138 cmdkopen, /* open */
139 139 cmdkclose, /* close */
140 140 cmdkstrategy, /* strategy */
141 141 nodev, /* print */
142 142 cmdkdump, /* dump */
143 143 cmdkread, /* read */
144 144 cmdkwrite, /* write */
145 145 cmdkioctl, /* ioctl */
146 146 nodev, /* devmap */
147 147 nodev, /* mmap */
148 148 nodev, /* segmap */
149 149 nochpoll, /* poll */
150 150 cmdk_prop_op, /* cb_prop_op */
151 151 0, /* streamtab */
152 152 D_64BIT | D_MP | D_NEW, /* Driver comaptibility flag */
153 153 CB_REV, /* cb_rev */
154 154 cmdkaread, /* async read */
155 155 cmdkawrite /* async write */
156 156 };
157 157
158 158 static int cmdkinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
159 159 void **result);
160 160 static int cmdkprobe(dev_info_t *dip);
161 161 static int cmdkattach(dev_info_t *dip, ddi_attach_cmd_t cmd);
162 162 static int cmdkdetach(dev_info_t *dip, ddi_detach_cmd_t cmd);
163 163
164 164 static void cmdk_setup_pm(dev_info_t *dip, struct cmdk *dkp);
165 165 static int cmdkresume(dev_info_t *dip);
166 166 static int cmdksuspend(dev_info_t *dip);
167 167 static int cmdkpower(dev_info_t *dip, int component, int level);
168 168
169 169 struct dev_ops cmdk_ops = {
170 170 DEVO_REV, /* devo_rev, */
171 171 0, /* refcnt */
172 172 cmdkinfo, /* info */
173 173 nulldev, /* identify */
174 174 cmdkprobe, /* probe */
175 175 cmdkattach, /* attach */
176 176 cmdkdetach, /* detach */
177 177 nodev, /* reset */
178 178 &cmdk_cb_ops, /* driver operations */
179 179 (struct bus_ops *)0, /* bus operations */
180 180 cmdkpower, /* power */
181 181 ddi_quiesce_not_needed, /* quiesce */
182 182 };
183 183
184 184 /*
185 185 * This is the loadable module wrapper.
186 186 */
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
187 187 #include <sys/modctl.h>
188 188
189 189 #ifndef XPV_HVM_DRIVER
190 190 static struct modldrv modldrv = {
191 191 &mod_driverops, /* Type of module. This one is a driver */
192 192 "Common Direct Access Disk",
193 193 &cmdk_ops, /* driver ops */
194 194 };
195 195
196 196 static struct modlinkage modlinkage = {
197 - MODREV_1, (void *)&modldrv, NULL
197 + MODREV_1, { (void *)&modldrv, NULL }
198 198 };
199 199
200 200
201 201 #else /* XPV_HVM_DRIVER */
202 202 static struct modlmisc modlmisc = {
203 203 &mod_miscops, /* Type of module. This one is a misc */
204 204 "HVM Common Direct Access Disk",
205 205 };
206 206
207 207 static struct modlinkage modlinkage = {
208 - MODREV_1, (void *)&modlmisc, NULL
208 + MODREV_1, { (void *)&modlmisc, NULL }
209 209 };
210 210
211 211 #endif /* XPV_HVM_DRIVER */
212 212
213 213 /* Function prototypes for cmlb callbacks */
214 214
215 215 static int cmdk_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr,
216 216 diskaddr_t start, size_t length, void *tg_cookie);
217 217
218 218 static int cmdk_lb_getinfo(dev_info_t *dip, int cmd, void *arg,
219 219 void *tg_cookie);
220 220
221 221 static void cmdk_devid_setup(struct cmdk *dkp);
222 222 static int cmdk_devid_modser(struct cmdk *dkp);
223 223 static int cmdk_get_modser(struct cmdk *dkp, int ioccmd, char *buf, int len);
224 224 static int cmdk_devid_fabricate(struct cmdk *dkp);
225 225 static int cmdk_devid_read(struct cmdk *dkp);
226 226
227 227 static cmlb_tg_ops_t cmdk_lb_ops = {
228 228 TG_DK_OPS_VERSION_1,
229 229 cmdk_lb_rdwr,
230 230 cmdk_lb_getinfo
231 231 };
232 232
233 233 static boolean_t
234 234 cmdk_isopen(struct cmdk *dkp, dev_t dev)
235 235 {
236 236 int part, otyp;
237 237 ulong_t partbit;
238 238
239 239 ASSERT(MUTEX_HELD((&dkp->dk_mutex)));
240 240
241 241 part = CMDKPART(dev);
242 242 partbit = 1 << part;
243 243
244 244 /* account for close */
245 245 if (dkp->dk_open_lyr[part] != 0)
246 246 return (B_TRUE);
247 247 for (otyp = 0; otyp < OTYPCNT; otyp++)
248 248 if (dkp->dk_open_reg[otyp] & partbit)
249 249 return (B_TRUE);
250 250 return (B_FALSE);
251 251 }
252 252
253 253 int
254 254 _init(void)
255 255 {
256 256 int rval;
257 257
258 258 #ifndef XPV_HVM_DRIVER
259 259 if (rval = ddi_soft_state_init(&cmdk_state, sizeof (struct cmdk), 7))
260 260 return (rval);
261 261 #endif /* !XPV_HVM_DRIVER */
262 262
263 263 mutex_init(&cmdk_attach_mutex, NULL, MUTEX_DRIVER, NULL);
264 264 if ((rval = mod_install(&modlinkage)) != 0) {
265 265 mutex_destroy(&cmdk_attach_mutex);
266 266 #ifndef XPV_HVM_DRIVER
267 267 ddi_soft_state_fini(&cmdk_state);
268 268 #endif /* !XPV_HVM_DRIVER */
269 269 }
270 270 return (rval);
271 271 }
272 272
273 273 int
274 274 _fini(void)
275 275 {
276 276 return (EBUSY);
277 277 }
278 278
279 279 int
280 280 _info(struct modinfo *modinfop)
281 281 {
282 282 return (mod_info(&modlinkage, modinfop));
283 283 }
284 284
285 285 /*
286 286 * Autoconfiguration Routines
287 287 */
288 288 static int
289 289 cmdkprobe(dev_info_t *dip)
290 290 {
291 291 int instance;
292 292 int status;
293 293 struct cmdk *dkp;
294 294
295 295 instance = ddi_get_instance(dip);
296 296
297 297 #ifndef XPV_HVM_DRIVER
298 298 if (ddi_get_soft_state(cmdk_state, instance))
299 299 return (DDI_PROBE_PARTIAL);
300 300
301 301 if (ddi_soft_state_zalloc(cmdk_state, instance) != DDI_SUCCESS)
302 302 return (DDI_PROBE_PARTIAL);
303 303 #endif /* !XPV_HVM_DRIVER */
304 304
305 305 if ((dkp = ddi_get_soft_state(cmdk_state, instance)) == NULL)
306 306 return (DDI_PROBE_PARTIAL);
307 307
308 308 mutex_init(&dkp->dk_mutex, NULL, MUTEX_DRIVER, NULL);
309 309 rw_init(&dkp->dk_bbh_mutex, NULL, RW_DRIVER, NULL);
310 310 dkp->dk_dip = dip;
311 311 mutex_enter(&dkp->dk_mutex);
312 312
313 313 dkp->dk_dev = makedevice(ddi_driver_major(dip),
314 314 ddi_get_instance(dip) << CMDK_UNITSHF);
315 315
316 316 /* linkage to dadk and strategy */
317 317 if (cmdk_create_obj(dip, dkp) != DDI_SUCCESS) {
318 318 mutex_exit(&dkp->dk_mutex);
319 319 mutex_destroy(&dkp->dk_mutex);
320 320 rw_destroy(&dkp->dk_bbh_mutex);
321 321 #ifndef XPV_HVM_DRIVER
322 322 ddi_soft_state_free(cmdk_state, instance);
323 323 #endif /* !XPV_HVM_DRIVER */
324 324 return (DDI_PROBE_PARTIAL);
325 325 }
326 326
327 327 status = dadk_probe(DKTP_DATA, KM_NOSLEEP);
328 328 if (status != DDI_PROBE_SUCCESS) {
329 329 cmdk_destroy_obj(dip, dkp); /* dadk/strategy linkage */
330 330 mutex_exit(&dkp->dk_mutex);
331 331 mutex_destroy(&dkp->dk_mutex);
332 332 rw_destroy(&dkp->dk_bbh_mutex);
333 333 #ifndef XPV_HVM_DRIVER
334 334 ddi_soft_state_free(cmdk_state, instance);
335 335 #endif /* !XPV_HVM_DRIVER */
336 336 return (status);
337 337 }
338 338
339 339 mutex_exit(&dkp->dk_mutex);
340 340 #ifdef CMDK_DEBUG
341 341 if (cmdk_debug & DENT)
342 342 PRF("cmdkprobe: instance= %d name= `%s`\n",
343 343 instance, ddi_get_name_addr(dip));
344 344 #endif
345 345 return (status);
346 346 }
347 347
348 348 static int
349 349 cmdkattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
350 350 {
351 351 int instance;
352 352 struct cmdk *dkp;
353 353 char *node_type;
354 354
355 355 switch (cmd) {
356 356 case DDI_ATTACH:
357 357 break;
358 358 case DDI_RESUME:
359 359 return (cmdkresume(dip));
360 360 default:
361 361 return (DDI_FAILURE);
362 362 }
363 363
364 364 instance = ddi_get_instance(dip);
365 365 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
366 366 return (DDI_FAILURE);
367 367
368 368 dkp->dk_pm_level = CMDK_SPINDLE_UNINIT;
369 369 mutex_init(&dkp->dk_mutex, NULL, MUTEX_DRIVER, NULL);
370 370
371 371 mutex_enter(&dkp->dk_mutex);
372 372
373 373 /* dadk_attach is an empty function that only returns SUCCESS */
374 374 (void) dadk_attach(DKTP_DATA);
375 375
376 376 node_type = (DKTP_EXT->tg_nodetype);
377 377
378 378 /*
379 379 * this open allows cmlb to read the device
380 380 * and determine the label types
381 381 * so that cmlb can create minor nodes for device
382 382 */
383 383
384 384 /* open the target disk */
385 385 if (dadk_open(DKTP_DATA, 0) != DDI_SUCCESS)
386 386 goto fail2;
387 387
388 388 #ifdef _ILP32
389 389 {
390 390 struct tgdk_geom phyg;
391 391 (void) dadk_getphygeom(DKTP_DATA, &phyg);
392 392 if ((phyg.g_cap - 1) > DK_MAX_BLOCKS) {
393 393 (void) dadk_close(DKTP_DATA);
394 394 goto fail2;
395 395 }
396 396 }
397 397 #endif
398 398
399 399
400 400 /* mark as having opened target */
401 401 dkp->dk_flag |= CMDK_TGDK_OPEN;
402 402
403 403 cmlb_alloc_handle((cmlb_handle_t *)&dkp->dk_cmlbhandle);
404 404
405 405 if (cmlb_attach(dip,
406 406 &cmdk_lb_ops,
407 407 DTYPE_DIRECT, /* device_type */
408 408 B_FALSE, /* removable */
409 409 B_FALSE, /* hot pluggable XXX */
410 410 node_type,
411 411 CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT, /* alter_behaviour */
412 412 dkp->dk_cmlbhandle,
413 413 0) != 0)
414 414 goto fail1;
415 415
416 416 /* Calling validate will create minor nodes according to disk label */
417 417 (void) cmlb_validate(dkp->dk_cmlbhandle, 0, 0);
418 418
419 419 /* set bbh (Bad Block Handling) */
420 420 cmdk_bbh_reopen(dkp);
421 421
422 422 /* setup devid string */
423 423 cmdk_devid_setup(dkp);
424 424
425 425 mutex_enter(&cmdk_attach_mutex);
426 426 if (instance > cmdk_max_instance)
427 427 cmdk_max_instance = instance;
428 428 mutex_exit(&cmdk_attach_mutex);
429 429
430 430 mutex_exit(&dkp->dk_mutex);
431 431
432 432 /*
433 433 * Add a zero-length attribute to tell the world we support
434 434 * kernel ioctls (for layered drivers)
435 435 */
436 436 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
437 437 DDI_KERNEL_IOCTL, NULL, 0);
438 438 ddi_report_dev(dip);
439 439
440 440 /*
441 441 * Initialize power management
442 442 */
443 443 mutex_init(&dkp->dk_pm_mutex, NULL, MUTEX_DRIVER, NULL);
444 444 cv_init(&dkp->dk_suspend_cv, NULL, CV_DRIVER, NULL);
445 445 cmdk_setup_pm(dip, dkp);
446 446
447 447 return (DDI_SUCCESS);
448 448
449 449 fail1:
450 450 cmlb_free_handle(&dkp->dk_cmlbhandle);
451 451 (void) dadk_close(DKTP_DATA);
452 452 fail2:
453 453 cmdk_destroy_obj(dip, dkp);
454 454 rw_destroy(&dkp->dk_bbh_mutex);
455 455 mutex_exit(&dkp->dk_mutex);
456 456 mutex_destroy(&dkp->dk_mutex);
457 457 #ifndef XPV_HVM_DRIVER
458 458 ddi_soft_state_free(cmdk_state, instance);
459 459 #endif /* !XPV_HVM_DRIVER */
460 460 return (DDI_FAILURE);
461 461 }
462 462
463 463
464 464 static int
465 465 cmdkdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
466 466 {
467 467 struct cmdk *dkp;
468 468 int instance;
469 469 int max_instance;
470 470
471 471 switch (cmd) {
472 472 case DDI_DETACH:
473 473 /* return (DDI_FAILURE); */
474 474 break;
475 475 case DDI_SUSPEND:
476 476 return (cmdksuspend(dip));
477 477 default:
478 478 #ifdef CMDK_DEBUG
479 479 if (cmdk_debug & DIO) {
480 480 PRF("cmdkdetach: cmd = %d unknown\n", cmd);
481 481 }
482 482 #endif
483 483 return (DDI_FAILURE);
484 484 }
485 485
486 486 mutex_enter(&cmdk_attach_mutex);
487 487 max_instance = cmdk_max_instance;
488 488 mutex_exit(&cmdk_attach_mutex);
489 489
490 490 /* check if any instance of driver is open */
491 491 for (instance = 0; instance < max_instance; instance++) {
492 492 dkp = ddi_get_soft_state(cmdk_state, instance);
493 493 if (!dkp)
494 494 continue;
495 495 if (dkp->dk_flag & CMDK_OPEN)
496 496 return (DDI_FAILURE);
497 497 }
498 498
499 499 instance = ddi_get_instance(dip);
500 500 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
501 501 return (DDI_SUCCESS);
502 502
503 503 mutex_enter(&dkp->dk_mutex);
504 504
505 505 /*
506 506 * The cmdk_part_info call at the end of cmdkattach may have
507 507 * caused cmdk_reopen to do a TGDK_OPEN, make sure we close on
508 508 * detach for case when cmdkopen/cmdkclose never occurs.
509 509 */
510 510 if (dkp->dk_flag & CMDK_TGDK_OPEN) {
511 511 dkp->dk_flag &= ~CMDK_TGDK_OPEN;
512 512 (void) dadk_close(DKTP_DATA);
513 513 }
514 514
515 515 cmlb_detach(dkp->dk_cmlbhandle, 0);
516 516 cmlb_free_handle(&dkp->dk_cmlbhandle);
517 517 ddi_prop_remove_all(dip);
518 518
519 519 cmdk_destroy_obj(dip, dkp); /* dadk/strategy linkage */
520 520
521 521 /*
522 522 * free the devid structure if allocated before
523 523 */
524 524 if (dkp->dk_devid) {
525 525 ddi_devid_free(dkp->dk_devid);
526 526 dkp->dk_devid = NULL;
527 527 }
528 528
529 529 mutex_exit(&dkp->dk_mutex);
530 530 mutex_destroy(&dkp->dk_mutex);
531 531 rw_destroy(&dkp->dk_bbh_mutex);
532 532 mutex_destroy(&dkp->dk_pm_mutex);
533 533 cv_destroy(&dkp->dk_suspend_cv);
534 534 #ifndef XPV_HVM_DRIVER
535 535 ddi_soft_state_free(cmdk_state, instance);
536 536 #endif /* !XPV_HVM_DRIVER */
537 537
538 538 return (DDI_SUCCESS);
539 539 }
540 540
541 541 static int
542 542 cmdkinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
543 543 {
544 544 dev_t dev = (dev_t)arg;
545 545 int instance;
546 546 struct cmdk *dkp;
547 547
548 548 #ifdef lint
549 549 dip = dip; /* no one ever uses this */
550 550 #endif
551 551 #ifdef CMDK_DEBUG
552 552 if (cmdk_debug & DENT)
553 553 PRF("cmdkinfo: call\n");
554 554 #endif
555 555 instance = CMDKUNIT(dev);
556 556
557 557 switch (infocmd) {
558 558 case DDI_INFO_DEVT2DEVINFO:
559 559 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
560 560 return (DDI_FAILURE);
561 561 *result = (void *) dkp->dk_dip;
562 562 break;
563 563 case DDI_INFO_DEVT2INSTANCE:
564 564 *result = (void *)(intptr_t)instance;
565 565 break;
566 566 default:
567 567 return (DDI_FAILURE);
568 568 }
569 569 return (DDI_SUCCESS);
570 570 }
571 571
572 572 /*
573 573 * Initialize the power management components
574 574 */
575 575 static void
576 576 cmdk_setup_pm(dev_info_t *dip, struct cmdk *dkp)
577 577 {
578 578 char *pm_comp[] = { "NAME=cmdk", "0=off", "1=on", NULL };
579 579
580 580 /*
581 581 * Since the cmdk device does not the 'reg' property,
582 582 * cpr will not call its DDI_SUSPEND/DDI_RESUME entries.
583 583 * The following code is to tell cpr that this device
584 584 * DOES need to be suspended and resumed.
585 585 */
586 586 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
587 587 "pm-hardware-state", "needs-suspend-resume");
588 588
589 589 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
590 590 "pm-components", pm_comp, 3) == DDI_PROP_SUCCESS) {
591 591 if (pm_raise_power(dip, 0, CMDK_SPINDLE_ON) == DDI_SUCCESS) {
592 592 mutex_enter(&dkp->dk_pm_mutex);
593 593 dkp->dk_pm_level = CMDK_SPINDLE_ON;
594 594 dkp->dk_pm_is_enabled = 1;
595 595 mutex_exit(&dkp->dk_pm_mutex);
596 596 } else {
597 597 mutex_enter(&dkp->dk_pm_mutex);
598 598 dkp->dk_pm_level = CMDK_SPINDLE_OFF;
599 599 dkp->dk_pm_is_enabled = 0;
600 600 mutex_exit(&dkp->dk_pm_mutex);
601 601 }
602 602 } else {
603 603 mutex_enter(&dkp->dk_pm_mutex);
604 604 dkp->dk_pm_level = CMDK_SPINDLE_UNINIT;
605 605 dkp->dk_pm_is_enabled = 0;
606 606 mutex_exit(&dkp->dk_pm_mutex);
607 607 }
608 608 }
609 609
610 610 /*
611 611 * suspend routine, it will be run when get the command
612 612 * DDI_SUSPEND at detach(9E) from system power management
613 613 */
614 614 static int
615 615 cmdksuspend(dev_info_t *dip)
616 616 {
617 617 struct cmdk *dkp;
618 618 int instance;
619 619 clock_t count = 0;
620 620
621 621 instance = ddi_get_instance(dip);
622 622 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
623 623 return (DDI_FAILURE);
624 624 mutex_enter(&dkp->dk_mutex);
625 625 if (dkp->dk_flag & CMDK_SUSPEND) {
626 626 mutex_exit(&dkp->dk_mutex);
627 627 return (DDI_SUCCESS);
628 628 }
629 629 dkp->dk_flag |= CMDK_SUSPEND;
630 630
631 631 /* need to wait a while */
632 632 while (dadk_getcmds(DKTP_DATA) != 0) {
633 633 delay(drv_usectohz(1000000));
634 634 if (count > 60) {
635 635 dkp->dk_flag &= ~CMDK_SUSPEND;
636 636 cv_broadcast(&dkp->dk_suspend_cv);
637 637 mutex_exit(&dkp->dk_mutex);
638 638 return (DDI_FAILURE);
639 639 }
640 640 count++;
641 641 }
642 642 mutex_exit(&dkp->dk_mutex);
643 643 return (DDI_SUCCESS);
644 644 }
645 645
646 646 /*
647 647 * resume routine, it will be run when get the command
648 648 * DDI_RESUME at attach(9E) from system power management
649 649 */
650 650 static int
651 651 cmdkresume(dev_info_t *dip)
652 652 {
653 653 struct cmdk *dkp;
654 654 int instance;
655 655
656 656 instance = ddi_get_instance(dip);
657 657 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
658 658 return (DDI_FAILURE);
659 659 mutex_enter(&dkp->dk_mutex);
660 660 if (!(dkp->dk_flag & CMDK_SUSPEND)) {
661 661 mutex_exit(&dkp->dk_mutex);
662 662 return (DDI_FAILURE);
663 663 }
664 664 dkp->dk_pm_level = CMDK_SPINDLE_ON;
665 665 dkp->dk_flag &= ~CMDK_SUSPEND;
666 666 cv_broadcast(&dkp->dk_suspend_cv);
667 667 mutex_exit(&dkp->dk_mutex);
668 668 return (DDI_SUCCESS);
669 669
670 670 }
671 671
672 672 /*
673 673 * power management entry point, it was used to
674 674 * change power management component.
675 675 * Actually, the real hard drive suspend/resume
676 676 * was handled in ata, so this function is not
677 677 * doing any real work other than verifying that
678 678 * the disk is idle.
679 679 */
680 680 static int
681 681 cmdkpower(dev_info_t *dip, int component, int level)
682 682 {
683 683 struct cmdk *dkp;
684 684 int instance;
685 685
686 686 instance = ddi_get_instance(dip);
687 687 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)) ||
688 688 component != 0 || level > CMDK_SPINDLE_ON ||
689 689 level < CMDK_SPINDLE_OFF) {
690 690 return (DDI_FAILURE);
691 691 }
692 692
693 693 mutex_enter(&dkp->dk_pm_mutex);
694 694 if (dkp->dk_pm_is_enabled && dkp->dk_pm_level == level) {
695 695 mutex_exit(&dkp->dk_pm_mutex);
696 696 return (DDI_SUCCESS);
697 697 }
698 698 mutex_exit(&dkp->dk_pm_mutex);
699 699
700 700 if ((level == CMDK_SPINDLE_OFF) &&
701 701 (dadk_getcmds(DKTP_DATA) != 0)) {
702 702 return (DDI_FAILURE);
703 703 }
704 704
705 705 mutex_enter(&dkp->dk_pm_mutex);
706 706 dkp->dk_pm_level = level;
707 707 mutex_exit(&dkp->dk_pm_mutex);
708 708 return (DDI_SUCCESS);
709 709 }
710 710
711 711 static int
712 712 cmdk_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
713 713 char *name, caddr_t valuep, int *lengthp)
714 714 {
715 715 struct cmdk *dkp;
716 716
717 717 #ifdef CMDK_DEBUG
718 718 if (cmdk_debug & DENT)
719 719 PRF("cmdk_prop_op: call\n");
720 720 #endif
721 721
722 722 dkp = ddi_get_soft_state(cmdk_state, ddi_get_instance(dip));
723 723 if (dkp == NULL)
724 724 return (ddi_prop_op(dev, dip, prop_op, mod_flags,
725 725 name, valuep, lengthp));
726 726
727 727 return (cmlb_prop_op(dkp->dk_cmlbhandle,
728 728 dev, dip, prop_op, mod_flags, name, valuep, lengthp,
729 729 CMDKPART(dev), NULL));
730 730 }
731 731
732 732 /*
733 733 * dump routine
734 734 */
735 735 static int
736 736 cmdkdump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk)
737 737 {
738 738 int instance;
739 739 struct cmdk *dkp;
740 740 diskaddr_t p_lblksrt;
741 741 diskaddr_t p_lblkcnt;
742 742 struct buf local;
743 743 struct buf *bp;
744 744
745 745 #ifdef CMDK_DEBUG
746 746 if (cmdk_debug & DENT)
747 747 PRF("cmdkdump: call\n");
748 748 #endif
749 749 instance = CMDKUNIT(dev);
750 750 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)) || (blkno < 0))
751 751 return (ENXIO);
752 752
753 753 if (cmlb_partinfo(
754 754 dkp->dk_cmlbhandle,
755 755 CMDKPART(dev),
756 756 &p_lblkcnt,
757 757 &p_lblksrt,
758 758 NULL,
759 759 NULL,
760 760 0)) {
761 761 return (ENXIO);
762 762 }
763 763
764 764 if ((blkno+nblk) > p_lblkcnt)
765 765 return (EINVAL);
766 766
767 767 cmdk_indump = 1; /* Tell disk targets we are panic dumpping */
768 768
769 769 bp = &local;
770 770 bzero(bp, sizeof (*bp));
771 771 bp->b_flags = B_BUSY;
772 772 bp->b_un.b_addr = addr;
773 773 bp->b_bcount = nblk << SCTRSHFT;
774 774 SET_BP_SEC(bp, ((ulong_t)(p_lblksrt + blkno)));
775 775
776 776 (void) dadk_dump(DKTP_DATA, bp);
777 777 return (bp->b_error);
778 778 }
779 779
780 780 /*
781 781 * Copy in the dadkio_rwcmd according to the user's data model. If needed,
782 782 * convert it for our internal use.
783 783 */
784 784 static int
785 785 rwcmd_copyin(struct dadkio_rwcmd *rwcmdp, caddr_t inaddr, int flag)
786 786 {
787 787 switch (ddi_model_convert_from(flag)) {
788 788 case DDI_MODEL_ILP32: {
789 789 struct dadkio_rwcmd32 cmd32;
790 790
791 791 if (ddi_copyin(inaddr, &cmd32,
792 792 sizeof (struct dadkio_rwcmd32), flag)) {
793 793 return (EFAULT);
794 794 }
795 795
796 796 rwcmdp->cmd = cmd32.cmd;
797 797 rwcmdp->flags = cmd32.flags;
798 798 rwcmdp->blkaddr = (blkaddr_t)cmd32.blkaddr;
799 799 rwcmdp->buflen = cmd32.buflen;
800 800 rwcmdp->bufaddr = (caddr_t)(intptr_t)cmd32.bufaddr;
801 801 /*
802 802 * Note: we do not convert the 'status' field,
803 803 * as it should not contain valid data at this
804 804 * point.
805 805 */
806 806 bzero(&rwcmdp->status, sizeof (rwcmdp->status));
807 807 break;
808 808 }
809 809 case DDI_MODEL_NONE: {
810 810 if (ddi_copyin(inaddr, rwcmdp,
811 811 sizeof (struct dadkio_rwcmd), flag)) {
812 812 return (EFAULT);
813 813 }
814 814 }
815 815 }
816 816 return (0);
817 817 }
818 818
819 819 /*
820 820 * If necessary, convert the internal rwcmdp and status to the appropriate
821 821 * data model and copy it out to the user.
822 822 */
823 823 static int
824 824 rwcmd_copyout(struct dadkio_rwcmd *rwcmdp, caddr_t outaddr, int flag)
825 825 {
826 826 switch (ddi_model_convert_from(flag)) {
827 827 case DDI_MODEL_ILP32: {
828 828 struct dadkio_rwcmd32 cmd32;
829 829
830 830 cmd32.cmd = rwcmdp->cmd;
831 831 cmd32.flags = rwcmdp->flags;
832 832 cmd32.blkaddr = rwcmdp->blkaddr;
833 833 cmd32.buflen = rwcmdp->buflen;
834 834 ASSERT64(((uintptr_t)rwcmdp->bufaddr >> 32) == 0);
835 835 cmd32.bufaddr = (caddr32_t)(uintptr_t)rwcmdp->bufaddr;
836 836
837 837 cmd32.status.status = rwcmdp->status.status;
838 838 cmd32.status.resid = rwcmdp->status.resid;
839 839 cmd32.status.failed_blk_is_valid =
840 840 rwcmdp->status.failed_blk_is_valid;
841 841 cmd32.status.failed_blk = rwcmdp->status.failed_blk;
842 842 cmd32.status.fru_code_is_valid =
843 843 rwcmdp->status.fru_code_is_valid;
844 844 cmd32.status.fru_code = rwcmdp->status.fru_code;
845 845
846 846 bcopy(rwcmdp->status.add_error_info,
847 847 cmd32.status.add_error_info, DADKIO_ERROR_INFO_LEN);
848 848
849 849 if (ddi_copyout(&cmd32, outaddr,
850 850 sizeof (struct dadkio_rwcmd32), flag))
851 851 return (EFAULT);
852 852 break;
853 853 }
854 854 case DDI_MODEL_NONE: {
855 855 if (ddi_copyout(rwcmdp, outaddr,
856 856 sizeof (struct dadkio_rwcmd), flag))
857 857 return (EFAULT);
858 858 }
859 859 }
860 860 return (0);
861 861 }
862 862
863 863 /*
864 864 * ioctl routine
865 865 */
866 866 static int
867 867 cmdkioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp)
868 868 {
869 869 int instance;
870 870 struct scsi_device *devp;
871 871 struct cmdk *dkp;
872 872 char data[NBPSCTR];
873 873
874 874 instance = CMDKUNIT(dev);
875 875 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
876 876 return (ENXIO);
877 877
878 878 mutex_enter(&dkp->dk_mutex);
879 879 while (dkp->dk_flag & CMDK_SUSPEND) {
880 880 cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex);
881 881 }
882 882 mutex_exit(&dkp->dk_mutex);
883 883
884 884 bzero(data, sizeof (data));
885 885
886 886 switch (cmd) {
887 887
888 888 case DKIOCGMEDIAINFO: {
889 889 struct dk_minfo media_info;
890 890 struct tgdk_geom phyg;
891 891
892 892 /* dadk_getphygeom always returns success */
893 893 (void) dadk_getphygeom(DKTP_DATA, &phyg);
894 894
895 895 media_info.dki_lbsize = phyg.g_secsiz;
896 896 media_info.dki_capacity = phyg.g_cap;
897 897 media_info.dki_media_type = DK_FIXED_DISK;
898 898
899 899 if (ddi_copyout(&media_info, (void *)arg,
900 900 sizeof (struct dk_minfo), flag)) {
901 901 return (EFAULT);
902 902 } else {
903 903 return (0);
904 904 }
905 905 }
906 906
907 907 case DKIOCINFO: {
908 908 struct dk_cinfo *info = (struct dk_cinfo *)data;
909 909
910 910 /* controller information */
911 911 info->dki_ctype = (DKTP_EXT->tg_ctype);
912 912 info->dki_cnum = ddi_get_instance(ddi_get_parent(dkp->dk_dip));
913 913 (void) strcpy(info->dki_cname,
914 914 ddi_get_name(ddi_get_parent(dkp->dk_dip)));
915 915
916 916 /* Unit Information */
917 917 info->dki_unit = ddi_get_instance(dkp->dk_dip);
918 918 devp = ddi_get_driver_private(dkp->dk_dip);
919 919 info->dki_slave = (CMDEV_TARG(devp)<<3) | CMDEV_LUN(devp);
920 920 (void) strcpy(info->dki_dname, ddi_driver_name(dkp->dk_dip));
921 921 info->dki_flags = DKI_FMTVOL;
922 922 info->dki_partition = CMDKPART(dev);
923 923
924 924 info->dki_maxtransfer = maxphys / DEV_BSIZE;
925 925 info->dki_addr = 1;
926 926 info->dki_space = 0;
927 927 info->dki_prio = 0;
928 928 info->dki_vec = 0;
929 929
930 930 if (ddi_copyout(data, (void *)arg, sizeof (*info), flag))
931 931 return (EFAULT);
932 932 else
933 933 return (0);
934 934 }
935 935
936 936 case DKIOCSTATE: {
937 937 int state;
938 938 int rval;
939 939 diskaddr_t p_lblksrt;
940 940 diskaddr_t p_lblkcnt;
941 941
942 942 if (ddi_copyin((void *)arg, &state, sizeof (int), flag))
943 943 return (EFAULT);
944 944
945 945 /* dadk_check_media blocks until state changes */
946 946 if (rval = dadk_check_media(DKTP_DATA, &state))
947 947 return (rval);
948 948
949 949 if (state == DKIO_INSERTED) {
950 950
951 951 if (cmlb_validate(dkp->dk_cmlbhandle, 0, 0) != 0)
952 952 return (ENXIO);
953 953
954 954 if (cmlb_partinfo(dkp->dk_cmlbhandle, CMDKPART(dev),
955 955 &p_lblkcnt, &p_lblksrt, NULL, NULL, 0))
956 956 return (ENXIO);
957 957
958 958 if (p_lblkcnt <= 0)
959 959 return (ENXIO);
960 960 }
961 961
962 962 if (ddi_copyout(&state, (caddr_t)arg, sizeof (int), flag))
963 963 return (EFAULT);
964 964
965 965 return (0);
966 966 }
967 967
968 968 /*
969 969 * is media removable?
970 970 */
971 971 case DKIOCREMOVABLE: {
972 972 int i;
973 973
974 974 i = (DKTP_EXT->tg_rmb) ? 1 : 0;
975 975
976 976 if (ddi_copyout(&i, (caddr_t)arg, sizeof (int), flag))
977 977 return (EFAULT);
978 978
979 979 return (0);
980 980 }
981 981
982 982 case DKIOCADDBAD:
983 983 /*
984 984 * This is not an update mechanism to add bad blocks
985 985 * to the bad block structures stored on disk.
986 986 *
987 987 * addbadsec(1M) will update the bad block data on disk
988 988 * and use this ioctl to force the driver to re-initialize
989 989 * the list of bad blocks in the driver.
990 990 */
991 991
992 992 /* start BBH */
993 993 cmdk_bbh_reopen(dkp);
994 994 return (0);
995 995
996 996 case DKIOCG_PHYGEOM:
997 997 case DKIOCG_VIRTGEOM:
998 998 case DKIOCGGEOM:
999 999 case DKIOCSGEOM:
1000 1000 case DKIOCGAPART:
1001 1001 case DKIOCSAPART:
1002 1002 case DKIOCGVTOC:
1003 1003 case DKIOCSVTOC:
1004 1004 case DKIOCPARTINFO:
1005 1005 case DKIOCGEXTVTOC:
1006 1006 case DKIOCSEXTVTOC:
1007 1007 case DKIOCEXTPARTINFO:
1008 1008 case DKIOCGMBOOT:
1009 1009 case DKIOCSMBOOT:
1010 1010 case DKIOCGETEFI:
1011 1011 case DKIOCSETEFI:
1012 1012 case DKIOCPARTITION:
1013 1013 case DKIOCSETEXTPART:
1014 1014 {
1015 1015 int rc;
1016 1016
1017 1017 rc = cmlb_ioctl(dkp->dk_cmlbhandle, dev, cmd, arg, flag,
1018 1018 credp, rvalp, 0);
1019 1019 if (cmd == DKIOCSVTOC || cmd == DKIOCSEXTVTOC)
1020 1020 cmdk_devid_setup(dkp);
1021 1021 return (rc);
1022 1022 }
1023 1023
1024 1024 case DIOCTL_RWCMD: {
1025 1025 struct dadkio_rwcmd *rwcmdp;
1026 1026 int status;
1027 1027
1028 1028 rwcmdp = kmem_alloc(sizeof (struct dadkio_rwcmd), KM_SLEEP);
1029 1029
1030 1030 status = rwcmd_copyin(rwcmdp, (caddr_t)arg, flag);
1031 1031
1032 1032 if (status == 0) {
1033 1033 bzero(&(rwcmdp->status), sizeof (struct dadkio_status));
1034 1034 status = dadk_ioctl(DKTP_DATA,
1035 1035 dev,
1036 1036 cmd,
1037 1037 (uintptr_t)rwcmdp,
1038 1038 flag,
1039 1039 credp,
1040 1040 rvalp);
1041 1041 }
1042 1042 if (status == 0)
1043 1043 status = rwcmd_copyout(rwcmdp, (caddr_t)arg, flag);
1044 1044
1045 1045 kmem_free(rwcmdp, sizeof (struct dadkio_rwcmd));
1046 1046 return (status);
1047 1047 }
1048 1048
1049 1049 default:
1050 1050 return (dadk_ioctl(DKTP_DATA,
1051 1051 dev,
1052 1052 cmd,
1053 1053 arg,
1054 1054 flag,
1055 1055 credp,
1056 1056 rvalp));
1057 1057 }
1058 1058 }
1059 1059
1060 1060 /*ARGSUSED1*/
1061 1061 static int
1062 1062 cmdkclose(dev_t dev, int flag, int otyp, cred_t *credp)
1063 1063 {
1064 1064 int part;
1065 1065 ulong_t partbit;
1066 1066 int instance;
1067 1067 struct cmdk *dkp;
1068 1068 int lastclose = 1;
1069 1069 int i;
1070 1070
1071 1071 instance = CMDKUNIT(dev);
1072 1072 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)) ||
1073 1073 (otyp >= OTYPCNT))
1074 1074 return (ENXIO);
1075 1075
1076 1076 mutex_enter(&dkp->dk_mutex);
1077 1077
1078 1078 /* check if device has been opened */
1079 1079 ASSERT(cmdk_isopen(dkp, dev));
1080 1080 if (!(dkp->dk_flag & CMDK_OPEN)) {
1081 1081 mutex_exit(&dkp->dk_mutex);
1082 1082 return (ENXIO);
1083 1083 }
1084 1084
1085 1085 while (dkp->dk_flag & CMDK_SUSPEND) {
1086 1086 cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex);
1087 1087 }
1088 1088
1089 1089 part = CMDKPART(dev);
1090 1090 partbit = 1 << part;
1091 1091
1092 1092 /* account for close */
1093 1093 if (otyp == OTYP_LYR) {
1094 1094 ASSERT(dkp->dk_open_lyr[part] > 0);
1095 1095 if (dkp->dk_open_lyr[part])
1096 1096 dkp->dk_open_lyr[part]--;
1097 1097 } else {
1098 1098 ASSERT((dkp->dk_open_reg[otyp] & partbit) != 0);
1099 1099 dkp->dk_open_reg[otyp] &= ~partbit;
1100 1100 }
1101 1101 dkp->dk_open_exl &= ~partbit;
1102 1102
1103 1103 for (i = 0; i < CMDK_MAXPART; i++)
1104 1104 if (dkp->dk_open_lyr[i] != 0) {
1105 1105 lastclose = 0;
1106 1106 break;
1107 1107 }
1108 1108
1109 1109 if (lastclose)
1110 1110 for (i = 0; i < OTYPCNT; i++)
1111 1111 if (dkp->dk_open_reg[i] != 0) {
1112 1112 lastclose = 0;
1113 1113 break;
1114 1114 }
1115 1115
1116 1116 mutex_exit(&dkp->dk_mutex);
1117 1117
1118 1118 if (lastclose)
1119 1119 cmlb_invalidate(dkp->dk_cmlbhandle, 0);
1120 1120
1121 1121 return (DDI_SUCCESS);
1122 1122 }
1123 1123
1124 1124 /*ARGSUSED3*/
1125 1125 static int
1126 1126 cmdkopen(dev_t *dev_p, int flag, int otyp, cred_t *credp)
1127 1127 {
1128 1128 dev_t dev = *dev_p;
1129 1129 int part;
1130 1130 ulong_t partbit;
1131 1131 int instance;
1132 1132 struct cmdk *dkp;
1133 1133 diskaddr_t p_lblksrt;
1134 1134 diskaddr_t p_lblkcnt;
1135 1135 int i;
1136 1136 int nodelay;
1137 1137
1138 1138 instance = CMDKUNIT(dev);
1139 1139 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
1140 1140 return (ENXIO);
1141 1141
1142 1142 if (otyp >= OTYPCNT)
1143 1143 return (EINVAL);
1144 1144
1145 1145 mutex_enter(&dkp->dk_mutex);
1146 1146 while (dkp->dk_flag & CMDK_SUSPEND) {
1147 1147 cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex);
1148 1148 }
1149 1149 mutex_exit(&dkp->dk_mutex);
1150 1150
1151 1151 part = CMDKPART(dev);
1152 1152 partbit = 1 << part;
1153 1153 nodelay = (flag & (FNDELAY | FNONBLOCK));
1154 1154
1155 1155 mutex_enter(&dkp->dk_mutex);
1156 1156
1157 1157 if (cmlb_validate(dkp->dk_cmlbhandle, 0, 0) != 0) {
1158 1158
1159 1159 /* fail if not doing non block open */
1160 1160 if (!nodelay) {
1161 1161 mutex_exit(&dkp->dk_mutex);
1162 1162 return (ENXIO);
1163 1163 }
1164 1164 } else if (cmlb_partinfo(dkp->dk_cmlbhandle, part, &p_lblkcnt,
1165 1165 &p_lblksrt, NULL, NULL, 0) == 0) {
1166 1166
1167 1167 if (p_lblkcnt <= 0 && (!nodelay || otyp != OTYP_CHR)) {
1168 1168 mutex_exit(&dkp->dk_mutex);
1169 1169 return (ENXIO);
1170 1170 }
1171 1171 } else {
1172 1172 /* fail if not doing non block open */
1173 1173 if (!nodelay) {
1174 1174 mutex_exit(&dkp->dk_mutex);
1175 1175 return (ENXIO);
1176 1176 }
1177 1177 }
1178 1178
1179 1179 if ((DKTP_EXT->tg_rdonly) && (flag & FWRITE)) {
1180 1180 mutex_exit(&dkp->dk_mutex);
1181 1181 return (EROFS);
1182 1182 }
1183 1183
1184 1184 /* check for part already opend exclusively */
1185 1185 if (dkp->dk_open_exl & partbit)
1186 1186 goto excl_open_fail;
1187 1187
1188 1188 /* check if we can establish exclusive open */
1189 1189 if (flag & FEXCL) {
1190 1190 if (dkp->dk_open_lyr[part])
1191 1191 goto excl_open_fail;
1192 1192 for (i = 0; i < OTYPCNT; i++) {
1193 1193 if (dkp->dk_open_reg[i] & partbit)
1194 1194 goto excl_open_fail;
1195 1195 }
1196 1196 }
1197 1197
1198 1198 /* open will succeed, account for open */
1199 1199 dkp->dk_flag |= CMDK_OPEN;
1200 1200 if (otyp == OTYP_LYR)
1201 1201 dkp->dk_open_lyr[part]++;
1202 1202 else
1203 1203 dkp->dk_open_reg[otyp] |= partbit;
1204 1204 if (flag & FEXCL)
1205 1205 dkp->dk_open_exl |= partbit;
1206 1206
1207 1207 mutex_exit(&dkp->dk_mutex);
1208 1208 return (DDI_SUCCESS);
1209 1209
1210 1210 excl_open_fail:
1211 1211 mutex_exit(&dkp->dk_mutex);
1212 1212 return (EBUSY);
1213 1213 }
1214 1214
1215 1215 /*
1216 1216 * read routine
1217 1217 */
1218 1218 /*ARGSUSED2*/
1219 1219 static int
1220 1220 cmdkread(dev_t dev, struct uio *uio, cred_t *credp)
1221 1221 {
1222 1222 return (cmdkrw(dev, uio, B_READ));
1223 1223 }
1224 1224
1225 1225 /*
1226 1226 * async read routine
1227 1227 */
1228 1228 /*ARGSUSED2*/
1229 1229 static int
1230 1230 cmdkaread(dev_t dev, struct aio_req *aio, cred_t *credp)
1231 1231 {
1232 1232 return (cmdkarw(dev, aio, B_READ));
1233 1233 }
1234 1234
1235 1235 /*
1236 1236 * write routine
1237 1237 */
1238 1238 /*ARGSUSED2*/
1239 1239 static int
1240 1240 cmdkwrite(dev_t dev, struct uio *uio, cred_t *credp)
1241 1241 {
1242 1242 return (cmdkrw(dev, uio, B_WRITE));
1243 1243 }
1244 1244
1245 1245 /*
1246 1246 * async write routine
1247 1247 */
1248 1248 /*ARGSUSED2*/
1249 1249 static int
1250 1250 cmdkawrite(dev_t dev, struct aio_req *aio, cred_t *credp)
1251 1251 {
1252 1252 return (cmdkarw(dev, aio, B_WRITE));
1253 1253 }
1254 1254
1255 1255 static void
1256 1256 cmdkmin(struct buf *bp)
1257 1257 {
1258 1258 if (bp->b_bcount > DK_MAXRECSIZE)
1259 1259 bp->b_bcount = DK_MAXRECSIZE;
1260 1260 }
1261 1261
1262 1262 static int
1263 1263 cmdkrw(dev_t dev, struct uio *uio, int flag)
1264 1264 {
1265 1265 int instance;
1266 1266 struct cmdk *dkp;
1267 1267
1268 1268 instance = CMDKUNIT(dev);
1269 1269 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
1270 1270 return (ENXIO);
1271 1271
1272 1272 mutex_enter(&dkp->dk_mutex);
1273 1273 while (dkp->dk_flag & CMDK_SUSPEND) {
1274 1274 cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex);
1275 1275 }
1276 1276 mutex_exit(&dkp->dk_mutex);
1277 1277
1278 1278 return (physio(cmdkstrategy, (struct buf *)0, dev, flag, cmdkmin, uio));
1279 1279 }
1280 1280
1281 1281 static int
1282 1282 cmdkarw(dev_t dev, struct aio_req *aio, int flag)
1283 1283 {
1284 1284 int instance;
1285 1285 struct cmdk *dkp;
1286 1286
1287 1287 instance = CMDKUNIT(dev);
1288 1288 if (!(dkp = ddi_get_soft_state(cmdk_state, instance)))
1289 1289 return (ENXIO);
1290 1290
1291 1291 mutex_enter(&dkp->dk_mutex);
1292 1292 while (dkp->dk_flag & CMDK_SUSPEND) {
1293 1293 cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex);
1294 1294 }
1295 1295 mutex_exit(&dkp->dk_mutex);
1296 1296
1297 1297 return (aphysio(cmdkstrategy, anocancel, dev, flag, cmdkmin, aio));
1298 1298 }
1299 1299
1300 1300 /*
1301 1301 * strategy routine
1302 1302 */
1303 1303 static int
1304 1304 cmdkstrategy(struct buf *bp)
1305 1305 {
1306 1306 int instance;
1307 1307 struct cmdk *dkp;
1308 1308 long d_cnt;
1309 1309 diskaddr_t p_lblksrt;
1310 1310 diskaddr_t p_lblkcnt;
1311 1311
1312 1312 instance = CMDKUNIT(bp->b_edev);
1313 1313 if (cmdk_indump || !(dkp = ddi_get_soft_state(cmdk_state, instance)) ||
1314 1314 (dkblock(bp) < 0)) {
1315 1315 bp->b_resid = bp->b_bcount;
1316 1316 SETBPERR(bp, ENXIO);
1317 1317 biodone(bp);
1318 1318 return (0);
1319 1319 }
1320 1320
1321 1321 mutex_enter(&dkp->dk_mutex);
1322 1322 ASSERT(cmdk_isopen(dkp, bp->b_edev));
1323 1323 while (dkp->dk_flag & CMDK_SUSPEND) {
1324 1324 cv_wait(&dkp->dk_suspend_cv, &dkp->dk_mutex);
1325 1325 }
1326 1326 mutex_exit(&dkp->dk_mutex);
1327 1327
1328 1328 bp->b_flags &= ~(B_DONE|B_ERROR);
1329 1329 bp->b_resid = 0;
1330 1330 bp->av_back = NULL;
1331 1331
1332 1332 /*
1333 1333 * only re-read the vtoc if necessary (force == FALSE)
1334 1334 */
1335 1335 if (cmlb_partinfo(dkp->dk_cmlbhandle, CMDKPART(bp->b_edev),
1336 1336 &p_lblkcnt, &p_lblksrt, NULL, NULL, 0)) {
1337 1337 SETBPERR(bp, ENXIO);
1338 1338 }
1339 1339
1340 1340 if ((bp->b_bcount & (NBPSCTR-1)) || (dkblock(bp) > p_lblkcnt))
1341 1341 SETBPERR(bp, ENXIO);
1342 1342
1343 1343 if ((bp->b_flags & B_ERROR) || (dkblock(bp) == p_lblkcnt)) {
1344 1344 bp->b_resid = bp->b_bcount;
1345 1345 biodone(bp);
1346 1346 return (0);
1347 1347 }
1348 1348
1349 1349 d_cnt = bp->b_bcount >> SCTRSHFT;
1350 1350 if ((dkblock(bp) + d_cnt) > p_lblkcnt) {
1351 1351 bp->b_resid = ((dkblock(bp) + d_cnt) - p_lblkcnt) << SCTRSHFT;
1352 1352 bp->b_bcount -= bp->b_resid;
1353 1353 }
1354 1354
1355 1355 SET_BP_SEC(bp, ((ulong_t)(p_lblksrt + dkblock(bp))));
1356 1356 if (dadk_strategy(DKTP_DATA, bp) != DDI_SUCCESS) {
1357 1357 bp->b_resid += bp->b_bcount;
1358 1358 biodone(bp);
1359 1359 }
1360 1360 return (0);
1361 1361 }
1362 1362
1363 1363 static int
1364 1364 cmdk_create_obj(dev_info_t *dip, struct cmdk *dkp)
1365 1365 {
1366 1366 struct scsi_device *devp;
1367 1367 opaque_t queobjp = NULL;
1368 1368 opaque_t flcobjp = NULL;
1369 1369 char que_keyvalp[64];
1370 1370 int que_keylen;
1371 1371 char flc_keyvalp[64];
1372 1372 int flc_keylen;
1373 1373
1374 1374 ASSERT(mutex_owned(&dkp->dk_mutex));
1375 1375
1376 1376 /* Create linkage to queueing routines based on property */
1377 1377 que_keylen = sizeof (que_keyvalp);
1378 1378 if (ddi_prop_op(DDI_DEV_T_NONE, dip, PROP_LEN_AND_VAL_BUF,
1379 1379 DDI_PROP_CANSLEEP, "queue", que_keyvalp, &que_keylen) !=
1380 1380 DDI_PROP_SUCCESS) {
1381 1381 cmn_err(CE_WARN, "cmdk_create_obj: queue property undefined");
1382 1382 return (DDI_FAILURE);
1383 1383 }
1384 1384 que_keyvalp[que_keylen] = (char)0;
1385 1385
1386 1386 if (strcmp(que_keyvalp, "qfifo") == 0) {
1387 1387 queobjp = (opaque_t)qfifo_create();
1388 1388 } else if (strcmp(que_keyvalp, "qsort") == 0) {
1389 1389 queobjp = (opaque_t)qsort_create();
1390 1390 } else {
1391 1391 return (DDI_FAILURE);
1392 1392 }
1393 1393
1394 1394 /* Create linkage to dequeueing routines based on property */
1395 1395 flc_keylen = sizeof (flc_keyvalp);
1396 1396 if (ddi_prop_op(DDI_DEV_T_NONE, dip, PROP_LEN_AND_VAL_BUF,
1397 1397 DDI_PROP_CANSLEEP, "flow_control", flc_keyvalp, &flc_keylen) !=
1398 1398 DDI_PROP_SUCCESS) {
1399 1399 cmn_err(CE_WARN,
1400 1400 "cmdk_create_obj: flow-control property undefined");
1401 1401 return (DDI_FAILURE);
1402 1402 }
1403 1403
1404 1404 flc_keyvalp[flc_keylen] = (char)0;
1405 1405
1406 1406 if (strcmp(flc_keyvalp, "dsngl") == 0) {
1407 1407 flcobjp = (opaque_t)dsngl_create();
1408 1408 } else if (strcmp(flc_keyvalp, "dmult") == 0) {
1409 1409 flcobjp = (opaque_t)dmult_create();
1410 1410 } else {
1411 1411 return (DDI_FAILURE);
1412 1412 }
1413 1413
1414 1414 /* populate bbh_obj object stored in dkp */
1415 1415 dkp->dk_bbh_obj.bbh_data = dkp;
1416 1416 dkp->dk_bbh_obj.bbh_ops = &cmdk_bbh_ops;
1417 1417
1418 1418 /* create linkage to dadk */
1419 1419 dkp->dk_tgobjp = (opaque_t)dadk_create();
1420 1420
1421 1421 devp = ddi_get_driver_private(dip);
1422 1422 (void) dadk_init(DKTP_DATA, devp, flcobjp, queobjp, &dkp->dk_bbh_obj,
1423 1423 NULL);
1424 1424
1425 1425 return (DDI_SUCCESS);
1426 1426 }
1427 1427
1428 1428 static void
1429 1429 cmdk_destroy_obj(dev_info_t *dip, struct cmdk *dkp)
1430 1430 {
1431 1431 char que_keyvalp[64];
1432 1432 int que_keylen;
1433 1433 char flc_keyvalp[64];
1434 1434 int flc_keylen;
1435 1435
1436 1436 ASSERT(mutex_owned(&dkp->dk_mutex));
1437 1437
1438 1438 (void) dadk_free((dkp->dk_tgobjp));
1439 1439 dkp->dk_tgobjp = NULL;
1440 1440
1441 1441 que_keylen = sizeof (que_keyvalp);
1442 1442 if (ddi_prop_op(DDI_DEV_T_NONE, dip, PROP_LEN_AND_VAL_BUF,
1443 1443 DDI_PROP_CANSLEEP, "queue", que_keyvalp, &que_keylen) !=
1444 1444 DDI_PROP_SUCCESS) {
1445 1445 cmn_err(CE_WARN, "cmdk_destroy_obj: queue property undefined");
1446 1446 return;
1447 1447 }
1448 1448 que_keyvalp[que_keylen] = (char)0;
1449 1449
1450 1450 flc_keylen = sizeof (flc_keyvalp);
1451 1451 if (ddi_prop_op(DDI_DEV_T_NONE, dip, PROP_LEN_AND_VAL_BUF,
1452 1452 DDI_PROP_CANSLEEP, "flow_control", flc_keyvalp, &flc_keylen) !=
1453 1453 DDI_PROP_SUCCESS) {
1454 1454 cmn_err(CE_WARN,
1455 1455 "cmdk_destroy_obj: flow-control property undefined");
1456 1456 return;
1457 1457 }
1458 1458 flc_keyvalp[flc_keylen] = (char)0;
1459 1459 }
1460 1460 /*ARGSUSED5*/
1461 1461 static int
1462 1462 cmdk_lb_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr,
1463 1463 diskaddr_t start, size_t count, void *tg_cookie)
1464 1464 {
1465 1465 struct cmdk *dkp;
1466 1466 opaque_t handle;
1467 1467 int rc = 0;
1468 1468 char *bufa;
1469 1469 size_t buflen;
1470 1470
1471 1471 dkp = ddi_get_soft_state(cmdk_state, ddi_get_instance(dip));
1472 1472 if (dkp == NULL)
1473 1473 return (ENXIO);
1474 1474
1475 1475 if (cmd != TG_READ && cmd != TG_WRITE)
1476 1476 return (EINVAL);
1477 1477
1478 1478 /* buflen must be multiple of 512 */
1479 1479 buflen = (count + NBPSCTR - 1) & -NBPSCTR;
1480 1480 handle = dadk_iob_alloc(DKTP_DATA, start, buflen, KM_SLEEP);
1481 1481 if (!handle)
1482 1482 return (ENOMEM);
1483 1483
1484 1484 if (cmd == TG_READ) {
1485 1485 bufa = dadk_iob_xfer(DKTP_DATA, handle, B_READ);
1486 1486 if (!bufa)
1487 1487 rc = EIO;
1488 1488 else
1489 1489 bcopy(bufa, bufaddr, count);
1490 1490 } else {
1491 1491 bufa = dadk_iob_htoc(DKTP_DATA, handle);
1492 1492 bcopy(bufaddr, bufa, count);
1493 1493 bufa = dadk_iob_xfer(DKTP_DATA, handle, B_WRITE);
1494 1494 if (!bufa)
1495 1495 rc = EIO;
1496 1496 }
1497 1497 (void) dadk_iob_free(DKTP_DATA, handle);
1498 1498
1499 1499 return (rc);
1500 1500 }
1501 1501
1502 1502 /*ARGSUSED3*/
1503 1503 static int
1504 1504 cmdk_lb_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie)
1505 1505 {
1506 1506
1507 1507 struct cmdk *dkp;
1508 1508 struct tgdk_geom phyg;
1509 1509
1510 1510
1511 1511 dkp = ddi_get_soft_state(cmdk_state, ddi_get_instance(dip));
1512 1512 if (dkp == NULL)
1513 1513 return (ENXIO);
1514 1514
1515 1515 switch (cmd) {
1516 1516 case TG_GETPHYGEOM: {
1517 1517 cmlb_geom_t *phygeomp = (cmlb_geom_t *)arg;
1518 1518
1519 1519 /* dadk_getphygeom always returns success */
1520 1520 (void) dadk_getphygeom(DKTP_DATA, &phyg);
1521 1521
1522 1522 phygeomp->g_capacity = phyg.g_cap;
1523 1523 phygeomp->g_nsect = phyg.g_sec;
1524 1524 phygeomp->g_nhead = phyg.g_head;
1525 1525 phygeomp->g_acyl = phyg.g_acyl;
1526 1526 phygeomp->g_ncyl = phyg.g_cyl;
1527 1527 phygeomp->g_secsize = phyg.g_secsiz;
1528 1528 phygeomp->g_intrlv = 1;
1529 1529 phygeomp->g_rpm = 3600;
1530 1530
1531 1531 return (0);
1532 1532 }
1533 1533
1534 1534 case TG_GETVIRTGEOM: {
1535 1535 cmlb_geom_t *virtgeomp = (cmlb_geom_t *)arg;
1536 1536 diskaddr_t capacity;
1537 1537
1538 1538 (void) dadk_getgeom(DKTP_DATA, &phyg);
1539 1539 capacity = phyg.g_cap;
1540 1540
1541 1541 /*
1542 1542 * If the controller returned us something that doesn't
1543 1543 * really fit into an Int 13/function 8 geometry
1544 1544 * result, just fail the ioctl. See PSARC 1998/313.
1545 1545 */
1546 1546 if (capacity < 0 || capacity >= 63 * 254 * 1024)
1547 1547 return (EINVAL);
1548 1548
1549 1549 virtgeomp->g_capacity = capacity;
1550 1550 virtgeomp->g_nsect = 63;
1551 1551 virtgeomp->g_nhead = 254;
1552 1552 virtgeomp->g_ncyl = capacity / (63 * 254);
1553 1553 virtgeomp->g_acyl = 0;
1554 1554 virtgeomp->g_secsize = 512;
1555 1555 virtgeomp->g_intrlv = 1;
1556 1556 virtgeomp->g_rpm = 3600;
1557 1557
1558 1558 return (0);
1559 1559 }
1560 1560
1561 1561 case TG_GETCAPACITY:
1562 1562 case TG_GETBLOCKSIZE:
1563 1563 {
1564 1564
1565 1565 /* dadk_getphygeom always returns success */
1566 1566 (void) dadk_getphygeom(DKTP_DATA, &phyg);
1567 1567 if (cmd == TG_GETCAPACITY)
1568 1568 *(diskaddr_t *)arg = phyg.g_cap;
1569 1569 else
1570 1570 *(uint32_t *)arg = (uint32_t)phyg.g_secsiz;
1571 1571
1572 1572 return (0);
1573 1573 }
1574 1574
1575 1575 case TG_GETATTR: {
1576 1576 tg_attribute_t *tgattribute = (tg_attribute_t *)arg;
1577 1577 if ((DKTP_EXT->tg_rdonly))
1578 1578 tgattribute->media_is_writable = FALSE;
1579 1579 else
1580 1580 tgattribute->media_is_writable = TRUE;
1581 1581
1582 1582 return (0);
1583 1583 }
1584 1584
1585 1585 default:
1586 1586 return (ENOTTY);
1587 1587 }
1588 1588 }
1589 1589
1590 1590
1591 1591
1592 1592
1593 1593
1594 1594 /*
1595 1595 * Create and register the devid.
1596 1596 * There are 4 different ways we can get a device id:
1597 1597 * 1. Already have one - nothing to do
1598 1598 * 2. Build one from the drive's model and serial numbers
1599 1599 * 3. Read one from the disk (first sector of last track)
1600 1600 * 4. Fabricate one and write it on the disk.
1601 1601 * If any of these succeeds, register the deviceid
1602 1602 */
1603 1603 static void
1604 1604 cmdk_devid_setup(struct cmdk *dkp)
1605 1605 {
1606 1606 int rc;
1607 1607
1608 1608 /* Try options until one succeeds, or all have failed */
1609 1609
1610 1610 /* 1. All done if already registered */
1611 1611 if (dkp->dk_devid != NULL)
1612 1612 return;
1613 1613
1614 1614 /* 2. Build a devid from the model and serial number */
1615 1615 rc = cmdk_devid_modser(dkp);
1616 1616 if (rc != DDI_SUCCESS) {
1617 1617 /* 3. Read devid from the disk, if present */
1618 1618 rc = cmdk_devid_read(dkp);
1619 1619
1620 1620 /* 4. otherwise make one up and write it on the disk */
1621 1621 if (rc != DDI_SUCCESS)
1622 1622 rc = cmdk_devid_fabricate(dkp);
1623 1623 }
1624 1624
1625 1625 /* If we managed to get a devid any of the above ways, register it */
1626 1626 if (rc == DDI_SUCCESS)
1627 1627 (void) ddi_devid_register(dkp->dk_dip, dkp->dk_devid);
1628 1628
1629 1629 }
1630 1630
1631 1631 /*
1632 1632 * Build a devid from the model and serial number
1633 1633 * Return DDI_SUCCESS or DDI_FAILURE.
1634 1634 */
1635 1635 static int
1636 1636 cmdk_devid_modser(struct cmdk *dkp)
1637 1637 {
1638 1638 int rc = DDI_FAILURE;
1639 1639 char *hwid;
1640 1640 int modlen;
1641 1641 int serlen;
1642 1642
1643 1643 /*
1644 1644 * device ID is a concatenation of model number, '=', serial number.
1645 1645 */
1646 1646 hwid = kmem_alloc(CMDK_HWIDLEN, KM_SLEEP);
1647 1647 modlen = cmdk_get_modser(dkp, DIOCTL_GETMODEL, hwid, CMDK_HWIDLEN);
1648 1648 if (modlen == 0) {
1649 1649 rc = DDI_FAILURE;
1650 1650 goto err;
1651 1651 }
1652 1652 hwid[modlen++] = '=';
1653 1653 serlen = cmdk_get_modser(dkp, DIOCTL_GETSERIAL,
1654 1654 hwid + modlen, CMDK_HWIDLEN - modlen);
1655 1655 if (serlen == 0) {
1656 1656 rc = DDI_FAILURE;
1657 1657 goto err;
1658 1658 }
1659 1659 hwid[modlen + serlen] = 0;
1660 1660
1661 1661 /* Initialize the device ID, trailing NULL not included */
1662 1662 rc = ddi_devid_init(dkp->dk_dip, DEVID_ATA_SERIAL, modlen + serlen,
1663 1663 hwid, &dkp->dk_devid);
1664 1664 if (rc != DDI_SUCCESS) {
1665 1665 rc = DDI_FAILURE;
1666 1666 goto err;
1667 1667 }
1668 1668
1669 1669 rc = DDI_SUCCESS;
1670 1670
1671 1671 err:
1672 1672 kmem_free(hwid, CMDK_HWIDLEN);
1673 1673 return (rc);
1674 1674 }
1675 1675
1676 1676 static int
1677 1677 cmdk_get_modser(struct cmdk *dkp, int ioccmd, char *buf, int len)
1678 1678 {
1679 1679 dadk_ioc_string_t strarg;
1680 1680 int rval;
1681 1681 char *s;
1682 1682 char ch;
1683 1683 boolean_t ret;
1684 1684 int i;
1685 1685 int tb;
1686 1686
1687 1687 strarg.is_buf = buf;
1688 1688 strarg.is_size = len;
1689 1689 if (dadk_ioctl(DKTP_DATA,
1690 1690 dkp->dk_dev,
1691 1691 ioccmd,
1692 1692 (uintptr_t)&strarg,
1693 1693 FNATIVE | FKIOCTL,
1694 1694 NULL,
1695 1695 &rval) != 0)
1696 1696 return (0);
1697 1697
1698 1698 /*
1699 1699 * valid model/serial string must contain a non-zero non-space
1700 1700 * trim trailing spaces/NULL
1701 1701 */
1702 1702 ret = B_FALSE;
1703 1703 s = buf;
1704 1704 for (i = 0; i < strarg.is_size; i++) {
1705 1705 ch = *s++;
1706 1706 if (ch != ' ' && ch != '\0')
1707 1707 tb = i + 1;
1708 1708 if (ch != ' ' && ch != '\0' && ch != '0')
1709 1709 ret = B_TRUE;
1710 1710 }
1711 1711
1712 1712 if (ret == B_FALSE)
1713 1713 return (0);
1714 1714
1715 1715 return (tb);
1716 1716 }
1717 1717
1718 1718 /*
1719 1719 * Read a devid from on the first block of the last track of
1720 1720 * the last cylinder. Make sure what we read is a valid devid.
1721 1721 * Return DDI_SUCCESS or DDI_FAILURE.
1722 1722 */
1723 1723 static int
1724 1724 cmdk_devid_read(struct cmdk *dkp)
1725 1725 {
1726 1726 diskaddr_t blk;
1727 1727 struct dk_devid *dkdevidp;
1728 1728 uint_t *ip;
1729 1729 int chksum;
1730 1730 int i, sz;
1731 1731 tgdk_iob_handle handle = NULL;
1732 1732 int rc = DDI_FAILURE;
1733 1733
1734 1734 if (cmlb_get_devid_block(dkp->dk_cmlbhandle, &blk, 0))
1735 1735 goto err;
1736 1736
1737 1737 /* read the devid */
1738 1738 handle = dadk_iob_alloc(DKTP_DATA, blk, NBPSCTR, KM_SLEEP);
1739 1739 if (handle == NULL)
1740 1740 goto err;
1741 1741
1742 1742 dkdevidp = (struct dk_devid *)dadk_iob_xfer(DKTP_DATA, handle, B_READ);
1743 1743 if (dkdevidp == NULL)
1744 1744 goto err;
1745 1745
1746 1746 /* Validate the revision */
1747 1747 if ((dkdevidp->dkd_rev_hi != DK_DEVID_REV_MSB) ||
1748 1748 (dkdevidp->dkd_rev_lo != DK_DEVID_REV_LSB))
1749 1749 goto err;
1750 1750
1751 1751 /* Calculate the checksum */
1752 1752 chksum = 0;
1753 1753 ip = (uint_t *)dkdevidp;
1754 1754 for (i = 0; i < ((NBPSCTR - sizeof (int))/sizeof (int)); i++)
1755 1755 chksum ^= ip[i];
1756 1756 if (DKD_GETCHKSUM(dkdevidp) != chksum)
1757 1757 goto err;
1758 1758
1759 1759 /* Validate the device id */
1760 1760 if (ddi_devid_valid((ddi_devid_t)dkdevidp->dkd_devid) != DDI_SUCCESS)
1761 1761 goto err;
1762 1762
1763 1763 /* keep a copy of the device id */
1764 1764 sz = ddi_devid_sizeof((ddi_devid_t)dkdevidp->dkd_devid);
1765 1765 dkp->dk_devid = kmem_alloc(sz, KM_SLEEP);
1766 1766 bcopy(dkdevidp->dkd_devid, dkp->dk_devid, sz);
1767 1767
1768 1768 rc = DDI_SUCCESS;
1769 1769
1770 1770 err:
1771 1771 if (handle != NULL)
1772 1772 (void) dadk_iob_free(DKTP_DATA, handle);
1773 1773 return (rc);
1774 1774 }
1775 1775
1776 1776 /*
1777 1777 * Create a devid and write it on the first block of the last track of
1778 1778 * the last cylinder.
1779 1779 * Return DDI_SUCCESS or DDI_FAILURE.
1780 1780 */
1781 1781 static int
1782 1782 cmdk_devid_fabricate(struct cmdk *dkp)
1783 1783 {
1784 1784 ddi_devid_t devid = NULL; /* devid made by ddi_devid_init */
1785 1785 struct dk_devid *dkdevidp; /* devid struct stored on disk */
1786 1786 diskaddr_t blk;
1787 1787 tgdk_iob_handle handle = NULL;
1788 1788 uint_t *ip, chksum;
1789 1789 int i;
1790 1790 int rc = DDI_FAILURE;
1791 1791
1792 1792 if (ddi_devid_init(dkp->dk_dip, DEVID_FAB, 0, NULL, &devid) !=
1793 1793 DDI_SUCCESS)
1794 1794 goto err;
1795 1795
1796 1796 if (cmlb_get_devid_block(dkp->dk_cmlbhandle, &blk, 0)) {
1797 1797 /* no device id block address */
1798 1798 goto err;
1799 1799 }
1800 1800
1801 1801 handle = dadk_iob_alloc(DKTP_DATA, blk, NBPSCTR, KM_SLEEP);
1802 1802 if (!handle)
1803 1803 goto err;
1804 1804
1805 1805 /* Locate the buffer */
1806 1806 dkdevidp = (struct dk_devid *)dadk_iob_htoc(DKTP_DATA, handle);
1807 1807
1808 1808 /* Fill in the revision */
1809 1809 bzero(dkdevidp, NBPSCTR);
1810 1810 dkdevidp->dkd_rev_hi = DK_DEVID_REV_MSB;
1811 1811 dkdevidp->dkd_rev_lo = DK_DEVID_REV_LSB;
1812 1812
1813 1813 /* Copy in the device id */
1814 1814 i = ddi_devid_sizeof(devid);
1815 1815 if (i > DK_DEVID_SIZE)
1816 1816 goto err;
1817 1817 bcopy(devid, dkdevidp->dkd_devid, i);
1818 1818
1819 1819 /* Calculate the chksum */
1820 1820 chksum = 0;
1821 1821 ip = (uint_t *)dkdevidp;
1822 1822 for (i = 0; i < ((NBPSCTR - sizeof (int))/sizeof (int)); i++)
1823 1823 chksum ^= ip[i];
1824 1824
1825 1825 /* Fill in the checksum */
1826 1826 DKD_FORMCHKSUM(chksum, dkdevidp);
1827 1827
1828 1828 /* write the devid */
1829 1829 (void) dadk_iob_xfer(DKTP_DATA, handle, B_WRITE);
1830 1830
1831 1831 dkp->dk_devid = devid;
1832 1832
1833 1833 rc = DDI_SUCCESS;
1834 1834
1835 1835 err:
1836 1836 if (handle != NULL)
1837 1837 (void) dadk_iob_free(DKTP_DATA, handle);
1838 1838
1839 1839 if (rc != DDI_SUCCESS && devid != NULL)
1840 1840 ddi_devid_free(devid);
1841 1841
1842 1842 return (rc);
1843 1843 }
1844 1844
1845 1845 static void
1846 1846 cmdk_bbh_free_alts(struct cmdk *dkp)
1847 1847 {
1848 1848 if (dkp->dk_alts_hdl) {
1849 1849 (void) dadk_iob_free(DKTP_DATA, dkp->dk_alts_hdl);
1850 1850 kmem_free(dkp->dk_slc_cnt,
1851 1851 NDKMAP * (sizeof (uint32_t) + sizeof (struct alts_ent *)));
1852 1852 dkp->dk_alts_hdl = NULL;
1853 1853 }
1854 1854 }
1855 1855
1856 1856 static void
1857 1857 cmdk_bbh_reopen(struct cmdk *dkp)
1858 1858 {
1859 1859 tgdk_iob_handle handle = NULL;
1860 1860 diskaddr_t slcb, slcn, slce;
1861 1861 struct alts_parttbl *ap;
1862 1862 struct alts_ent *enttblp;
1863 1863 uint32_t altused;
1864 1864 uint32_t altbase;
1865 1865 uint32_t altlast;
1866 1866 int alts;
1867 1867 uint16_t vtoctag;
1868 1868 int i, j;
1869 1869
1870 1870 /* find slice with V_ALTSCTR tag */
1871 1871 for (alts = 0; alts < NDKMAP; alts++) {
1872 1872 if (cmlb_partinfo(
1873 1873 dkp->dk_cmlbhandle,
1874 1874 alts,
1875 1875 &slcn,
1876 1876 &slcb,
1877 1877 NULL,
1878 1878 &vtoctag,
1879 1879 0)) {
1880 1880 goto empty; /* no partition table exists */
1881 1881 }
1882 1882
1883 1883 if (vtoctag == V_ALTSCTR && slcn > 1)
1884 1884 break;
1885 1885 }
1886 1886 if (alts >= NDKMAP) {
1887 1887 goto empty; /* no V_ALTSCTR slice defined */
1888 1888 }
1889 1889
1890 1890 /* read in ALTS label block */
1891 1891 handle = dadk_iob_alloc(DKTP_DATA, slcb, NBPSCTR, KM_SLEEP);
1892 1892 if (!handle) {
1893 1893 goto empty;
1894 1894 }
1895 1895
1896 1896 ap = (struct alts_parttbl *)dadk_iob_xfer(DKTP_DATA, handle, B_READ);
1897 1897 if (!ap || (ap->alts_sanity != ALTS_SANITY)) {
1898 1898 goto empty;
1899 1899 }
1900 1900
1901 1901 altused = ap->alts_ent_used; /* number of BB entries */
1902 1902 altbase = ap->alts_ent_base; /* blk offset from begin slice */
1903 1903 altlast = ap->alts_ent_end; /* blk offset to last block */
1904 1904 /* ((altused * sizeof (struct alts_ent) + NBPSCTR - 1) & ~NBPSCTR) */
1905 1905
1906 1906 if (altused == 0 ||
1907 1907 altbase < 1 ||
1908 1908 altbase > altlast ||
1909 1909 altlast >= slcn) {
1910 1910 goto empty;
1911 1911 }
1912 1912 (void) dadk_iob_free(DKTP_DATA, handle);
1913 1913
1914 1914 /* read in ALTS remapping table */
1915 1915 handle = dadk_iob_alloc(DKTP_DATA,
1916 1916 slcb + altbase,
1917 1917 (altlast - altbase + 1) << SCTRSHFT, KM_SLEEP);
1918 1918 if (!handle) {
1919 1919 goto empty;
1920 1920 }
1921 1921
1922 1922 enttblp = (struct alts_ent *)dadk_iob_xfer(DKTP_DATA, handle, B_READ);
1923 1923 if (!enttblp) {
1924 1924 goto empty;
1925 1925 }
1926 1926
1927 1927 rw_enter(&dkp->dk_bbh_mutex, RW_WRITER);
1928 1928
1929 1929 /* allocate space for dk_slc_cnt and dk_slc_ent tables */
1930 1930 if (dkp->dk_slc_cnt == NULL) {
1931 1931 dkp->dk_slc_cnt = kmem_alloc(NDKMAP *
1932 1932 (sizeof (long) + sizeof (struct alts_ent *)), KM_SLEEP);
1933 1933 }
1934 1934 dkp->dk_slc_ent = (struct alts_ent **)(dkp->dk_slc_cnt + NDKMAP);
1935 1935
1936 1936 /* free previous BB table (if any) */
1937 1937 if (dkp->dk_alts_hdl) {
1938 1938 (void) dadk_iob_free(DKTP_DATA, dkp->dk_alts_hdl);
1939 1939 dkp->dk_alts_hdl = NULL;
1940 1940 dkp->dk_altused = 0;
1941 1941 }
1942 1942
1943 1943 /* save linkage to new BB table */
1944 1944 dkp->dk_alts_hdl = handle;
1945 1945 dkp->dk_altused = altused;
1946 1946
1947 1947 /*
1948 1948 * build indexes to BB table by slice
1949 1949 * effectively we have
1950 1950 * struct alts_ent *enttblp[altused];
1951 1951 *
1952 1952 * uint32_t dk_slc_cnt[NDKMAP];
1953 1953 * struct alts_ent *dk_slc_ent[NDKMAP];
1954 1954 */
1955 1955 for (i = 0; i < NDKMAP; i++) {
1956 1956 if (cmlb_partinfo(
1957 1957 dkp->dk_cmlbhandle,
1958 1958 i,
1959 1959 &slcn,
1960 1960 &slcb,
1961 1961 NULL,
1962 1962 NULL,
1963 1963 0)) {
1964 1964 goto empty1;
1965 1965 }
1966 1966
1967 1967 dkp->dk_slc_cnt[i] = 0;
1968 1968 if (slcn == 0)
1969 1969 continue; /* slice is not allocated */
1970 1970
1971 1971 /* last block in slice */
1972 1972 slce = slcb + slcn - 1;
1973 1973
1974 1974 /* find first remap entry in after beginnning of slice */
1975 1975 for (j = 0; j < altused; j++) {
1976 1976 if (enttblp[j].bad_start + enttblp[j].bad_end >= slcb)
1977 1977 break;
1978 1978 }
1979 1979 dkp->dk_slc_ent[i] = enttblp + j;
1980 1980
1981 1981 /* count remap entrys until end of slice */
1982 1982 for (; j < altused && enttblp[j].bad_start <= slce; j++) {
1983 1983 dkp->dk_slc_cnt[i] += 1;
1984 1984 }
1985 1985 }
1986 1986
1987 1987 rw_exit(&dkp->dk_bbh_mutex);
1988 1988 return;
1989 1989
1990 1990 empty:
1991 1991 rw_enter(&dkp->dk_bbh_mutex, RW_WRITER);
1992 1992 empty1:
1993 1993 if (handle && handle != dkp->dk_alts_hdl)
1994 1994 (void) dadk_iob_free(DKTP_DATA, handle);
1995 1995
1996 1996 if (dkp->dk_alts_hdl) {
1997 1997 (void) dadk_iob_free(DKTP_DATA, dkp->dk_alts_hdl);
1998 1998 dkp->dk_alts_hdl = NULL;
1999 1999 }
2000 2000
2001 2001 rw_exit(&dkp->dk_bbh_mutex);
2002 2002 }
2003 2003
2004 2004 /*ARGSUSED*/
2005 2005 static bbh_cookie_t
2006 2006 cmdk_bbh_htoc(opaque_t bbh_data, opaque_t handle)
2007 2007 {
2008 2008 struct bbh_handle *hp;
2009 2009 bbh_cookie_t ckp;
2010 2010
2011 2011 hp = (struct bbh_handle *)handle;
2012 2012 ckp = hp->h_cktab + hp->h_idx;
2013 2013 hp->h_idx++;
2014 2014 return (ckp);
2015 2015 }
2016 2016
2017 2017 /*ARGSUSED*/
2018 2018 static void
2019 2019 cmdk_bbh_freehandle(opaque_t bbh_data, opaque_t handle)
2020 2020 {
2021 2021 struct bbh_handle *hp;
2022 2022
2023 2023 hp = (struct bbh_handle *)handle;
2024 2024 kmem_free(handle, (sizeof (struct bbh_handle) +
2025 2025 (hp->h_totck * (sizeof (struct bbh_cookie)))));
2026 2026 }
2027 2027
2028 2028
2029 2029 /*
2030 2030 * cmdk_bbh_gethandle remaps the bad sectors to alternates.
2031 2031 * There are 7 different cases when the comparison is made
2032 2032 * between the bad sector cluster and the disk section.
2033 2033 *
2034 2034 * bad sector cluster gggggggggggbbbbbbbggggggggggg
2035 2035 * case 1: ddddd
2036 2036 * case 2: -d-----
2037 2037 * case 3: ddddd
2038 2038 * case 4: dddddddddddd
2039 2039 * case 5: ddddddd-----
2040 2040 * case 6: ---ddddddd
2041 2041 * case 7: ddddddd
2042 2042 *
2043 2043 * where: g = good sector, b = bad sector
2044 2044 * d = sector in disk section
2045 2045 * - = disk section may be extended to cover those disk area
2046 2046 */
2047 2047
2048 2048 static opaque_t
2049 2049 cmdk_bbh_gethandle(opaque_t bbh_data, struct buf *bp)
2050 2050 {
2051 2051 struct cmdk *dkp = (struct cmdk *)bbh_data;
2052 2052 struct bbh_handle *hp;
2053 2053 struct bbh_cookie *ckp;
2054 2054 struct alts_ent *altp;
2055 2055 uint32_t alts_used;
2056 2056 uint32_t part = CMDKPART(bp->b_edev);
2057 2057 daddr32_t lastsec;
2058 2058 long d_count;
2059 2059 int i;
2060 2060 int idx;
2061 2061 int cnt;
2062 2062
2063 2063 if (part >= V_NUMPAR)
2064 2064 return (NULL);
2065 2065
2066 2066 /*
2067 2067 * This if statement is atomic and it will succeed
2068 2068 * if there are no bad blocks (almost always)
2069 2069 *
2070 2070 * so this if is performed outside of the rw_enter for speed
2071 2071 * and then repeated inside the rw_enter for safety
2072 2072 */
2073 2073 if (!dkp->dk_alts_hdl) {
2074 2074 return (NULL);
2075 2075 }
2076 2076
2077 2077 rw_enter(&dkp->dk_bbh_mutex, RW_READER);
2078 2078
2079 2079 if (dkp->dk_alts_hdl == NULL) {
2080 2080 rw_exit(&dkp->dk_bbh_mutex);
2081 2081 return (NULL);
2082 2082 }
2083 2083
2084 2084 alts_used = dkp->dk_slc_cnt[part];
2085 2085 if (alts_used == 0) {
2086 2086 rw_exit(&dkp->dk_bbh_mutex);
2087 2087 return (NULL);
2088 2088 }
2089 2089 altp = dkp->dk_slc_ent[part];
2090 2090
2091 2091 /*
2092 2092 * binary search for the largest bad sector index in the alternate
2093 2093 * entry table which overlaps or larger than the starting d_sec
2094 2094 */
2095 2095 i = cmdk_bbh_bsearch(altp, alts_used, GET_BP_SEC(bp));
2096 2096 /* if starting sector is > the largest bad sector, return */
2097 2097 if (i == -1) {
2098 2098 rw_exit(&dkp->dk_bbh_mutex);
2099 2099 return (NULL);
2100 2100 }
2101 2101 /* i is the starting index. Set altp to the starting entry addr */
2102 2102 altp += i;
2103 2103
2104 2104 d_count = bp->b_bcount >> SCTRSHFT;
2105 2105 lastsec = GET_BP_SEC(bp) + d_count - 1;
2106 2106
2107 2107 /* calculate the number of bad sectors */
2108 2108 for (idx = i, cnt = 0; idx < alts_used; idx++, altp++, cnt++) {
2109 2109 if (lastsec < altp->bad_start)
2110 2110 break;
2111 2111 }
2112 2112
2113 2113 if (!cnt) {
2114 2114 rw_exit(&dkp->dk_bbh_mutex);
2115 2115 return (NULL);
2116 2116 }
2117 2117
2118 2118 /* calculate the maximum number of reserved cookies */
2119 2119 cnt <<= 1;
2120 2120 cnt++;
2121 2121
2122 2122 /* allocate the handle */
2123 2123 hp = (struct bbh_handle *)kmem_zalloc((sizeof (*hp) +
2124 2124 (cnt * sizeof (*ckp))), KM_SLEEP);
2125 2125
2126 2126 hp->h_idx = 0;
2127 2127 hp->h_totck = cnt;
2128 2128 ckp = hp->h_cktab = (struct bbh_cookie *)(hp + 1);
2129 2129 ckp[0].ck_sector = GET_BP_SEC(bp);
2130 2130 ckp[0].ck_seclen = d_count;
2131 2131
2132 2132 altp = dkp->dk_slc_ent[part];
2133 2133 altp += i;
2134 2134 for (idx = 0; i < alts_used; i++, altp++) {
2135 2135 /* CASE 1: */
2136 2136 if (lastsec < altp->bad_start)
2137 2137 break;
2138 2138
2139 2139 /* CASE 3: */
2140 2140 if (ckp[idx].ck_sector > altp->bad_end)
2141 2141 continue;
2142 2142
2143 2143 /* CASE 2 and 7: */
2144 2144 if ((ckp[idx].ck_sector >= altp->bad_start) &&
2145 2145 (lastsec <= altp->bad_end)) {
2146 2146 ckp[idx].ck_sector = altp->good_start +
2147 2147 ckp[idx].ck_sector - altp->bad_start;
2148 2148 break;
2149 2149 }
2150 2150
2151 2151 /* at least one bad sector in our section. break it. */
2152 2152 /* CASE 5: */
2153 2153 if ((lastsec >= altp->bad_start) &&
2154 2154 (lastsec <= altp->bad_end)) {
2155 2155 ckp[idx+1].ck_seclen = lastsec - altp->bad_start + 1;
2156 2156 ckp[idx].ck_seclen -= ckp[idx+1].ck_seclen;
2157 2157 ckp[idx+1].ck_sector = altp->good_start;
2158 2158 break;
2159 2159 }
2160 2160 /* CASE 6: */
2161 2161 if ((ckp[idx].ck_sector <= altp->bad_end) &&
2162 2162 (ckp[idx].ck_sector >= altp->bad_start)) {
2163 2163 ckp[idx+1].ck_seclen = ckp[idx].ck_seclen;
2164 2164 ckp[idx].ck_seclen = altp->bad_end -
2165 2165 ckp[idx].ck_sector + 1;
2166 2166 ckp[idx+1].ck_seclen -= ckp[idx].ck_seclen;
2167 2167 ckp[idx].ck_sector = altp->good_start +
2168 2168 ckp[idx].ck_sector - altp->bad_start;
2169 2169 idx++;
2170 2170 ckp[idx].ck_sector = altp->bad_end + 1;
2171 2171 continue; /* check rest of section */
2172 2172 }
2173 2173
2174 2174 /* CASE 4: */
2175 2175 ckp[idx].ck_seclen = altp->bad_start - ckp[idx].ck_sector;
2176 2176 ckp[idx+1].ck_sector = altp->good_start;
2177 2177 ckp[idx+1].ck_seclen = altp->bad_end - altp->bad_start + 1;
2178 2178 idx += 2;
2179 2179 ckp[idx].ck_sector = altp->bad_end + 1;
2180 2180 ckp[idx].ck_seclen = lastsec - altp->bad_end;
2181 2181 }
2182 2182
2183 2183 rw_exit(&dkp->dk_bbh_mutex);
2184 2184 return ((opaque_t)hp);
2185 2185 }
2186 2186
2187 2187 static int
2188 2188 cmdk_bbh_bsearch(struct alts_ent *buf, int cnt, daddr32_t key)
2189 2189 {
2190 2190 int i;
2191 2191 int ind;
2192 2192 int interval;
2193 2193 int mystatus = -1;
2194 2194
2195 2195 if (!cnt)
2196 2196 return (mystatus);
2197 2197
2198 2198 ind = 1; /* compiler complains about possible uninitialized var */
2199 2199 for (i = 1; i <= cnt; i <<= 1)
2200 2200 ind = i;
2201 2201
2202 2202 for (interval = ind; interval; ) {
2203 2203 if ((key >= buf[ind-1].bad_start) &&
2204 2204 (key <= buf[ind-1].bad_end)) {
2205 2205 return (ind-1);
2206 2206 } else {
2207 2207 interval >>= 1;
2208 2208 if (key < buf[ind-1].bad_start) {
2209 2209 /* record the largest bad sector index */
2210 2210 mystatus = ind-1;
2211 2211 if (!interval)
2212 2212 break;
2213 2213 ind = ind - interval;
2214 2214 } else {
2215 2215 /*
2216 2216 * if key is larger than the last element
2217 2217 * then break
2218 2218 */
2219 2219 if ((ind == cnt) || !interval)
2220 2220 break;
2221 2221 if ((ind+interval) <= cnt)
2222 2222 ind += interval;
2223 2223 }
2224 2224 }
2225 2225 }
2226 2226 return (mystatus);
2227 2227 }
↓ open down ↓ |
2009 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX