Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/avs/ns/sdbc/sd_misc.c
+++ new/usr/src/uts/common/avs/ns/sdbc/sd_misc.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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #define _SCM_
27 27
28 28 #include <sys/types.h>
29 29 #include <sys/ksynch.h>
30 30 #include <sys/cmn_err.h>
31 31 #include <sys/modctl.h>
32 32 #include <sys/conf.h>
33 33 #include <sys/errno.h>
34 34 #include <sys/file.h>
35 35 #include <sys/kmem.h>
36 36 #include <sys/cred.h>
37 37 #include <sys/ddi.h>
38 38 #include <sys/nsc_thread.h>
39 39
40 40 #include "sd_bcache.h"
41 41 #include "sd_misc.h"
42 42 #include "sd_trace.h"
43 43 #include "sd_ft.h"
44 44 #include "sd_io.h"
45 45 #include "sd_bio.h"
46 46 #include "sd_pcu.h"
47 47 #include "sd_tdaemon.h"
48 48 #include "sdbc_ioctl.h"
49 49 #include <sys/ncall/ncall.h>
50 50 #include <sys/nsctl/nsctl.h>
51 51 #include <sys/nsctl/nsvers.h>
52 52
53 53 #include <sys/sdt.h> /* dtrace is S10 or later */
54 54
55 55 #include <sys/unistat/spcs_s.h>
56 56 #include <sys/unistat/spcs_s_k.h>
57 57 #include <sys/unistat/spcs_errors.h>
58 58 static dev_info_t *dev_dip;
59 59 dev_info_t *sdbc_get_dip();
60 60
61 61
62 62 /*
63 63 * A global variable to set the threshold for large writes to
64 64 * be in write through mode when NVRAM is present. This should
65 65 * solve the NVRAM bandwidth problem.
66 66 */
67 67
68 68 int sdbc_wrthru_len;
69 69 nsc_size_t sdbc_max_fbas = _SD_MAX_FBAS;
70 70 int sdbc_max_devs = 0;
71 71
72 72 krwlock_t sdbc_queue_lock;
73 73
74 74 static int _sd_debug_level = 0;
75 75
76 76 static kmutex_t _sd_block_lk;
77 77
78 78 #define REGISTER_SVC(X, Y) (ncall_register_svc(X, Y))
79 79 #define UNREGISTER_SVC(X) (ncall_unregister_svc(X))
80 80
81 81 const int sdbc_major_rev = ISS_VERSION_MAJ;
82 82 const int sdbc_minor_rev = ISS_VERSION_MIN;
83 83 const int sdbc_micro_rev = ISS_VERSION_MIC;
84 84 const int sdbc_baseline_rev = ISS_VERSION_NUM;
85 85 static char sdbc_version[16];
86 86
87 87 static int _sdbc_attached = 0;
88 88
89 89 static int _sdbc_print(dev_t dev, char *s);
90 90 static int sdbcunload(void);
91 91 static int sdbcload(void);
92 92 static int sdbcopen(dev_t *devp, int flag, int otyp, cred_t *crp);
93 93 static int sdbcclose(dev_t dev, int flag, int otyp, cred_t *crp);
94 94 static int sdbcioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *crp,
95 95 int *rvp);
96 96 static int _sdbc_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
97 97 static int _sdbc_probe(dev_info_t *dip);
98 98 static int _sdbc_attach(dev_info_t *, ddi_attach_cmd_t);
99 99 static int _sdbc_detach(dev_info_t *, ddi_detach_cmd_t);
100 100 static int _sdbc_reset(dev_info_t *, ddi_reset_cmd_t);
101 101
102 102 #ifdef sun
103 103 /*
104 104 * Solaris specific driver module interface code.
105 105 */
106 106
107 107 #ifdef USES_SOFT_STATE
108 108 struct sdbc_state {
109 109 dev_info_t *dip; /* everyone would need a devinfo */
110 110 };
111 111
112 112 static void *sdbc_statep; /* for soft state routines */
113 113 #endif /* USES_SOFT_STATE */
114 114
115 115 static struct cb_ops sdbc_cb_ops = {
116 116 sdbcopen, /* open */
117 117 sdbcclose, /* close */
118 118 nodev, /* not a block driver, strategy not an entry point */
119 119 _sdbc_print, /* no print routine */
120 120 nodev, /* no dump routine */
121 121 nodev, /* read */
122 122 nodev, /* write */
123 123 (int (*) ()) sdbcioctl, /* ioctl */
124 124 nodev, /* no devmap routine */
125 125 nodev, /* no mmap routine */
126 126 nodev, /* no segmap routine */
127 127 nochpoll, /* no chpoll routine */
128 128 ddi_prop_op,
129 129 0, /* not a STREAMS driver, no cb_str routine */
130 130 D_NEW | D_MP, /* safe for multi-thread/multi-processor */
131 131 };
132 132
133 133
134 134 static struct dev_ops sdbc_ops = {
135 135 DEVO_REV, /* Driver build version */
136 136 0, /* device reference count */
137 137 _sdbc_getinfo,
138 138 nulldev,
139 139 _sdbc_probe,
140 140 _sdbc_attach,
141 141 _sdbc_detach,
142 142 _sdbc_reset,
143 143 &sdbc_cb_ops,
144 144 (struct bus_ops *)NULL
↓ open down ↓ |
144 lines elided |
↑ open up ↑ |
145 145 };
146 146
147 147 static struct modldrv sdbc_ldrv = {
148 148 &mod_driverops,
149 149 "nws:Storage Cache:" ISS_VERSION_STR,
150 150 &sdbc_ops
151 151 };
152 152
153 153 static struct modlinkage sdbc_modlinkage = {
154 154 MODREV_1,
155 - &sdbc_ldrv,
156 - NULL
155 + { &sdbc_ldrv, NULL }
157 156 };
158 157
159 158 /*
160 159 * dynmem interface
161 160 */
162 161 static int mutex_and_condvar_flag;
163 162
164 163 /*
165 164 * Solaris module load time code
166 165 */
167 166 int
168 167 _init(void)
169 168 {
170 169
171 170 int err;
172 171
173 172 mutex_and_condvar_flag = 0;
174 173
175 174 #ifdef USES_SOFT_STATE
176 175 ddi_soft_state_init(&sdbc_statep, sizeof (struct sdbc_state),
177 176 MAX_INSTANCES);
178 177 #endif /* USES_SOFT_STATE */
179 178
180 179 /*
181 180 * It is "load" time, call the unixware equivalent.
182 181 */
183 182 err = sdbcload();
184 183 if (!err)
185 184 err = mod_install(&sdbc_modlinkage);
186 185
187 186 if (err) {
188 187 (void) sdbcunload();
189 188 #ifdef USES_SOFT_STATE
190 189 ddi_soft_state_fini(&sdbc_statep);
191 190 #endif /* USES_SOFT_STATE */
192 191 }
193 192
194 193 if (!err) {
195 194 mutex_and_condvar_flag = 1;
196 195 mutex_init(&dynmem_processing_dm.thread_dm_lock, "dynmem",
197 196 MUTEX_DRIVER, NULL);
198 197 cv_init(&dynmem_processing_dm.thread_dm_cv, "dynmem",
199 198 CV_DRIVER, NULL);
200 199 }
201 200
202 201 return (err);
203 202
204 203 }
205 204 /*
206 205 * Solaris module unload time code
207 206 */
208 207
209 208 int
210 209 _fini(void)
211 210 {
212 211 int err;
213 212
214 213 if (_sd_cache_initialized) {
215 214 return (EBUSY);
216 215 } else if (_sd_ioset &&
217 216 (_sd_ioset->set_nlive || _sd_ioset->set_nthread)) {
218 217 cmn_err(CE_WARN, "!sdbc:_fini() %d threads still "
219 218 "active; %d threads in set\n", _sd_ioset->set_nlive,
220 219 _sd_ioset->set_nthread);
221 220 return (EBUSY);
222 221 }
223 222 if ((err = mod_remove(&sdbc_modlinkage)) == 0) {
224 223 DTRACE_PROBE2(_sdbc_fini_mod_remove_succeeded,
225 224 int, err,
226 225 struct modlinkage *, &sdbc_modlinkage);
227 226 err = sdbcunload();
228 227 #ifdef USES_SOFT_STATE
229 228 ddi_soft_state_fini(&sdbc_statep);
230 229 #endif /* USES_SOFT_STATE */
231 230
232 231 if (mutex_and_condvar_flag) {
233 232 cv_destroy(&dynmem_processing_dm.thread_dm_cv);
234 233 mutex_destroy(&dynmem_processing_dm.thread_dm_lock);
235 234 mutex_and_condvar_flag = 0;
236 235 }
237 236 }
238 237
239 238 return (err);
240 239 }
241 240
242 241 /*
243 242 * Solaris module info code
244 243 */
245 244 int
246 245 _info(struct modinfo *modinfop)
247 246 {
248 247 return (mod_info(&sdbc_modlinkage, modinfop));
249 248 }
250 249
251 250 /*ARGSUSED*/
252 251 static int
253 252 _sdbc_probe(dev_info_t *dip)
254 253 {
255 254 return (DDI_PROBE_SUCCESS);
256 255 }
257 256
258 257 /*
259 258 * Attach an instance of the device. This happens before an open
260 259 * can succeed.
261 260 */
262 261 static int
263 262 _sdbc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
264 263 {
265 264 _dm_process_vars_t local_dm_process_vars;
266 265 struct buf bp;
267 266
268 267 if (cmd != DDI_ATTACH)
269 268 return (DDI_FAILURE);
270 269
271 270 /*
272 271 * Get the threshold value for setting large writes in
273 272 * write through mode(when NVRAM is present)
274 273 */
275 274
276 275 sdbc_wrthru_len = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
277 276 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_wrthru_thresh", 64);
278 277
279 278 /* Get sdbc_max_fbas from sdbc.conf */
280 279 sdbc_max_fbas = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
281 280 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_max_fbas",
282 281 _SD_MAX_FBAS);
283 282
284 283 bp.b_bcount = (size_t)FBA_SIZE(sdbc_max_fbas);
285 284 minphys(&bp); /* clamps value to maxphys */
286 285
287 286 sdbc_max_fbas = FBA_NUM(bp.b_bcount);
288 287
289 288 if (sdbc_max_fbas > _SD_MAX_FBAS) {
290 289 cmn_err(CE_WARN,
291 290 "!_sdbc_attach: sdbc_max_fbas set to %d", _SD_MAX_FBAS);
292 291 sdbc_max_fbas = _SD_MAX_FBAS;
293 292 }
294 293
295 294 /*
296 295 * -get the maximum list length for multipage dynmem
297 296 * -time between aging
298 297 * -number of agings before dealloc
299 298 * -what to report D0=shutdown, D1=thread variables
300 299 */
301 300 dynmem_processing_dm.max_dyn_list = MAX_DYN_LIST_DEFAULT;
302 301 dynmem_processing_dm.monitor_dynmem_process =
303 302 MONITOR_DYNMEM_PROCESS_DEFAULT;
304 303 dynmem_processing_dm.cache_aging_ct1 = CACHE_AGING_CT_DEFAULT;
305 304 dynmem_processing_dm.cache_aging_ct2 = CACHE_AGING_CT_DEFAULT;
306 305 dynmem_processing_dm.cache_aging_ct3 = CACHE_AGING_CT_DEFAULT;
307 306 dynmem_processing_dm.cache_aging_sec1 = CACHE_AGING_SEC1_DEFAULT;
308 307 dynmem_processing_dm.cache_aging_sec2 = CACHE_AGING_SEC2_DEFAULT;
309 308 dynmem_processing_dm.cache_aging_sec3 = CACHE_AGING_SEC3_DEFAULT;
310 309 dynmem_processing_dm.cache_aging_pcnt1 = CACHE_AGING_PCNT1_DEFAULT;
311 310 dynmem_processing_dm.cache_aging_pcnt2 = CACHE_AGING_PCNT2_DEFAULT;
312 311 dynmem_processing_dm.max_holds_pcnt = MAX_HOLDS_PCNT_DEFAULT;
313 312 dynmem_processing_dm.process_directive = PROCESS_DIRECTIVE_DEFAULT;
314 313
315 314 local_dm_process_vars.max_dyn_list = ddi_prop_get_int(DDI_DEV_T_ANY,
316 315 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_max_dyn_list",
317 316 MAX_DYN_LIST_DEFAULT);
318 317
319 318 local_dm_process_vars.monitor_dynmem_process =
320 319 ddi_prop_get_int(DDI_DEV_T_ANY, dip,
321 320 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_monitor_dynmem",
322 321 MONITOR_DYNMEM_PROCESS_DEFAULT);
323 322
324 323 local_dm_process_vars.cache_aging_ct1 = ddi_prop_get_int(DDI_DEV_T_ANY,
325 324 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_ct1",
326 325 CACHE_AGING_CT_DEFAULT);
327 326
328 327 local_dm_process_vars.cache_aging_ct2 = ddi_prop_get_int(DDI_DEV_T_ANY,
329 328 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_ct2",
330 329 CACHE_AGING_CT_DEFAULT);
331 330
332 331 local_dm_process_vars.cache_aging_ct3 = ddi_prop_get_int(DDI_DEV_T_ANY,
333 332 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_ct3",
334 333 CACHE_AGING_CT_DEFAULT);
335 334
336 335 local_dm_process_vars.cache_aging_sec1 = ddi_prop_get_int(DDI_DEV_T_ANY,
337 336 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_sec1",
338 337 CACHE_AGING_SEC1_DEFAULT);
339 338
340 339 local_dm_process_vars.cache_aging_sec2 = ddi_prop_get_int(DDI_DEV_T_ANY,
341 340 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_sec2",
342 341 CACHE_AGING_SEC2_DEFAULT);
343 342
344 343 local_dm_process_vars.cache_aging_sec3 = ddi_prop_get_int(DDI_DEV_T_ANY,
345 344 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_sec3",
346 345 CACHE_AGING_SEC3_DEFAULT);
347 346
348 347 local_dm_process_vars.cache_aging_pcnt1 =
349 348 ddi_prop_get_int(DDI_DEV_T_ANY, dip,
350 349 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_pcnt1",
351 350 CACHE_AGING_PCNT1_DEFAULT);
352 351
353 352 local_dm_process_vars.cache_aging_pcnt2 =
354 353 ddi_prop_get_int(DDI_DEV_T_ANY, dip,
355 354 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_pcnt2",
356 355 CACHE_AGING_PCNT2_DEFAULT);
357 356
358 357 local_dm_process_vars.process_directive =
359 358 ddi_prop_get_int(DDI_DEV_T_ANY, dip,
360 359 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_process_directive",
361 360 PROCESS_DIRECTIVE_DEFAULT);
362 361
363 362 local_dm_process_vars.max_holds_pcnt = ddi_prop_get_int(DDI_DEV_T_ANY,
364 363 dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_max_holds_pcnt",
365 364 MAX_HOLDS_PCNT_DEFAULT);
366 365
367 366 (void) sdbc_edit_xfer_process_vars_dm(&local_dm_process_vars);
368 367
369 368 #define MINOR_NAME "c,sdbc" /* character device */
370 369 #define MINOR_NUMBER 0
371 370 #ifdef MINOR_NAME
372 371 if (ddi_create_minor_node(dip, MINOR_NAME, S_IFCHR,
373 372 MINOR_NUMBER, DDI_PSEUDO, 0) != DDI_SUCCESS) {
374 373 /* free anything we allocated here */
375 374 return (DDI_FAILURE);
376 375 }
377 376 #endif /* MINOR_NAME */
378 377
379 378 /* Announce presence of the device */
380 379 ddi_report_dev(dip);
381 380 dev_dip = dip;
382 381 /* mark the device as attached, opens may proceed */
383 382 _sdbc_attached = 1;
384 383
385 384 rw_init(&sdbc_queue_lock, NULL, RW_DRIVER, NULL);
386 385
387 386 return (DDI_SUCCESS);
388 387 }
389 388
390 389 /*ARGSUSED*/
391 390 static int
392 391 _sdbc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
393 392 {
394 393 if (cmd == DDI_DETACH) {
395 394 /*
396 395 * Check first if the cache is still in use
397 396 * and if it is, prevent the detach.
398 397 */
399 398 if (_sd_cache_initialized)
400 399 return (EBUSY);
401 400
402 401 _sdbc_attached = 0;
403 402
404 403 rw_destroy(&sdbc_queue_lock);
405 404 dev_dip = NULL;
406 405
407 406 return (DDI_SUCCESS);
408 407 } else
409 408 return (DDI_FAILURE);
410 409 }
411 410
412 411 /*ARGSUSED*/
413 412 static int
414 413 _sdbc_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
415 414 {
416 415 return (DDI_SUCCESS);
417 416 }
418 417
419 418 /*ARGSUSED*/
420 419 static int
421 420 _sdbc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
422 421 {
423 422 dev_t dev;
424 423 #ifdef USES_SOFT_STATE
425 424 struct sdbc_state *xsp;
426 425 int instance;
427 426 #endif /* USES_SOFT_STATE */
428 427 int rc;
429 428
430 429 switch (cmd) {
431 430 case DDI_INFO_DEVT2INSTANCE:
432 431 dev = (dev_t)arg;
433 432 /* The "instance" number is the minor number */
434 433 *result = (void *)(unsigned long)getminor(dev);
435 434 rc = DDI_SUCCESS;
436 435 break;
437 436
438 437 case DDI_INFO_DEVT2DEVINFO:
439 438 dev = (dev_t)arg;
440 439 #ifdef USES_SOFT_STATE
441 440 /* the instance number is the minor number */
442 441 instance = getminor(dev);
443 442 xsp = ddi_get_soft_state(sdbc_statep, instance);
444 443 if (xsp == NULL)
445 444 return (DDI_FAILURE);
446 445 *result = (void *) xsp->dip;
447 446 #else
448 447 *result = (void *) NULL;
449 448 #endif /* USES_SOFT_STATE */
450 449 rc = DDI_SUCCESS;
451 450 break;
452 451
453 452 default:
454 453 rc = DDI_FAILURE;
455 454 break;
456 455 }
457 456 return (rc);
458 457 }
459 458
460 459 /*ARGSUSED*/
461 460 int
462 461 _sdbc_print(dev_t dev, char *s)
463 462 {
464 463 cmn_err(CE_WARN, "!sdbc(_sdbc_print) %s", s);
465 464 return (0);
466 465 }
467 466 #else
468 467 MOD_DRV_WRAPPER(sdbc, sdbcload, sdbcunload, NULL, "Storage Device Block Cache");
469 468 #endif /* sun */
470 469
471 470 static int sdbc_inited;
472 471
473 472 static int
474 473 sdbcinit(void)
475 474 {
476 475 int rc;
477 476
478 477 sdbc_inited = 0;
479 478
480 479 (void) strncpy(sdbc_version, _VERSION_, sizeof (sdbc_version));
481 480
482 481 mutex_init(&_sd_cache_lock, NULL, MUTEX_DRIVER, NULL);
483 482 mutex_init(&_sdbc_config_lock, NULL, MUTEX_DRIVER, NULL);
484 483
485 484 #ifdef m88k
486 485 REGISTER_SVC(SD_DUAL_WRITE, r_sd_ifs_write);
487 486 REGISTER_SVC(SD_DUAL_READ, r_sd_ifs_read);
488 487 REGISTER_SVC(SD_SET_CD, r_sd_set_cd);
489 488 REGISTER_SVC(SD_GETSIZE, r_sd_getsize);
490 489 REGISTER_SVC(SD_DUAL_OPEN, r_sd_ifs_open);
491 490 REGISTER_SVC(SD_REMOTE_FLUSH, r_sd_remote_flush);
492 491 REGISTER_SVC(SD_SGREMOTE_FLUSH, r_sd_sgremote_flush);
493 492 REGISTER_SVC(SD_DISK_IO, r_sd_disk_io);
494 493 REGISTER_SVC(SD_GET_BMAP, r_rem_get_bmap);
495 494
496 495 if ((rc = hpf_register_module("SDBC", _sd_hpf_stats)) != 0)
497 496 return (rc);
498 497 #endif
499 498 REGISTER_SVC(SD_ENABLE, r_sd_ifs_cache_enable);
500 499 REGISTER_SVC(SD_DISABLE, r_sd_ifs_cache_disable);
501 500 REGISTER_SVC(SD_CD_DISCARD, r_cd_discard);
502 501
503 502 cv_init(&_sd_flush_cv, NULL, CV_DRIVER, NULL);
504 503
505 504 mutex_init(&_sd_block_lk, NULL, MUTEX_DRIVER, NULL);
506 505
507 506 sdbc_max_devs = nsc_max_devices();
508 507
509 508 /*
510 509 * Initialize the bitmap array that would be useful in determining
511 510 * if the mask is not fragmented, instead of determinig this
512 511 * at run time. Also initialize a lookup array for each mask, with
513 512 * the starting position, the length, and the mask subset
514 513 */
515 514 _sd_init_contig_bmap();
516 515 _sd_init_lookup_map();
517 516
518 517 if ((rc = _sdbc_iobuf_load()) != 0)
519 518 return (rc);
520 519 if ((rc = _sdbc_handles_load()) != 0)
521 520 return (rc);
522 521 if ((rc = _sdbc_tr_load()) != 0)
523 522 return (rc);
524 523 if ((rc = _sdbc_ft_load()) != 0)
525 524 return (rc);
526 525 if ((rc = _sdbc_tdaemon_load()) != 0)
527 526 return (rc);
528 527 if ((rc = _sdbc_hash_load()) != 0)
529 528 return (rc);
530 529 #ifdef DEBUG
531 530 _sdbc_ioj_load();
532 531 #endif
533 532 sdbc_inited = 1;
534 533
535 534 return (0);
536 535 }
537 536
538 537 static int
539 538 sdbcunload(void)
540 539 {
541 540 if (_sd_cache_initialized) {
542 541 cmn_err(CE_WARN,
543 542 "!sdbc(sdbcunload) cannot unload module - cache in use!");
544 543 return (EEXIST);
545 544 }
546 545 #ifdef m88k
547 546 UNREGISTER_SVC(SD_DUAL_WRITE);
548 547 UNREGISTER_SVC(SD_DUAL_READ);
549 548 UNREGISTER_SVC(SD_SET_CD);
550 549 UNREGISTER_SVC(SD_GETSIZE);
551 550 UNREGISTER_SVC(SD_DUAL_OPEN);
552 551 UNREGISTER_SVC(SD_REMOTE_FLUSH);
553 552 UNREGISTER_SVC(SD_SGREMOTE_FLUSH);
554 553 UNREGISTER_SVC(SD_DISK_IO);
555 554 UNREGISTER_SVC(SD_GET_BMAP);
556 555
557 556 (void) hpf_unregister_module("SDBC");
558 557 #endif
559 558 UNREGISTER_SVC(SD_ENABLE);
560 559 UNREGISTER_SVC(SD_DISABLE);
561 560 UNREGISTER_SVC(SD_CD_DISCARD);
562 561
563 562 cv_destroy(&_sd_flush_cv);
564 563 mutex_destroy(&_sd_block_lk);
565 564
566 565 _sdbc_hash_unload();
567 566 _sdbc_ft_unload();
568 567 _sdbc_tr_unload();
569 568 _sdbc_tdaemon_unload();
570 569 _sdbc_handles_unload();
571 570 _sdbc_iobuf_unload();
572 571 #ifdef DEBUG
573 572 _sdbc_ioj_unload();
574 573 #endif
575 574
576 575 mutex_destroy(&_sd_cache_lock);
577 576 mutex_destroy(&_sdbc_config_lock);
578 577
579 578 /*
580 579 * Normally we would unregister memory at deconfig time.
581 580 * However when chasing things like memory leaks it is
582 581 * useful to defer until unload time.
583 582 */
584 583 if (_sdbc_memtype_deconfigure_delayed)
585 584 _sdbc_memtype_deconfigure();
586 585
587 586 return (0);
588 587 }
589 588
590 589
591 590 static int
592 591 sdbcload(void)
593 592 {
594 593 int err;
595 594
596 595 if ((err = sdbcinit()) != 0) {
597 596 (void) sdbcunload();
598 597 return (err);
599 598 }
600 599 return (0);
601 600 }
602 601
603 602
604 603 /* ARGSUSED */
605 604
606 605 static int
607 606 sdbcopen(dev_t *devp, int flag, int otyp, cred_t *crp)
608 607 {
609 608 int nd = nsc_node_id();
610 609
611 610 /*
612 611 * If we were statically linked in then returning an error out
613 612 * of sdbcinit won't prevent someone from coming thru here.
614 613 * We must prevent them from getting any further.
615 614 */
616 615 if (!sdbc_inited)
617 616 return (EINVAL);
618 617
619 618 if (nd < nsc_min_nodeid) {
620 619 cmn_err(CE_WARN,
621 620 "!sdbc(sdbcopen) open failed, systemid (%d) must be >= %d",
622 621 nd, nsc_min_nodeid);
623 622 return (EINVAL);
624 623 }
625 624 if (!_sdbc_attached)
626 625 return (ENXIO);
627 626
628 627 return (0);
629 628 }
630 629
631 630
632 631 /* ARGSUSED */
633 632
634 633 static int
635 634 sdbcclose(dev_t dev, int flag, int otyp, cred_t *crp)
636 635 {
637 636 return (0);
638 637 }
639 638
640 639 #ifdef _MULTI_DATAMODEL
641 640 static int
642 641 convert_ioctl_args(int cmd, void *arg, int mode, _sdbc_ioctl_t *args)
643 642 /*
644 643 * convert_ioctl-args - Do a case by case conversion of a ILP32 ioctl
645 644 * structure to an LP64 structure.
646 645 * The main concern here is whether to sign-extend or not. The rule
647 646 * is that pointers are not sign extended, the rest are obvious.
648 647 * Since most everything is sign-extended the definition of
649 648 * _sdbc_ioctl32_t uses signed fields.
650 649 *
651 650 */
652 651 {
653 652 _sdbc_ioctl32_t args32;
654 653
655 654 if (ddi_copyin(arg, &args32, sizeof (_sdbc_ioctl32_t), mode))
656 655 return (EFAULT);
657 656
658 657 bzero((void *) args, sizeof (_sdbc_ioctl_t));
659 658
660 659 switch (cmd) {
661 660
662 661 case SDBC_UNUSED_1:
663 662 case SDBC_UNUSED_2:
664 663 case SDBC_UNUSED_3:
665 664 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
666 665 cmn_err(CE_WARN,
667 666 "!sdbc(convert_ioctl_args) obsolete sdbc ioctl used");
668 667 return (EINVAL);
669 668
670 669 case SDBC_ADUMP:
671 670 args->arg0 = args32.arg0; /* cd */
672 671 args->arg1 = (uint32_t)args32.arg1; /* &tt */
673 672 args->arg2 = (uint32_t)args32.arg2; /* NULL (buf) */
674 673 args->arg3 = args32.arg3; /* size of buf */
675 674 args->arg4 = args32.arg4; /* flag */
676 675 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
677 676 break;
678 677
679 678 case SDBC_TEST_INIT:
680 679 args->arg0 = (uint32_t)args32.arg0; /* fname (char *) */
681 680 args->arg1 = args32.arg1; /* index */
682 681 args->arg2 = args32.arg2; /* len */
683 682 args->arg3 = args32.arg3; /* track size */
684 683 args->arg4 = args32.arg4; /* flag */
685 684 break;
686 685
687 686 case SDBC_TEST_START:
688 687 args->arg0 = args32.arg0; /* num */
689 688 args->arg1 = args32.arg1; /* type */
690 689 args->arg2 = args32.arg2; /* loops */
691 690 args->arg3 = args32.arg3; /* from */
692 691 args->arg4 = args32.arg4; /* seed */
693 692 break;
694 693
695 694 case SDBC_TEST_END:
696 695 break;
697 696
698 697 case SDBC_ENABLE:
699 698 case SDBC_VERSION:
700 699 args->arg0 = (uint32_t)args32.arg0; /* pointer */
701 700 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
702 701 break;
703 702
704 703 case SDBC_DISABLE:
705 704 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
706 705 break;
707 706
708 707 case SDBC_GET_CLUSTER_SIZE:
709 708 args->arg0 = (uint32_t)args32.arg0; /* (int * ) */
710 709 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
711 710 break;
712 711
713 712 /* get the gl_file data */
714 713 case SDBC_GET_CLUSTER_DATA:
715 714 /* pointer to array[2*cluster_size] */
716 715 args->arg0 = (uint32_t)args32.arg0;
717 716 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
718 717 break;
719 718
720 719 /* get the size of the global info pages for each board */
721 720 case SDBC_GET_GLMUL_SIZES:
722 721 args->arg0 = (uint32_t)args32.arg0; /* int[CACHE_MEM_PAD] * */
723 722 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
724 723 break;
725 724
726 725 /* get the global info about write blocks */
727 726 case SDBC_GET_GLMUL_INFO:
728 727 /* pointer to array[2*(sum of GLMUL_SIZES)] */
729 728 args->arg0 = (uint32_t)args32.arg0;
730 729 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
731 730 break;
732 731
733 732 case SDBC_SET_CD_HINT:
734 733 args->arg0 = args32.arg0; /* cd */
735 734 args->arg1 = args32.arg1; /* hint */
736 735 args->arg2 = args32.arg2; /* flag */
737 736 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
738 737 break;
739 738
740 739 case SDBC_GET_CD_HINT:
741 740 args->arg0 = args32.arg0;
742 741 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
743 742 break;
744 743
745 744 case SDBC_SET_NODE_HINT:
746 745 args->arg0 = args32.arg0; /* hint */
747 746 args->arg1 = args32.arg1; /* flag */
748 747 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
749 748 break;
750 749
751 750 case SDBC_GET_NODE_HINT:
752 751 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
753 752 break;
754 753
755 754 case SDBC_STATS:
756 755 args->arg0 = (uint32_t)args32.arg0; /* (_sd_stats_t *) */
757 756 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
758 757 break;
759 758
760 759 case SDBC_ZAP_STATS:
761 760 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
762 761 break;
763 762
764 763 case SDBC_GET_CD_BLK:
765 764 args->arg0 = args32.arg0; /* cd */
766 765 args->arg1 = (uint32_t)args32.arg1; /* blk */
767 766 args->arg2 = (uint32_t)args32.arg2; /* (addr[5] *) */
768 767 break;
769 768
770 769 case SDBC_GET_CONFIG:
771 770 args->arg0 = (uint32_t)args32.arg0; /* (_sdbc_config_t *) */
772 771 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
773 772 break;
774 773
775 774 case SDBC_SET_CONFIG:
776 775 args->arg0 = (uint32_t)args32.arg0; /* (_sdbc_config_t *) */
777 776 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
778 777 break;
779 778
780 779 case SDBC_MAXFILES:
781 780 args->arg0 = (uint32_t)args32.arg0; /* (int * ) */
782 781 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
783 782 break;
784 783
785 784 #ifdef DEBUG
786 785 /* toggle flusher flag for testing */
787 786 case SDBC_TOGGLE_FLUSH:
788 787 args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
789 788 break;
790 789
791 790 case SDBC_INJ_IOERR: /* cd, errnum */
792 791 args->arg0 = args32.arg0; /* cd */
793 792 args->arg1 = args32.arg1; /* i/o error number */
794 793 args->arg2 = args32.arg2; /* countdown to issuing error */
795 794 break;
796 795
797 796 /* clear injected i/o errors */
798 797 case SDBC_CLR_IOERR: /* cd */
799 798 args->arg0 = args32.arg0; /* cd */
800 799 break;
801 800 #endif /* DEBUG */
802 801 default:
803 802 return (EINVAL);
804 803 }
805 804
806 805 return (0);
807 806 }
808 807 #endif /* _MULTI_DATAMODEL */
809 808
810 809 static int
811 810 sdbc_get_cd_blk(_sdbc_ioctl_t *args, int mode)
812 811 {
813 812
814 813 _sd_cctl_t *cc_ent;
815 814 caddr_t data;
816 815 char *taddr;
817 816 intptr_t addr[5];
818 817 #ifdef _MULTI_DATAMODEL
819 818 uint32_t addr_32[5];
820 819 #endif /* _MULTI_DATAMODEL */
821 820 char *lookup_file = NULL;
822 821 int rc;
823 822 sdbc_info_t info;
824 823 nsc_off_t fba_pos; /* disk block number */
825 824
826 825 if (_sd_cache_initialized == 0) {
827 826 return (EINVAL);
828 827 }
829 828
830 829 /* copyin the block number */
831 830 if (ddi_copyin((void *)args->arg1, &fba_pos, sizeof (nsc_off_t),
832 831 mode)) {
833 832 return (EFAULT);
834 833 }
835 834
836 835 #ifdef _MULTI_DATAMODEL
837 836 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
838 837 if (ddi_copyin((void *)args->arg2, addr_32, sizeof (addr_32),
839 838 mode)) {
840 839 return (EFAULT);
841 840 }
842 841 addr[0] = addr_32[0]; /* (sdbc_info_t *) */
843 842 addr[1] = addr_32[1]; /* (char *) cdata */
844 843 addr[2] = addr_32[2]; /* ( int * ) cblk_size */
845 844 addr[3] = addr_32[3]; /* ( char * ) filename */
846 845 addr[4] = addr_32[4]; /* ( char *) wdata */
847 846 } else {
848 847 if (ddi_copyin((void *)args->arg2, addr, sizeof (addr), mode)) {
849 848 return (EFAULT);
850 849 }
851 850 }
852 851 #else /* _MULTI_DATAMODEL */
853 852 if (ddi_copyin((void *)args->arg2, addr, sizeof (addr), mode)) {
854 853 return (EFAULT);
855 854 }
856 855 #endif /* _MULTI_DATAMODEL */
857 856
858 857 (void) copyout(&CACHE_BLOCK_SIZE, (void *)addr[2], sizeof (int));
859 858
860 859 if (_sd_get_cd_blk((int)args->arg0, FBA_TO_BLK_NUM(fba_pos),
861 860 &cc_ent, &data, &lookup_file)) {
862 861 if (lookup_file != NULL)
863 862 (void) copyout(lookup_file, (void *)addr[3],
864 863 NSC_MAXPATH);
865 864 return (ENOENT);
866 865 }
867 866 rc = 0;
868 867 taddr = NULL;
869 868
870 869 info.ci_write = cc_ent->cc_write ? 1 : 0;
871 870 info.ci_dirty = cc_ent->cc_dirty;
872 871 info.ci_valid = cc_ent->cc_valid;
873 872 info.ci_cd = CENTRY_CD(cc_ent);
874 873 info.ci_dblk = BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent));
875 874 (void) copyout(lookup_file, (void *)addr[3], NSC_MAXPATH);
876 875 (void) copyout(&info, (void *)addr[0], sizeof (sdbc_info_t));
877 876
878 877 (void) copyout(data, (void *)addr[1], CACHE_BLOCK_SIZE);
879 878
880 879 /* get the write data if any */
881 880 if (cc_ent->cc_write) {
882 881
883 882 if (sdbc_safestore) {
884 883 cmn_err(CE_WARN,
885 884 "!sdbc(sdbc_get_cd_blk) cc_write 0x%p sc-res 0x%p",
886 885 (void *)cc_ent->cc_write,
887 886 (void *)cc_ent->cc_write->sc_res);
888 887
889 888 if ((taddr = kmem_alloc(CACHE_BLOCK_SIZE,
890 889 KM_NOSLEEP)) == NULL) {
891 890 cmn_err(CE_WARN,
892 891 "!sdbc(sdbc_get_cd_blk) kmem_alloc failed."
893 892 " cannot get write data");
894 893 info.ci_write = NULL;
895 894 rc = EFAULT;
896 895 } else if (SSOP_READ_CBLOCK(sdbc_safestore,
897 896 cc_ent->cc_write->sc_res, taddr,
898 897 CACHE_BLOCK_SIZE, 0) == SS_ERR) {
899 898
900 899 cmn_err(CE_WARN, "sdbc(sdbc_get_cd_blk) "
901 900 "!safestore read failed");
902 901 rc = EFAULT;
903 902
904 903 } else if (copyout(taddr, (void *)addr[4],
905 904 CACHE_BLOCK_SIZE)) {
906 905 cmn_err(CE_WARN,
907 906 "!sdbc(sdbc_get_cd_blk) copyout failed."
908 907 " cannot get write data");
909 908 rc = EFAULT;
910 909 }
911 910 }
912 911
913 912 }
914 913
915 914 if (taddr)
916 915 kmem_free(taddr, CACHE_BLOCK_SIZE);
917 916
918 917 return (rc);
919 918 }
920 919
921 920 /* ARGSUSED */
922 921 static int
923 922 sdbcioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *crp, int *rvp)
924 923 {
925 924 int rc = 0;
926 925 _sdbc_ioctl_t args;
927 926 int convert_32 = 0;
928 927 spcs_s_info_t kstatus;
929 928
930 929 *rvp = 0;
931 930
932 931 #ifdef _MULTI_DATAMODEL
933 932 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
934 933 int rc;
935 934 convert_32 = 1;
936 935 if ((rc = convert_ioctl_args(cmd, arg, mode, &args)) != 0)
937 936 return (rc);
938 937 } else {
939 938 if (ddi_copyin(arg, &args, sizeof (_sdbc_ioctl_t), mode)) {
940 939 return (EFAULT);
941 940 }
942 941 }
943 942 #else /* _MULTI_DATAMODEL */
944 943 if (ddi_copyin(arg, &args, sizeof (_sdbc_ioctl_t), mode)) {
945 944 return (EFAULT);
946 945 }
947 946 #endif /* _MULTI_DATAMODEL */
948 947
949 948 kstatus = spcs_s_kcreate();
950 949 if (!kstatus)
951 950 return (ENOMEM);
952 951
953 952 switch (cmd) {
954 953
955 954 case SDBC_UNUSED_1:
956 955 case SDBC_UNUSED_2:
957 956 case SDBC_UNUSED_3:
958 957
959 958 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
960 959 SDBC_EOBSOLETE));
961 960
962 961 case SDBC_ADUMP:
963 962 rc = _sd_adump(&args, rvp);
964 963 break;
965 964
966 965 case SDBC_TEST_INIT:
967 966 rc = _sd_test_init(&args);
968 967 break;
969 968
970 969 case SDBC_TEST_START:
971 970 rc = _sd_test_start(&args, rvp);
972 971 break;
973 972
974 973 case SDBC_TEST_END:
975 974 rc = _sd_test_end();
976 975 break;
977 976
978 977 case SDBC_ENABLE:
979 978 mutex_enter(&_sdbc_config_lock);
980 979 rc = _sdbc_configure((_sd_cache_param_t *)args.arg0,
981 980 NULL, kstatus);
982 981 if (rc && rc != EALREADY && rc != SDBC_ENONETMEM) {
983 982 (void) _sdbc_deconfigure(kstatus);
984 983 mutex_exit(&_sdbc_config_lock);
985 984 return (spcs_s_ocopyoutf
986 985 (&kstatus, args.sdbc_ustatus, rc));
987 986 }
988 987 mutex_exit(&_sdbc_config_lock);
989 988 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
990 989
991 990 case SDBC_DISABLE:
992 991 mutex_enter(&_sdbc_config_lock);
993 992 if (_sd_cache_initialized == 0) {
994 993
995 994 mutex_exit(&_sdbc_config_lock);
996 995 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
997 996 SDBC_EDISABLE));
998 997 }
999 998 rc = _sdbc_deconfigure(kstatus);
1000 999 mutex_exit(&_sdbc_config_lock);
1001 1000 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
1002 1001
1003 1002 case SDBC_GET_CLUSTER_SIZE:
1004 1003 if (_sd_cache_initialized == 0) {
1005 1004
1006 1005 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1007 1006 SDBC_ECLUSTER_SIZE));
1008 1007 }
1009 1008
1010 1009 rc = sd_get_file_info_size((void *)args.arg0);
1011 1010 break;
1012 1011
1013 1012 /* get the gl_file data */
1014 1013 case SDBC_GET_CLUSTER_DATA:
1015 1014 if (_sd_cache_initialized == 0) {
1016 1015
1017 1016 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1018 1017 SDBC_ECLUSTER_DATA));
1019 1018 }
1020 1019 rc = sd_get_file_info_data((void *)args.arg0);
1021 1020 break;
1022 1021
1023 1022 /* get the size of the global info pages for each board */
1024 1023 case SDBC_GET_GLMUL_SIZES:
1025 1024 if (_sd_cache_initialized == 0) {
1026 1025 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1027 1026 SDBC_EGLMUL_SIZE));
1028 1027 }
1029 1028 rc = sd_get_glmul_sizes((void *)args.arg0);
1030 1029 break;
1031 1030
1032 1031 /* get the global info about write blocks */
1033 1032 case SDBC_GET_GLMUL_INFO:
1034 1033 if (_sd_cache_initialized == 0) {
1035 1034
1036 1035 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1037 1036 SDBC_EGLMUL_INFO));
1038 1037
1039 1038 }
1040 1039 rc = sd_get_glmul_info((void *)args.arg0);
1041 1040 break;
1042 1041
1043 1042 case SDBC_SET_CD_HINT:
1044 1043 if (_sd_cache_initialized == 0)
1045 1044 return (spcs_s_ocopyoutf(&kstatus,
1046 1045 args.sdbc_ustatus, EINVAL));
1047 1046 rc = ((args.arg2) ?
1048 1047 _sd_set_hint((int)args.arg0, (uint_t)args.arg1) :
1049 1048 _sd_clear_hint((int)args.arg0, (uint_t)args.arg1));
1050 1049 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
1051 1050
1052 1051 case SDBC_GET_CD_HINT:
1053 1052 {
1054 1053 uint_t hint;
1055 1054
1056 1055 if (_sd_cache_initialized == 0)
1057 1056 return (spcs_s_ocopyoutf(&kstatus,
1058 1057 args.sdbc_ustatus, EINVAL));
1059 1058 if ((rc = _sd_get_cd_hint((int)args.arg0, &hint)) == 0)
1060 1059 *rvp = hint;
1061 1060 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1062 1061 rc));
1063 1062 }
1064 1063
1065 1064 case SDBC_SET_NODE_HINT:
1066 1065 rc = ((args.arg1) ? _sd_set_node_hint((uint_t)args.arg0) :
1067 1066 _sd_clear_node_hint((uint_t)args.arg0));
1068 1067 if (rc)
1069 1068 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1070 1069 rc));
1071 1070 /* FALLTHRU */
1072 1071 case SDBC_GET_NODE_HINT:
1073 1072 {
1074 1073 uint_t hint;
1075 1074 if ((rc = _sd_get_node_hint(&hint)) == 0)
1076 1075 *rvp = hint;
1077 1076 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1078 1077 rc));
1079 1078 }
1080 1079
1081 1080 case SDBC_STATS:
1082 1081 rc = _sd_get_stats((void *)args.arg0, convert_32);
1083 1082 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
1084 1083
1085 1084 case SDBC_ZAP_STATS:
1086 1085 _sd_zap_stats();
1087 1086 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, 0));
1088 1087
1089 1088 case SDBC_GET_CD_BLK:
1090 1089 if (_sd_cache_initialized == 0)
1091 1090 return (spcs_s_ocopyoutf(&kstatus,
1092 1091 args.sdbc_ustatus, EINVAL));
1093 1092 rc = sdbc_get_cd_blk(&args, mode);
1094 1093 break;
1095 1094
1096 1095 case SDBC_GET_CONFIG:
1097 1096 {
1098 1097 _sdbc_config_t sdbc_config_info;
1099 1098
1100 1099 if (ddi_copyin((void *)args.arg0,
1101 1100 &sdbc_config_info,
1102 1101 sizeof (_sdbc_config_t),
1103 1102 mode)) {
1104 1103 spcs_s_kfree(kstatus);
1105 1104 return (EFAULT);
1106 1105 }
1107 1106 rc = _sdbc_get_config(&sdbc_config_info);
1108 1107 (void) ddi_copyout(&sdbc_config_info,
1109 1108 (void *)args.arg0,
1110 1109 sizeof (_sdbc_config_t),
1111 1110 mode);
1112 1111 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
1113 1112 }
1114 1113
1115 1114 case SDBC_SET_CONFIG:
1116 1115 {
1117 1116 _sdbc_config_t mgmt_config_info;
1118 1117
1119 1118 if (ddi_copyin((void *)args.arg0,
1120 1119 &mgmt_config_info,
1121 1120 sizeof (_sdbc_config_t),
1122 1121 mode)) {
1123 1122 spcs_s_kfree(kstatus);
1124 1123 return (EFAULT);
1125 1124 }
1126 1125
1127 1126 rc = _sdbc_configure(NULL, &mgmt_config_info, kstatus);
1128 1127 if (rc && rc != EALREADY) {
1129 1128 (void) _sdbc_deconfigure(kstatus);
1130 1129 return (spcs_s_ocopyoutf
1131 1130 (&kstatus, args.sdbc_ustatus, rc));
1132 1131 }
1133 1132
1134 1133 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
1135 1134 }
1136 1135
1137 1136 case SDBC_MAXFILES:
1138 1137 if (copyout(&sdbc_max_devs, (void *)args.arg0,
1139 1138 sizeof (sdbc_max_devs)))
1140 1139 rc = EFAULT;
1141 1140 else
1142 1141 rc = 0;
1143 1142
1144 1143 break;
1145 1144
1146 1145 case SDBC_VERSION:
1147 1146 {
1148 1147 cache_version_t cache_version;
1149 1148
1150 1149 cache_version.major = sdbc_major_rev;
1151 1150 cache_version.minor = sdbc_minor_rev;
1152 1151 cache_version.micro = sdbc_micro_rev;
1153 1152 cache_version.baseline = sdbc_baseline_rev;
1154 1153
1155 1154 if (ddi_copyout(&cache_version, (void *)args.arg0,
1156 1155 sizeof (cache_version_t), mode)) {
1157 1156 rc = EFAULT;
1158 1157 break;
1159 1158 }
1160 1159
1161 1160 break;
1162 1161 }
1163 1162
1164 1163
1165 1164 #ifdef DEBUG
1166 1165 /* toggle flusher flag for testing */
1167 1166 case SDBC_TOGGLE_FLUSH:
1168 1167 _sdbc_flush_flag ^= 1;
1169 1168 *rvp = _sdbc_flush_flag;
1170 1169 rc = 0;
1171 1170
1172 1171 return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
1173 1172 SDBC_ETOGGLE_FLUSH, _sdbc_flush_flag ? "on" : "off"));
1174 1173
1175 1174
1176 1175 /* inject i/o errors */
1177 1176 case SDBC_INJ_IOERR: /* cd, errnum */
1178 1177 if (_sd_cache_initialized == 0)
1179 1178 return (spcs_s_ocopyoutf(&kstatus,
1180 1179 args.sdbc_ustatus, EINVAL));
1181 1180 rc = _sdbc_inject_ioerr(args.arg0, args.arg1, args.arg2);
1182 1181 break;
1183 1182
1184 1183 /* clear injected i/o errors */
1185 1184 case SDBC_CLR_IOERR: /* cd */
1186 1185 if (_sd_cache_initialized == 0)
1187 1186 return (spcs_s_ocopyoutf(&kstatus,
1188 1187 args.sdbc_ustatus, EINVAL));
1189 1188 rc = _sdbc_clear_ioerr(args.arg0);
1190 1189 break;
1191 1190
1192 1191 #endif /* DEBUG */
1193 1192 default:
1194 1193 _sd_print(3, "!SDBC unknown ioctl: 0x%x unsupported", cmd);
1195 1194 rc = EINVAL;
1196 1195 break;
1197 1196 }
1198 1197
1199 1198 spcs_s_kfree(kstatus);
1200 1199 return (rc);
1201 1200 }
1202 1201
1203 1202
1204 1203 /*
1205 1204 * _sd_timed_block - sleep waiting for ticks time delay.
1206 1205 * ticks - # of ticks to sleep
1207 1206 * cvp - pointer to the cv we wait on while we delay.
1208 1207 *
1209 1208 * NO spin locks can be held at entry!
1210 1209 *
1211 1210 */
1212 1211 void
1213 1212 _sd_timed_block(clock_t ticks, kcondvar_t *cvp)
1214 1213 {
1215 1214 mutex_enter(&_sd_block_lk);
1216 1215 (void) cv_reltimedwait(cvp, &_sd_block_lk, ticks, TR_CLOCK_TICK);
1217 1216 mutex_exit(&_sd_block_lk);
1218 1217 }
1219 1218
1220 1219
1221 1220 /*
1222 1221 * _sd_unblock - awake a sleeper waiting on cv pointed to by cvp.
1223 1222 *
1224 1223 * NO spin locks can be held at entry as we may sleep.
1225 1224 *
1226 1225 */
1227 1226 void
1228 1227 _sd_unblock(kcondvar_t *cvp)
1229 1228 {
1230 1229
1231 1230 mutex_enter(&_sd_block_lk);
1232 1231 cv_broadcast(cvp);
1233 1232 mutex_exit(&_sd_block_lk);
1234 1233 }
1235 1234
1236 1235 /* ARGSUSED */
1237 1236 void
1238 1237 _sd_data_log(int num, _sd_cctl_t *centry, nsc_off_t st, nsc_size_t len)
1239 1238 {
1240 1239 #if defined(_SD_FBA_DATA_LOG)
1241 1240 nsc_size_t i;
1242 1241 nsc_off_t blk;
1243 1242
1244 1243 blk = BLK_TO_FBA_NUM(CENTRY_BLK(centry));
1245 1244 for (i = st; i < (st + len); i++)
1246 1245 SDTRACE(num, CENTRY_CD(centry), 1, blk + i,
1247 1246 *(int *)(centry->cc_data + FBA_SIZE(i)),
1248 1247 *(int *)(centry->cc_data + FBA_SIZE(i) + 4));
1249 1248 #endif /* _SD_FBA_DATA_LOG */
1250 1249 }
1251 1250
1252 1251 /* ARGSUSED */
1253 1252 void
1254 1253 _sd_data_log_chain(int num, _sd_cctl_t *centry, nsc_off_t fba_pos,
1255 1254 nsc_size_t fba_len)
1256 1255 {
1257 1256 #if defined(_SD_FBA_DATA_LOG)
1258 1257 sdbc_cblk_fba_t st_cblk_len; /* FBA len of starting cache block */
1259 1258 sdbc_cblk_fba_t end_cblk_len; /* FBA len of ending cache block */
1260 1259 sdbc_cblk_fba_t st_cblk_off; /* FBA offset into starting cblock */
1261 1260
1262 1261 while (CENTRY_BLK(centry) != FBA_TO_BLK_NUM(fba_pos))
1263 1262 centry = centry->cc_chain;
1264 1263
1265 1264 st_cblk_off = BLK_FBA_OFF(fba_pos);
1266 1265 st_cblk_len = BLK_FBAS - st_cblk_off;
1267 1266 if (st_cblk_len >= fba_len) {
1268 1267 end_cblk_len = 0;
1269 1268 st_cblk_len = fba_len;
1270 1269 } else {
1271 1270 end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
1272 1271 }
1273 1272
1274 1273 DATA_LOG(num, centry, st_cblk_off, st_cblk_len);
1275 1274
1276 1275 fba_len -= st_cblk_len;
1277 1276 centry = centry->cc_chain;
1278 1277
1279 1278 while (fba_len > end_cblk_len) {
1280 1279 DATA_LOG(num, centry, 0, BLK_FBAS);
1281 1280 fba_len -= BLK_FBAS;
1282 1281 centry = centry->cc_chain;
1283 1282 }
1284 1283 if (end_cblk_len) DATA_LOG(num, centry, 0, end_cblk_len);
1285 1284 #endif /* _SD_FBA_DATA_LOG */
1286 1285 }
1287 1286
1288 1287
1289 1288 void
1290 1289 _sd_zap_stats(void)
1291 1290 {
1292 1291 int i;
1293 1292
1294 1293 if (_sd_cache_stats == NULL)
1295 1294 return;
1296 1295
1297 1296 _sd_cache_stats->st_rdhits = 0;
1298 1297 _sd_cache_stats->st_rdmiss = 0;
1299 1298 _sd_cache_stats->st_wrhits = 0;
1300 1299 _sd_cache_stats->st_wrmiss = 0;
1301 1300 _sd_lru_q.sq_noreq_stat = 0;
1302 1301 _sd_lru_q.sq_req_stat = 0;
1303 1302
1304 1303 for (i = 0; i < sdbc_max_devs; i++) {
1305 1304 _sd_cache_stats->st_shared[i].sh_cache_read = 0;
1306 1305 _sd_cache_stats->st_shared[i].sh_cache_write = 0;
1307 1306 _sd_cache_stats->st_shared[i].sh_disk_read = 0;
1308 1307 _sd_cache_stats->st_shared[i].sh_disk_write = 0;
1309 1308 }
1310 1309 }
1311 1310
1312 1311
1313 1312 /*
1314 1313 * Return the cache sizes used by the Sense Subsystem Status CCW
1315 1314 */
1316 1315 int
1317 1316 _sd_cache_sizes(int *asize, int *wsize)
1318 1317 {
1319 1318 int psize;
1320 1319
1321 1320 *asize = 0;
1322 1321 *wsize = 0;
1323 1322
1324 1323 /*
1325 1324 * add in the total cache size and the
1326 1325 * non-volatile (battery-backed) cache size.
1327 1326 */
1328 1327 if (_sd_net_config.sn_configured) {
1329 1328 psize = _sd_net_config.sn_psize;
1330 1329 *asize += (_sd_net_config.sn_cpages * psize);
1331 1330 *wsize += (safestore_config.ssc_wsize);
1332 1331 }
1333 1332
1334 1333 return (0);
1335 1334 }
1336 1335
1337 1336
1338 1337 /*PRINTFLIKE2*/
1339 1338 void
1340 1339 _sd_print(int level, char *fmt, ...)
1341 1340 {
1342 1341 va_list adx;
1343 1342 if (level <= _sd_debug_level) {
1344 1343 va_start(adx, fmt);
1345 1344 vcmn_err(CE_NOTE, fmt, adx);
1346 1345 va_end(adx);
1347 1346
1348 1347 }
1349 1348 }
1350 1349
1351 1350
1352 1351 int
1353 1352 _sd_get_cd_blk(int cd, nsc_off_t cblk, _sd_cctl_t **cc, caddr_t *data,
1354 1353 char **filename)
1355 1354 {
1356 1355 _sd_cctl_t *cc_ent;
1357 1356
1358 1357 if (FILE_OPENED(cd) != 0) {
1359 1358 *filename = _sd_cache_files[cd].cd_info->sh_filename;
1360 1359 if (cc_ent = (_sd_cctl_t *)
1361 1360 _sd_hash_search(cd, cblk, _sd_htable)) {
1362 1361 *cc = cc_ent;
1363 1362 *data = (caddr_t)cc_ent->cc_data;
1364 1363 return (0);
1365 1364 }
1366 1365 }
1367 1366 return (-1);
1368 1367 }
1369 1368
1370 1369 /*
1371 1370 * central dyn mem processing vars edit rtn.
1372 1371 * input a local copy and xfer to global
1373 1372 *
1374 1373 * sec0,sec1,sec2
1375 1374 * range check 1 to 255 (arbitrary but in any case must be <= 2000 due to
1376 1375 * 32bit signed int limits in later calc)
1377 1376 * aging_ct
1378 1377 * range check 1 to 255 (only 8 bits reserved for aging ctr)
1379 1378 *
1380 1379 */
1381 1380 int
1382 1381 sdbc_edit_xfer_process_vars_dm(_dm_process_vars_t *process_vars)
1383 1382 {
1384 1383 if (process_vars->max_dyn_list > 0)
1385 1384 dynmem_processing_dm.max_dyn_list = process_vars->max_dyn_list;
1386 1385
1387 1386 /* no edit on monitor_dynmem_process */
1388 1387 dynmem_processing_dm.monitor_dynmem_process =
1389 1388 process_vars->monitor_dynmem_process;
1390 1389 /* no edit on process_directive */
1391 1390 dynmem_processing_dm.process_directive =
1392 1391 process_vars->process_directive;
1393 1392
1394 1393 if (process_vars->cache_aging_ct1 > 0 &&
1395 1394 process_vars->cache_aging_ct1 <= CACHE_AGING_CT_MAX)
1396 1395 dynmem_processing_dm.cache_aging_ct1 =
1397 1396 process_vars->cache_aging_ct1;
1398 1397 if (process_vars->cache_aging_ct2 > 0 &&
1399 1398 process_vars->cache_aging_ct2 <= CACHE_AGING_CT_MAX)
1400 1399 dynmem_processing_dm.cache_aging_ct2 =
1401 1400 process_vars->cache_aging_ct2;
1402 1401 if (process_vars->cache_aging_ct3 > 0 &&
1403 1402 process_vars->cache_aging_ct3 <= CACHE_AGING_CT_MAX)
1404 1403 dynmem_processing_dm.cache_aging_ct3 =
1405 1404 process_vars->cache_aging_ct3;
1406 1405 if (process_vars->cache_aging_sec1 > 0 &&
1407 1406 process_vars->cache_aging_sec1 <= CACHE_AGING_SEC1_MAX)
1408 1407 dynmem_processing_dm.cache_aging_sec1 =
1409 1408 process_vars->cache_aging_sec1;
1410 1409 if (process_vars->cache_aging_sec2 > 0 &&
1411 1410 process_vars->cache_aging_sec2 <= CACHE_AGING_SEC2_MAX)
1412 1411 dynmem_processing_dm.cache_aging_sec2 =
1413 1412 process_vars->cache_aging_sec2;
1414 1413 if (process_vars->cache_aging_sec3 > 0 &&
1415 1414 process_vars->cache_aging_sec3 <= CACHE_AGING_SEC3_MAX)
1416 1415 dynmem_processing_dm.cache_aging_sec3 =
1417 1416 process_vars->cache_aging_sec3;
1418 1417 if (process_vars->cache_aging_pcnt1 >= 0 &&
1419 1418 process_vars->cache_aging_pcnt1 <= CACHE_AGING_PCNT1_MAX)
1420 1419 dynmem_processing_dm.cache_aging_pcnt1 =
1421 1420 process_vars->cache_aging_pcnt1;
1422 1421 if (process_vars->cache_aging_pcnt2 >= 0 &&
1423 1422 process_vars->cache_aging_pcnt2 <= CACHE_AGING_PCNT2_MAX)
1424 1423 dynmem_processing_dm.cache_aging_pcnt2 =
1425 1424 process_vars->cache_aging_pcnt2;
1426 1425 if (process_vars->max_holds_pcnt >= 0 &&
1427 1426 process_vars->max_holds_pcnt <= MAX_HOLDS_PCNT_MAX)
1428 1427 dynmem_processing_dm.max_holds_pcnt =
1429 1428 process_vars->max_holds_pcnt;
1430 1429 return (0);
1431 1430 }
1432 1431
1433 1432 dev_info_t *
1434 1433 sdbc_get_dip()
1435 1434 {
1436 1435 return (dev_dip);
1437 1436 }
↓ open down ↓ |
1271 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX