1 3786 arutz /* 2 3786 arutz * CDDL HEADER START 3 3786 arutz * 4 3786 arutz * The contents of this file are subject to the terms of the 5 3786 arutz * Common Development and Distribution License (the "License"). 6 3786 arutz * You may not use this file except in compliance with the License. 7 3786 arutz * 8 3786 arutz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 3786 arutz * or http://www.opensolaris.org/os/licensing. 10 3786 arutz * See the License for the specific language governing permissions 11 3786 arutz * and limitations under the License. 12 3786 arutz * 13 3786 arutz * When distributing Covered Code, include this CDDL HEADER in each 14 3786 arutz * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 3786 arutz * If applicable, add the following below this CDDL HEADER, with the 16 3786 arutz * fields enclosed by brackets "[]" replaced with your own identifying 17 3786 arutz * information: Portions Copyright [yyyy] [name of copyright owner] 18 3786 arutz * 19 3786 arutz * CDDL HEADER END 20 3786 arutz */ 21 3786 arutz 22 3786 arutz /* 23 8863 Edward * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 3786 arutz * Use is subject to license terms. 25 3786 arutz */ 26 3786 arutz 27 3786 arutz 28 3786 arutz /* 29 3786 arutz * Direct Attached disk driver for SPARC machines. 30 3786 arutz */ 31 3786 arutz 32 3786 arutz /* 33 3786 arutz * Includes, Declarations and Local Data 34 3786 arutz */ 35 3786 arutz #include <sys/dada/dada.h> 36 3786 arutz #include <sys/dkbad.h> 37 3786 arutz #include <sys/dklabel.h> 38 3786 arutz #include <sys/dkio.h> 39 3786 arutz #include <sys/cdio.h> 40 3786 arutz #include <sys/vtoc.h> 41 3786 arutz #include <sys/dada/targets/daddef.h> 42 3786 arutz #include <sys/dada/targets/dadpriv.h> 43 3786 arutz #include <sys/file.h> 44 3786 arutz #include <sys/stat.h> 45 3786 arutz #include <sys/kstat.h> 46 3786 arutz #include <sys/vtrace.h> 47 3786 arutz #include <sys/aio_req.h> 48 3786 arutz #include <sys/note.h> 49 3786 arutz #include <sys/cmlb.h> 50 3786 arutz 51 3786 arutz /* 52 3786 arutz * Global Error Levels for Error Reporting 53 3786 arutz */ 54 3786 arutz int dcd_error_level = DCD_ERR_RETRYABLE; 55 3786 arutz /* 56 3786 arutz * Local Static Data 57 3786 arutz */ 58 3786 arutz 59 3786 arutz static int dcd_io_time = DCD_IO_TIME; 60 3786 arutz static int dcd_retry_count = DCD_RETRY_COUNT; 61 3786 arutz #ifndef lint 62 3786 arutz static int dcd_report_pfa = 1; 63 3786 arutz #endif 64 3786 arutz static int dcd_rot_delay = 4; 65 3786 arutz static int dcd_poll_busycnt = DCD_POLL_TIMEOUT; 66 3786 arutz 67 3786 arutz /* 68 3786 arutz * Local Function Prototypes 69 3786 arutz */ 70 3786 arutz 71 3786 arutz static int dcdopen(dev_t *dev_p, int flag, int otyp, cred_t *cred_p); 72 3786 arutz static int dcdclose(dev_t dev, int flag, int otyp, cred_t *cred_p); 73 3786 arutz static int dcdstrategy(struct buf *bp); 74 3786 arutz static int dcddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk); 75 3786 arutz static int dcdioctl(dev_t, int, intptr_t, int, cred_t *, int *); 76 3786 arutz static int dcdread(dev_t dev, struct uio *uio, cred_t *cred_p); 77 3786 arutz static int dcdwrite(dev_t dev, struct uio *uio, cred_t *cred_p); 78 3786 arutz static int dcd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, 79 3786 arutz char *, caddr_t, int *); 80 3786 arutz static int dcdaread(dev_t dev, struct aio_req *aio, cred_t *cred_p); 81 3786 arutz static int dcdawrite(dev_t dev, struct aio_req *aio, cred_t *cred_p); 82 3786 arutz 83 3786 arutz 84 3786 arutz static void dcd_free_softstate(struct dcd_disk *un, dev_info_t *devi); 85 3786 arutz static int dcd_doattach(dev_info_t *devi, int (*f)()); 86 3786 arutz static int dcd_validate_geometry(struct dcd_disk *un); 87 3786 arutz static ddi_devid_t dcd_get_devid(struct dcd_disk *un); 88 3786 arutz static ddi_devid_t dcd_create_devid(struct dcd_disk *un); 89 3786 arutz static int dcd_make_devid_from_serial(struct dcd_disk *un); 90 3786 arutz static void dcd_validate_model_serial(char *str, int *retlen, int totallen); 91 3786 arutz static int dcd_read_deviceid(struct dcd_disk *un); 92 3786 arutz static int dcd_write_deviceid(struct dcd_disk *un); 93 3786 arutz static int dcd_poll(struct dcd_pkt *pkt); 94 3786 arutz static char *dcd_rname(int reason); 95 3786 arutz static void dcd_flush_cache(struct dcd_disk *un); 96 3786 arutz 97 3786 arutz static int dcd_compute_dk_capacity(struct dcd_device *devp, 98 3786 arutz diskaddr_t *capacity); 99 3786 arutz static int dcd_send_lb_rw_cmd(dev_info_t *devinfo, void *bufaddr, 100 3786 arutz diskaddr_t start_block, size_t reqlength, uchar_t cmd); 101 3786 arutz 102 3786 arutz static void dcdmin(struct buf *bp); 103 3786 arutz 104 3786 arutz static int dcdioctl_cmd(dev_t, struct udcd_cmd *, 105 3786 arutz enum uio_seg, enum uio_seg); 106 3786 arutz 107 3786 arutz static void dcdstart(struct dcd_disk *un); 108 3786 arutz static void dcddone_and_mutex_exit(struct dcd_disk *un, struct buf *bp); 109 3786 arutz static void make_dcd_cmd(struct dcd_disk *un, struct buf *bp, int (*f)()); 110 3786 arutz static void dcdudcdmin(struct buf *bp); 111 3786 arutz 112 3786 arutz static int dcdrunout(caddr_t); 113 3786 arutz static int dcd_check_wp(dev_t dev); 114 3786 arutz static int dcd_unit_ready(dev_t dev); 115 3786 arutz static void dcd_handle_tran_busy(struct buf *bp, struct diskhd *dp, 116 3786 arutz struct dcd_disk *un); 117 3786 arutz static void dcdintr(struct dcd_pkt *pkt); 118 3786 arutz static int dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp); 119 3786 arutz static void dcd_offline(struct dcd_disk *un, int bechatty); 120 3786 arutz static int dcd_ready_and_valid(dev_t dev, struct dcd_disk *un); 121 3786 arutz static void dcd_reset_disk(struct dcd_disk *un, struct dcd_pkt *pkt); 122 3786 arutz static void dcd_translate(struct dadkio_status32 *statp, struct udcd_cmd *cmdp); 123 3786 arutz static int dcdflushdone(struct buf *bp); 124 3786 arutz 125 3786 arutz /* Function prototypes for cmlb */ 126 3786 arutz 127 3786 arutz static int dcd_lb_rdwr(dev_info_t *devi, uchar_t cmd, void *bufaddr, 128 3786 arutz diskaddr_t start_block, size_t reqlength, void *tg_cookie); 129 3786 arutz 130 3786 arutz static int dcd_lb_getphygeom(dev_info_t *devi, cmlb_geom_t *phygeomp); 131 3786 arutz static int dcd_lb_getinfo(dev_info_t *devi, int cmd, void *arg, 132 3786 arutz void *tg_cookie); 133 3786 arutz 134 3786 arutz 135 3786 arutz static cmlb_tg_ops_t dcd_lb_ops = { 136 3786 arutz TG_DK_OPS_VERSION_1, 137 3786 arutz dcd_lb_rdwr, 138 3786 arutz dcd_lb_getinfo 139 3786 arutz }; 140 3786 arutz 141 3786 arutz /* 142 3786 arutz * Error and Logging Functions 143 3786 arutz */ 144 3786 arutz #ifndef lint 145 3786 arutz static void clean_print(dev_info_t *dev, char *label, uint_t level, 146 3786 arutz char *title, char *data, int len); 147 3786 arutz static void dcdrestart(void *arg); 148 3786 arutz #endif /* lint */ 149 3786 arutz 150 3786 arutz static int dcd_check_error(struct dcd_disk *un, struct buf *bp); 151 3786 arutz 152 3786 arutz /* 153 3786 arutz * Error statistics create/update functions 154 3786 arutz */ 155 3786 arutz static int dcd_create_errstats(struct dcd_disk *, int); 156 3786 arutz 157 3786 arutz 158 3786 arutz 159 3786 arutz /*PRINTFLIKE4*/ 160 3786 arutz extern void dcd_log(dev_info_t *, char *, uint_t, const char *, ...) 161 3786 arutz __KPRINTFLIKE(4); 162 3786 arutz extern void makecommand(struct dcd_pkt *, int, uchar_t, uint32_t, 163 3786 arutz uchar_t, uint32_t, uchar_t, uchar_t); 164 3786 arutz 165 3786 arutz 166 3786 arutz /* 167 3786 arutz * Configuration Routines 168 3786 arutz */ 169 3786 arutz static int dcdinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 170 3786 arutz void **result); 171 3786 arutz static int dcdprobe(dev_info_t *devi); 172 3786 arutz static int dcdattach(dev_info_t *devi, ddi_attach_cmd_t cmd); 173 3786 arutz static int dcddetach(dev_info_t *devi, ddi_detach_cmd_t cmd); 174 3786 arutz static int dcdreset(dev_info_t *dip, ddi_reset_cmd_t cmd); 175 3786 arutz static int dcd_dr_detach(dev_info_t *devi); 176 3786 arutz static int dcdpower(dev_info_t *devi, int component, int level); 177 3786 arutz 178 3786 arutz static void *dcd_state; 179 3786 arutz static int dcd_max_instance; 180 3786 arutz static char *dcd_label = "dad"; 181 3786 arutz 182 3786 arutz static char *diskokay = "disk okay\n"; 183 3786 arutz 184 3786 arutz #if DEBUG || lint 185 3786 arutz #define DCDDEBUG 186 3786 arutz #endif 187 3786 arutz 188 3786 arutz int dcd_test_flag = 0; 189 3786 arutz /* 190 3786 arutz * Debugging macros 191 3786 arutz */ 192 3786 arutz #ifdef DCDDEBUG 193 3786 arutz static int dcddebug = 0; 194 3786 arutz #define DEBUGGING (dcddebug > 1) 195 3786 arutz #define DAD_DEBUG if (dcddebug == 1) dcd_log 196 3786 arutz #define DAD_DEBUG2 if (dcddebug > 1) dcd_log 197 3786 arutz #else /* DCDDEBUG */ 198 3786 arutz #define dcddebug (0) 199 3786 arutz #define DEBUGGING (0) 200 3786 arutz #define DAD_DEBUG if (0) dcd_log 201 3786 arutz #define DAD_DEBUG2 if (0) dcd_log 202 3786 arutz #endif 203 3786 arutz 204 3786 arutz /* 205 3786 arutz * we use pkt_private area for storing bp and retry_count 206 3786 arutz * XXX: Really is this usefull. 207 3786 arutz */ 208 3786 arutz struct dcd_pkt_private { 209 3786 arutz struct buf *dcdpp_bp; 210 3786 arutz short dcdpp_retry_count; 211 3786 arutz short dcdpp_victim_retry_count; 212 3786 arutz }; 213 3786 arutz 214 3786 arutz 215 3786 arutz _NOTE(SCHEME_PROTECTS_DATA("Unique per pkt", dcd_pkt_private buf)) 216 3786 arutz 217 3786 arutz #define PP_LEN (sizeof (struct dcd_pkt_private)) 218 3786 arutz 219 3786 arutz #define PKT_SET_BP(pkt, bp) \ 220 3786 arutz ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_bp = bp 221 3786 arutz #define PKT_GET_BP(pkt) \ 222 3786 arutz (((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_bp) 223 3786 arutz 224 3786 arutz 225 3786 arutz #define PKT_SET_RETRY_CNT(pkt, n) \ 226 3786 arutz ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count = n 227 3786 arutz 228 3786 arutz #define PKT_GET_RETRY_CNT(pkt) \ 229 3786 arutz (((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count) 230 3786 arutz 231 3786 arutz #define PKT_INCR_RETRY_CNT(pkt, n) \ 232 3786 arutz ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_retry_count += n 233 3786 arutz 234 3786 arutz #define PKT_SET_VICTIM_RETRY_CNT(pkt, n) \ 235 3786 arutz ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count \ 236 3786 arutz = n 237 3786 arutz 238 3786 arutz #define PKT_GET_VICTIM_RETRY_CNT(pkt) \ 239 3786 arutz (((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count) 240 3786 arutz #define PKT_INCR_VICTIM_RETRY_CNT(pkt, n) \ 241 3786 arutz ((struct dcd_pkt_private *)pkt->pkt_private)->dcdpp_victim_retry_count \ 242 3786 arutz += n 243 3786 arutz 244 3786 arutz #define DISK_NOT_READY_RETRY_COUNT (dcd_retry_count / 2) 245 3786 arutz 246 3786 arutz 247 3786 arutz /* 248 3786 arutz * Urk! 249 3786 arutz */ 250 3786 arutz #define SET_BP_ERROR(bp, err) \ 251 3786 arutz bioerror(bp, err); 252 3786 arutz 253 3786 arutz #define IOSP KSTAT_IO_PTR(un->un_stats) 254 3786 arutz #define IO_PARTITION_STATS un->un_pstats[DCDPART(bp->b_edev)] 255 3786 arutz #define IOSP_PARTITION KSTAT_IO_PTR(IO_PARTITION_STATS) 256 3786 arutz 257 3786 arutz #define DCD_DO_KSTATS(un, kstat_function, bp) \ 258 3786 arutz ASSERT(mutex_owned(DCD_MUTEX)); \ 259 3786 arutz if (bp != un->un_sbufp) { \ 260 3786 arutz if (un->un_stats) { \ 261 3786 arutz kstat_function(IOSP); \ 262 3786 arutz } \ 263 3786 arutz if (IO_PARTITION_STATS) { \ 264 3786 arutz kstat_function(IOSP_PARTITION); \ 265 3786 arutz } \ 266 3786 arutz } 267 3786 arutz 268 3786 arutz #define DCD_DO_ERRSTATS(un, x) \ 269 3786 arutz if (un->un_errstats) { \ 270 3786 arutz struct dcd_errstats *dtp; \ 271 3786 arutz dtp = (struct dcd_errstats *)un->un_errstats->ks_data; \ 272 3786 arutz dtp->x.value.ui32++; \ 273 3786 arutz } 274 3786 arutz 275 3786 arutz #define GET_SOFT_STATE(dev) \ 276 3786 arutz struct dcd_disk *un; \ 277 3786 arutz int instance, part; \ 278 3786 arutz minor_t minor = getminor(dev); \ 279 3786 arutz \ 280 3786 arutz part = minor & DCDPART_MASK; \ 281 3786 arutz instance = minor >> DCDUNIT_SHIFT; \ 282 3786 arutz if ((un = ddi_get_soft_state(dcd_state, instance)) == NULL) \ 283 3786 arutz return (ENXIO); 284 3786 arutz 285 3786 arutz #define LOGICAL_BLOCK_ALIGN(blkno, blknoshift) \ 286 3786 arutz (((blkno) & ((1 << (blknoshift)) - 1)) == 0) 287 3786 arutz 288 3786 arutz /* 289 3786 arutz * After the following number of sectors, the cylinder number spills over 290 3786 arutz * 0xFFFF if sectors = 63 and heads = 16. 291 3786 arutz */ 292 3786 arutz #define NUM_SECTORS_32G 0x3EFFC10 293 3786 arutz 294 3786 arutz /* 295 3786 arutz * Configuration Data 296 3786 arutz */ 297 3786 arutz 298 3786 arutz /* 299 3786 arutz * Device driver ops vector 300 3786 arutz */ 301 3786 arutz 302 3786 arutz static struct cb_ops dcd_cb_ops = { 303 3786 arutz dcdopen, /* open */ 304 3786 arutz dcdclose, /* close */ 305 3786 arutz dcdstrategy, /* strategy */ 306 3786 arutz nodev, /* print */ 307 3786 arutz dcddump, /* dump */ 308 3786 arutz dcdread, /* read */ 309 3786 arutz dcdwrite, /* write */ 310 3786 arutz dcdioctl, /* ioctl */ 311 3786 arutz nodev, /* devmap */ 312 3786 arutz nodev, /* mmap */ 313 3786 arutz nodev, /* segmap */ 314 3786 arutz nochpoll, /* poll */ 315 3786 arutz dcd_prop_op, /* cb_prop_op */ 316 3786 arutz 0, /* streamtab */ 317 3786 arutz D_64BIT | D_MP | D_NEW, /* Driver compatibility flag */ 318 3786 arutz CB_REV, /* cb_rev */ 319 3786 arutz dcdaread, /* async I/O read entry point */ 320 3786 arutz dcdawrite /* async I/O write entry point */ 321 3786 arutz }; 322 3786 arutz 323 3786 arutz static struct dev_ops dcd_ops = { 324 3786 arutz DEVO_REV, /* devo_rev, */ 325 3786 arutz 0, /* refcnt */ 326 3786 arutz dcdinfo, /* info */ 327 3786 arutz nulldev, /* identify */ 328 3786 arutz dcdprobe, /* probe */ 329 3786 arutz dcdattach, /* attach */ 330 3786 arutz dcddetach, /* detach */ 331 3786 arutz dcdreset, /* reset */ 332 3786 arutz &dcd_cb_ops, /* driver operations */ 333 3786 arutz (struct bus_ops *)0, /* bus operations */ 334 7656 Sherry dcdpower, /* power */ 335 7656 Sherry ddi_quiesce_not_supported, /* devo_quiesce */ 336 3786 arutz }; 337 3786 arutz 338 3786 arutz 339 3786 arutz /* 340 3786 arutz * This is the loadable module wrapper. 341 3786 arutz */ 342 3786 arutz #include <sys/modctl.h> 343 3786 arutz 344 3786 arutz static struct modldrv modldrv = { 345 3786 arutz &mod_driverops, /* Type of module. This one is a driver */ 346 7656 Sherry "DAD Disk Driver", /* Name of the module. */ 347 3786 arutz &dcd_ops, /* driver ops */ 348 3786 arutz }; 349 3786 arutz 350 3786 arutz 351 3786 arutz 352 3786 arutz static struct modlinkage modlinkage = { 353 3786 arutz MODREV_1, &modldrv, NULL 354 3786 arutz }; 355 3786 arutz 356 3786 arutz /* 357 3786 arutz * the dcd_attach_mutex only protects dcd_max_instance in multi-threaded 358 3786 arutz * attach situations 359 3786 arutz */ 360 3786 arutz static kmutex_t dcd_attach_mutex; 361 3786 arutz 362 3786 arutz int 363 3786 arutz _init(void) 364 3786 arutz { 365 3786 arutz int e; 366 3786 arutz 367 3786 arutz if ((e = ddi_soft_state_init(&dcd_state, sizeof (struct dcd_disk), 368 3786 arutz DCD_MAXUNIT)) != 0) 369 3786 arutz return (e); 370 3786 arutz 371 3786 arutz mutex_init(&dcd_attach_mutex, NULL, MUTEX_DRIVER, NULL); 372 3786 arutz e = mod_install(&modlinkage); 373 3786 arutz if (e != 0) { 374 3786 arutz mutex_destroy(&dcd_attach_mutex); 375 3786 arutz ddi_soft_state_fini(&dcd_state); 376 3786 arutz return (e); 377 3786 arutz } 378 3786 arutz 379 3786 arutz return (e); 380 3786 arutz } 381 3786 arutz 382 3786 arutz int 383 3786 arutz _fini(void) 384 3786 arutz { 385 3786 arutz int e; 386 3786 arutz 387 3786 arutz if ((e = mod_remove(&modlinkage)) != 0) 388 3786 arutz return (e); 389 3786 arutz 390 3786 arutz ddi_soft_state_fini(&dcd_state); 391 3786 arutz mutex_destroy(&dcd_attach_mutex); 392 3786 arutz 393 3786 arutz return (e); 394 3786 arutz } 395 3786 arutz 396 3786 arutz int 397 3786 arutz _info(struct modinfo *modinfop) 398 3786 arutz { 399 3786 arutz 400 3786 arutz return (mod_info(&modlinkage, modinfop)); 401 3786 arutz } 402 3786 arutz 403 3786 arutz static int 404 3786 arutz dcdprobe(dev_info_t *devi) 405 3786 arutz { 406 3786 arutz struct dcd_device *devp; 407 3786 arutz int rval = DDI_PROBE_PARTIAL; 408 3786 arutz int instance; 409 3786 arutz 410 3786 arutz devp = ddi_get_driver_private(devi); 411 3786 arutz instance = ddi_get_instance(devi); 412 3786 arutz 413 3786 arutz /* 414 3786 arutz * Keep a count of how many disks (ie. highest instance no) we have 415 3786 arutz * XXX currently not used but maybe useful later again 416 3786 arutz */ 417 3786 arutz mutex_enter(&dcd_attach_mutex); 418 3786 arutz if (instance > dcd_max_instance) 419 3786 arutz dcd_max_instance = instance; 420 3786 arutz mutex_exit(&dcd_attach_mutex); 421 3786 arutz 422 7224 cth DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "dcdprobe:\n"); 423 3786 arutz 424 3786 arutz if (ddi_get_soft_state(dcd_state, instance) != NULL) 425 3786 arutz return (DDI_PROBE_PARTIAL); 426 3786 arutz 427 3786 arutz /* 428 3786 arutz * Turn around and call utility probe routine 429 3786 arutz * to see whether we actually have a disk at 430 3786 arutz */ 431 3786 arutz 432 3786 arutz DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, 433 3786 arutz "dcdprobe: %x\n", dcd_probe(devp, NULL_FUNC)); 434 3786 arutz 435 3786 arutz switch (dcd_probe(devp, NULL_FUNC)) { 436 3786 arutz default: 437 3786 arutz case DCDPROBE_NORESP: 438 3786 arutz case DCDPROBE_NONCCS: 439 3786 arutz case DCDPROBE_NOMEM: 440 3786 arutz case DCDPROBE_FAILURE: 441 3786 arutz case DCDPROBE_BUSY: 442 3786 arutz break; 443 3786 arutz 444 3786 arutz case DCDPROBE_EXISTS: 445 3786 arutz /* 446 3786 arutz * Check whether it is a ATA device and then 447 3786 arutz * return SUCCESS. 448 3786 arutz */ 449 3786 arutz DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, 450 3786 arutz "config %x\n", devp->dcd_ident->dcd_config); 451 3786 arutz if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) { 452 3786 arutz if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) { 453 3786 arutz rval = DDI_PROBE_SUCCESS; 454 3786 arutz } else 455 3786 arutz rval = DDI_PROBE_FAILURE; 456 3786 arutz } else { 457 3786 arutz rval = DDI_PROBE_FAILURE; 458 3786 arutz } 459 3786 arutz break; 460 3786 arutz } 461 3786 arutz dcd_unprobe(devp); 462 3786 arutz 463 3786 arutz DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, 464 3786 arutz "dcdprobe returns %x\n", rval); 465 3786 arutz 466 3786 arutz return (rval); 467 3786 arutz } 468 3786 arutz 469 3786 arutz 470 3786 arutz /*ARGSUSED*/ 471 3786 arutz static int 472 3786 arutz dcdattach(dev_info_t *devi, ddi_attach_cmd_t cmd) 473 3786 arutz { 474 3786 arutz int instance, rval; 475 3786 arutz struct dcd_device *devp; 476 3786 arutz struct dcd_disk *un; 477 3786 arutz struct diskhd *dp; 478 3786 arutz char *pm_comp[] = 479 3786 arutz { "NAME=ide-disk", "0=standby", "1=idle", "2=active" }; 480 3786 arutz 481 3786 arutz /* CONSTCOND */ 482 3786 arutz ASSERT(NO_COMPETING_THREADS); 483 3786 arutz 484 3786 arutz 485 3786 arutz devp = ddi_get_driver_private(devi); 486 3786 arutz instance = ddi_get_instance(devi); 487 3786 arutz DAD_DEBUG2(devp->dcd_dev, dcd_label, DCD_DEBUG, "Attach Started\n"); 488 3786 arutz 489 3786 arutz switch (cmd) { 490 3786 arutz case DDI_ATTACH: 491 3786 arutz break; 492 3786 arutz 493 3786 arutz case DDI_RESUME: 494 3786 arutz if (!(un = ddi_get_soft_state(dcd_state, instance))) 495 3786 arutz return (DDI_FAILURE); 496 3786 arutz mutex_enter(DCD_MUTEX); 497 3786 arutz Restore_state(un); 498 3786 arutz /* 499 3786 arutz * Restore the state which was saved to give the 500 3786 arutz * the right state in un_last_state 501 3786 arutz */ 502 3786 arutz un->un_last_state = un->un_save_state; 503 3786 arutz un->un_throttle = 2; 504 3786 arutz cv_broadcast(&un->un_suspend_cv); 505 3786 arutz /* 506 3786 arutz * Raise the power level of the device to active. 507 3786 arutz */ 508 3786 arutz mutex_exit(DCD_MUTEX); 509 3786 arutz (void) pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE); 510 3786 arutz mutex_enter(DCD_MUTEX); 511 3786 arutz 512 3786 arutz /* 513 3786 arutz * start unit - if this is a low-activity device 514 3786 arutz * commands in queue will have to wait until new 515 3786 arutz * commands come in, which may take awhile. 516 3786 arutz * Also, we specifically don't check un_ncmds 517 3786 arutz * because we know that there really are no 518 3786 arutz * commands in progress after the unit was suspended 519 3786 arutz * and we could have reached the throttle level, been 520 3786 arutz * suspended, and have no new commands coming in for 521 3786 arutz * awhile. Highly unlikely, but so is the low- 522 3786 arutz * activity disk scenario. 523 3786 arutz */ 524 3786 arutz dp = &un->un_utab; 525 3786 arutz if (dp->b_actf && (dp->b_forw == NULL)) { 526 3786 arutz dcdstart(un); 527 3786 arutz } 528 3786 arutz 529 3786 arutz mutex_exit(DCD_MUTEX); 530 3786 arutz return (DDI_SUCCESS); 531 3786 arutz 532 3786 arutz default: 533 3786 arutz return (DDI_FAILURE); 534 3786 arutz } 535 3786 arutz 536 3786 arutz if (dcd_doattach(devi, SLEEP_FUNC) == DDI_FAILURE) { 537 3786 arutz return (DDI_FAILURE); 538 3786 arutz } 539 3786 arutz 540 3786 arutz if (!(un = (struct dcd_disk *) 541 3786 arutz ddi_get_soft_state(dcd_state, instance))) { 542 3786 arutz return (DDI_FAILURE); 543 3786 arutz } 544 3786 arutz devp->dcd_private = (ataopaque_t)un; 545 3786 arutz 546 3786 arutz /* 547 3786 arutz * Add a zero-length attribute to tell the world we support 548 3786 arutz * kernel ioctls (for layered drivers) 549 3786 arutz */ 550 3786 arutz (void) ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP, 551 3786 arutz DDI_KERNEL_IOCTL, NULL, 0); 552 3786 arutz 553 3786 arutz /* 554 3786 arutz * Since the dad device does not have the 'reg' property, 555 3786 arutz * cpr will not call its DDI_SUSPEND/DDI_RESUME entries. 556 3786 arutz * The following code is to tell cpr that this device 557 3786 arutz * does need to be suspended and resumed. 558 3786 arutz */ 559 3786 arutz (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi, 560 3786 arutz "pm-hardware-state", (caddr_t)"needs-suspend-resume"); 561 3786 arutz 562 3786 arutz /* 563 3786 arutz * Initialize power management bookkeeping; 564 3786 arutz * Create components - In IDE case there are 3 levels and one 565 3786 arutz * component. The levels being - active, idle, standby. 566 3786 arutz */ 567 3786 arutz 568 3786 arutz rval = ddi_prop_update_string_array(DDI_DEV_T_NONE, 569 3786 arutz devi, "pm-components", pm_comp, 4); 570 3786 arutz if (rval == DDI_PROP_SUCCESS) { 571 3786 arutz /* 572 3786 arutz * Ignore the return value of pm_raise_power 573 3786 arutz * Even if we check the return values and 574 3786 arutz * remove the property created above, PM 575 3786 arutz * framework will not honour the change after 576 3786 arutz * first call to pm_raise_power. Hence, the 577 3786 arutz * removal of that property does not help if 578 3786 arutz * pm_raise_power fails. 579 3786 arutz */ 580 3786 arutz (void) pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE); 581 3786 arutz } 582 3786 arutz 583 3786 arutz ddi_report_dev(devi); 584 3786 arutz 585 3786 arutz cmlb_alloc_handle(&un->un_dklbhandle); 586 3786 arutz 587 3786 arutz if (cmlb_attach(devi, 588 7224 cth &dcd_lb_ops, 589 7224 cth 0, 590 8863 Edward B_FALSE, 591 8863 Edward B_FALSE, 592 7224 cth DDI_NT_BLOCK_CHAN, 593 7224 cth CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8, 594 7224 cth un->un_dklbhandle, 595 7224 cth 0) != 0) { 596 3786 arutz cmlb_free_handle(&un->un_dklbhandle); 597 3786 arutz dcd_free_softstate(un, devi); 598 3786 arutz return (DDI_FAILURE); 599 3786 arutz } 600 3786 arutz 601 3786 arutz mutex_enter(DCD_MUTEX); 602 3786 arutz (void) dcd_validate_geometry(un); 603 3786 arutz 604 3786 arutz /* Get devid; create a devid ONLY IF could not get ID */ 605 3786 arutz if (dcd_get_devid(un) == NULL) { 606 3786 arutz /* Create the fab'd devid */ 607 3786 arutz (void) dcd_create_devid(un); 608 3786 arutz } 609 3786 arutz mutex_exit(DCD_MUTEX); 610 3786 arutz 611 3786 arutz return (DDI_SUCCESS); 612 3786 arutz } 613 3786 arutz 614 3786 arutz static void 615 3786 arutz dcd_free_softstate(struct dcd_disk *un, dev_info_t *devi) 616 3786 arutz { 617 3786 arutz struct dcd_device *devp; 618 3786 arutz int instance = ddi_get_instance(devi); 619 3786 arutz 620 3786 arutz devp = ddi_get_driver_private(devi); 621 3786 arutz 622 3786 arutz if (un) { 623 3786 arutz sema_destroy(&un->un_semoclose); 624 3786 arutz cv_destroy(&un->un_sbuf_cv); 625 3786 arutz cv_destroy(&un->un_state_cv); 626 3786 arutz cv_destroy(&un->un_disk_busy_cv); 627 3786 arutz cv_destroy(&un->un_suspend_cv); 628 3786 arutz 629 3786 arutz /* 630 3786 arutz * Deallocate command packet resources. 631 3786 arutz */ 632 3786 arutz if (un->un_sbufp) 633 3786 arutz freerbuf(un->un_sbufp); 634 3786 arutz if (un->un_dp) { 635 3786 arutz kmem_free((caddr_t)un->un_dp, sizeof (*un->un_dp)); 636 3786 arutz } 637 3786 arutz /* 638 3786 arutz * Unregister the devid and free devid resources allocated 639 3786 arutz */ 640 3786 arutz ddi_devid_unregister(DCD_DEVINFO); 641 3786 arutz if (un->un_devid) { 642 3786 arutz ddi_devid_free(un->un_devid); 643 3786 arutz un->un_devid = NULL; 644 3786 arutz } 645 3786 arutz 646 3786 arutz /* 647 3786 arutz * Delete kstats. Kstats for non CD devices are deleted 648 3786 arutz * in dcdclose. 649 3786 arutz */ 650 3786 arutz if (un->un_stats) { 651 3786 arutz kstat_delete(un->un_stats); 652 3786 arutz } 653 3786 arutz 654 3786 arutz } 655 3786 arutz 656 3786 arutz /* 657 3786 arutz * Cleanup scsi_device resources. 658 3786 arutz */ 659 3786 arutz ddi_soft_state_free(dcd_state, instance); 660 3786 arutz devp->dcd_private = (ataopaque_t)0; 661 3786 arutz /* unprobe scsi device */ 662 3786 arutz dcd_unprobe(devp); 663 3786 arutz 664 3786 arutz /* Remove properties created during attach */ 665 3786 arutz ddi_prop_remove_all(devi); 666 3786 arutz } 667 3786 arutz 668 3786 arutz static int 669 3786 arutz dcddetach(dev_info_t *devi, ddi_detach_cmd_t cmd) 670 3786 arutz { 671 3786 arutz int instance; 672 3786 arutz struct dcd_disk *un; 673 3786 arutz clock_t wait_cmds_complete; 674 3786 arutz instance = ddi_get_instance(devi); 675 3786 arutz 676 3786 arutz if (!(un = ddi_get_soft_state(dcd_state, instance))) 677 3786 arutz return (DDI_FAILURE); 678 3786 arutz 679 3786 arutz switch (cmd) { 680 3786 arutz case DDI_DETACH: 681 3786 arutz return (dcd_dr_detach(devi)); 682 3786 arutz 683 3786 arutz case DDI_SUSPEND: 684 3786 arutz mutex_enter(DCD_MUTEX); 685 3786 arutz if (un->un_state == DCD_STATE_SUSPENDED) { 686 3786 arutz mutex_exit(DCD_MUTEX); 687 3786 arutz return (DDI_SUCCESS); 688 3786 arutz } 689 3786 arutz un->un_throttle = 0; 690 3786 arutz /* 691 3786 arutz * Save the last state first 692 3786 arutz */ 693 3786 arutz un->un_save_state = un->un_last_state; 694 3786 arutz 695 3786 arutz New_state(un, DCD_STATE_SUSPENDED); 696 3786 arutz 697 3786 arutz /* 698 3786 arutz * wait till current operation completed. If we are 699 3786 arutz * in the resource wait state (with an intr outstanding) 700 3786 arutz * then we need to wait till the intr completes and 701 3786 arutz * starts the next cmd. We wait for 702 3786 arutz * DCD_WAIT_CMDS_COMPLETE seconds before failing the 703 3786 arutz * DDI_SUSPEND. 704 3786 arutz */ 705 3786 arutz wait_cmds_complete = ddi_get_lbolt(); 706 3786 arutz wait_cmds_complete += 707 7224 cth DCD_WAIT_CMDS_COMPLETE * drv_usectohz(1000000); 708 3786 arutz 709 3786 arutz while (un->un_ncmds) { 710 3786 arutz if (cv_timedwait(&un->un_disk_busy_cv, 711 3786 arutz DCD_MUTEX, wait_cmds_complete) == -1) { 712 3786 arutz /* 713 3786 arutz * commands Didn't finish in the 714 3786 arutz * specified time, fail the DDI_SUSPEND. 715 3786 arutz */ 716 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, 717 3786 arutz DCD_DEBUG, "dcddetach: SUSPEND " 718 3786 arutz "failed due to outstanding cmds\n"); 719 3786 arutz Restore_state(un); 720 3786 arutz mutex_exit(DCD_MUTEX); 721 3786 arutz return (DDI_FAILURE); 722 3786 arutz } 723 3786 arutz } 724 3786 arutz mutex_exit(DCD_MUTEX); 725 3786 arutz return (DDI_SUCCESS); 726 3786 arutz } 727 3786 arutz return (DDI_FAILURE); 728 3786 arutz } 729 3786 arutz 730 3786 arutz /* 731 3786 arutz * The reset entry point gets invoked at the system shutdown time or through 732 3786 arutz * CPR code at system suspend. 733 3786 arutz * Will be flushing the cache and expect this to be last I/O operation to the 734 3786 arutz * disk before system reset/power off. 735 3786 arutz */ 736 3786 arutz /*ARGSUSED*/ 737 3786 arutz static int 738 3786 arutz dcdreset(dev_info_t *dip, ddi_reset_cmd_t cmd) 739 3786 arutz { 740 3786 arutz struct dcd_disk *un; 741 3786 arutz int instance; 742 3786 arutz 743 3786 arutz instance = ddi_get_instance(dip); 744 3786 arutz 745 3786 arutz if (!(un = ddi_get_soft_state(dcd_state, instance))) 746 3786 arutz return (DDI_FAILURE); 747 3786 arutz 748 3786 arutz dcd_flush_cache(un); 749 3786 arutz 750 3786 arutz return (DDI_SUCCESS); 751 3786 arutz } 752 3786 arutz 753 3786 arutz 754 3786 arutz static int 755 3786 arutz dcd_dr_detach(dev_info_t *devi) 756 3786 arutz { 757 3786 arutz struct dcd_device *devp; 758 3786 arutz struct dcd_disk *un; 759 3786 arutz 760 3786 arutz /* 761 3786 arutz * Get scsi_device structure for this instance. 762 3786 arutz */ 763 3786 arutz if ((devp = ddi_get_driver_private(devi)) == NULL) 764 3786 arutz return (DDI_FAILURE); 765 3786 arutz 766 3786 arutz /* 767 3786 arutz * Get dcd_disk structure containing target 'private' information 768 3786 arutz */ 769 3786 arutz un = (struct dcd_disk *)devp->dcd_private; 770 3786 arutz 771 3786 arutz /* 772 3786 arutz * Verify there are NO outstanding commands issued to this device. 773 3786 arutz * ie, un_ncmds == 0. 774 3786 arutz * It's possible to have outstanding commands through the physio 775 3786 arutz * code path, even though everything's closed. 776 3786 arutz */ 777 3786 arutz #ifndef lint 778 3786 arutz _NOTE(COMPETING_THREADS_NOW); 779 3786 arutz #endif 780 3786 arutz mutex_enter(DCD_MUTEX); 781 3786 arutz if (un->un_ncmds) { 782 3786 arutz mutex_exit(DCD_MUTEX); 783 3786 arutz _NOTE(NO_COMPETING_THREADS_NOW); 784 3786 arutz return (DDI_FAILURE); 785 3786 arutz } 786 3786 arutz 787 3786 arutz mutex_exit(DCD_MUTEX); 788 3786 arutz 789 3786 arutz cmlb_detach(un->un_dklbhandle, 0); 790 3786 arutz cmlb_free_handle(&un->un_dklbhandle); 791 3786 arutz 792 3786 arutz 793 3786 arutz /* 794 3786 arutz * Lower the power state of the device 795 3786 arutz * i.e. the minimum power consumption state - sleep. 796 3786 arutz */ 797 3786 arutz (void) pm_lower_power(DCD_DEVINFO, 0, DCD_DEVICE_STANDBY); 798 3786 arutz 799 3786 arutz _NOTE(NO_COMPETING_THREADS_NOW); 800 3786 arutz 801 3786 arutz /* 802 3786 arutz * at this point there are no competing threads anymore 803 3786 arutz * release active MT locks and all device resources. 804 3786 arutz */ 805 3786 arutz dcd_free_softstate(un, devi); 806 3786 arutz 807 3786 arutz return (DDI_SUCCESS); 808 3786 arutz } 809 3786 arutz 810 3786 arutz static int 811 3786 arutz dcdpower(dev_info_t *devi, int component, int level) 812 3786 arutz { 813 3786 arutz struct dcd_pkt *pkt; 814 3786 arutz struct dcd_disk *un; 815 3786 arutz int instance; 816 3786 arutz uchar_t cmd; 817 3786 arutz 818 3786 arutz 819 3786 arutz instance = ddi_get_instance(devi); 820 3786 arutz 821 3786 arutz if (!(un = ddi_get_soft_state(dcd_state, instance)) || 822 7224 cth (DCD_DEVICE_STANDBY > level) || (level > DCD_DEVICE_ACTIVE) || 823 7224 cth component != 0) { 824 3786 arutz return (DDI_FAILURE); 825 3786 arutz } 826 3786 arutz 827 3786 arutz mutex_enter(DCD_MUTEX); 828 3786 arutz /* 829 3786 arutz * if there are active commands for the device or device will be 830 3786 arutz * active soon. At the same time there is request to lower power 831 3786 arutz * return failure. 832 3786 arutz */ 833 3786 arutz if ((un->un_ncmds) && (level != DCD_DEVICE_ACTIVE)) { 834 3786 arutz mutex_exit(DCD_MUTEX); 835 3786 arutz return (DDI_FAILURE); 836 3786 arutz } 837 3786 arutz 838 3786 arutz if ((un->un_state == DCD_STATE_OFFLINE) || 839 3786 arutz (un->un_state == DCD_STATE_FATAL)) { 840 3786 arutz mutex_exit(DCD_MUTEX); 841 3786 arutz return (DDI_FAILURE); 842 3786 arutz } 843 3786 arutz 844 3786 arutz if (level == DCD_DEVICE_ACTIVE) { 845 3786 arutz /* 846 3786 arutz * No need to fire any command, just set the state structure 847 3786 arutz * to indicate previous state and set the level to active 848 3786 arutz */ 849 3786 arutz un->un_power_level = DCD_DEVICE_ACTIVE; 850 3786 arutz if (un->un_state == DCD_STATE_PM_SUSPENDED) 851 3786 arutz Restore_state(un); 852 3786 arutz mutex_exit(DCD_MUTEX); 853 3786 arutz } else { 854 3786 arutz pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL, 855 3786 arutz NULL, (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN, 856 3786 arutz PKT_CONSISTENT, NULL_FUNC, NULL); 857 3786 arutz 858 3786 arutz if (pkt == (struct dcd_pkt *)NULL) { 859 3786 arutz mutex_exit(DCD_MUTEX); 860 3786 arutz return (DDI_FAILURE); 861 3786 arutz } 862 3786 arutz 863 3786 arutz switch (level) { 864 3786 arutz case DCD_DEVICE_IDLE: 865 3786 arutz cmd = ATA_IDLE_IMMEDIATE; 866 3786 arutz break; 867 3786 arutz 868 3786 arutz case DCD_DEVICE_STANDBY: 869 3786 arutz cmd = ATA_STANDBY_IMMEDIATE; 870 3786 arutz break; 871 3786 arutz } 872 3786 arutz 873 3786 arutz makecommand(pkt, 0, cmd, 0, 0, 0, NO_DATA_XFER, 0); 874 3786 arutz mutex_exit(DCD_MUTEX); 875 3786 arutz /* 876 3786 arutz * Issue the appropriate command 877 3786 arutz */ 878 3786 arutz if ((dcd_poll(pkt)) || (SCBP_C(pkt) != STATUS_GOOD)) { 879 3786 arutz dcd_destroy_pkt(pkt); 880 3786 arutz return (DDI_FAILURE); 881 3786 arutz } 882 3786 arutz dcd_destroy_pkt(pkt); 883 3786 arutz mutex_enter(DCD_MUTEX); 884 3786 arutz if (un->un_state != DCD_STATE_PM_SUSPENDED) 885 3786 arutz New_state(un, DCD_STATE_PM_SUSPENDED); 886 3786 arutz un->un_power_level = level; 887 3786 arutz mutex_exit(DCD_MUTEX); 888 3786 arutz } 889 3786 arutz 890 3786 arutz return (DDI_SUCCESS); 891 3786 arutz } 892 3786 arutz 893 3786 arutz static int 894 3786 arutz dcd_doattach(dev_info_t *devi, int (*canwait)()) 895 3786 arutz { 896 3786 arutz struct dcd_device *devp; 897 3786 arutz struct dcd_disk *un = (struct dcd_disk *)0; 898 3786 arutz int instance; 899 3786 arutz int km_flags = (canwait != NULL_FUNC)? KM_SLEEP : KM_NOSLEEP; 900 3786 arutz int rval; 901 3786 arutz char *prop_template = "target%x-dcd-options"; 902 3786 arutz int options; 903 3786 arutz char prop_str[32]; 904 3786 arutz int target; 905 3786 arutz diskaddr_t capacity; 906 3786 arutz 907 3786 arutz devp = ddi_get_driver_private(devi); 908 3786 arutz 909 3786 arutz /* 910 3786 arutz * Call the routine scsi_probe to do some of the dirty work. 911 3786 arutz * If the INQUIRY command succeeds, the field dcd_inq in the 912 3786 arutz * device structure will be filled in. The dcd_sense structure 913 3786 arutz * will also be allocated. 914 3786 arutz */ 915 3786 arutz 916 3786 arutz switch (dcd_probe(devp, canwait)) { 917 3786 arutz default: 918 3786 arutz return (DDI_FAILURE); 919 3786 arutz 920 3786 arutz case DCDPROBE_EXISTS: 921 3786 arutz if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) { 922 3786 arutz if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) { 923 3786 arutz rval = DDI_SUCCESS; 924 3786 arutz } else { 925 3786 arutz rval = DDI_FAILURE; 926 3786 arutz goto error; 927 3786 arutz } 928 3786 arutz } else { 929 3786 arutz rval = DDI_FAILURE; 930 3786 arutz goto error; 931 3786 arutz } 932 3786 arutz } 933 3786 arutz 934 3786 arutz 935 3786 arutz instance = ddi_get_instance(devp->dcd_dev); 936 3786 arutz 937 3786 arutz if (ddi_soft_state_zalloc(dcd_state, instance) != DDI_SUCCESS) { 938 3786 arutz rval = DDI_FAILURE; 939 3786 arutz goto error; 940 3786 arutz } 941 3786 arutz 942 3786 arutz un = ddi_get_soft_state(dcd_state, instance); 943 3786 arutz 944 3786 arutz un->un_sbufp = getrbuf(km_flags); 945 3786 arutz if (un->un_sbufp == (struct buf *)NULL) { 946 3786 arutz rval = DDI_FAILURE; 947 3786 arutz goto error; 948 3786 arutz } 949 3786 arutz 950 3786 arutz 951 3786 arutz un->un_dcd = devp; 952 3786 arutz un->un_power_level = -1; 953 3786 arutz un->un_tgattribute.media_is_writable = 1; 954 3786 arutz 955 3786 arutz sema_init(&un->un_semoclose, 1, NULL, SEMA_DRIVER, NULL); 956 3786 arutz cv_init(&un->un_sbuf_cv, NULL, CV_DRIVER, NULL); 957 3786 arutz cv_init(&un->un_state_cv, NULL, CV_DRIVER, NULL); 958 3786 arutz /* Initialize power management conditional variable */ 959 3786 arutz cv_init(&un->un_disk_busy_cv, NULL, CV_DRIVER, NULL); 960 3786 arutz cv_init(&un->un_suspend_cv, NULL, CV_DRIVER, NULL); 961 3786 arutz 962 3786 arutz if (un->un_dp == 0) { 963 3786 arutz /* 964 3786 arutz * Assume CCS drive, assume parity, but call 965 3786 arutz * it a CDROM if it is a RODIRECT device. 966 3786 arutz */ 967 3786 arutz un->un_dp = (struct dcd_drivetype *) 968 3786 arutz kmem_zalloc(sizeof (struct dcd_drivetype), km_flags); 969 3786 arutz if (!un->un_dp) { 970 3786 arutz rval = DDI_FAILURE; 971 3786 arutz goto error; 972 3786 arutz } 973 3786 arutz if ((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) { 974 3786 arutz if (devp->dcd_ident->dcd_config & ATANON_REMOVABLE) { 975 3786 arutz un->un_dp->ctype = CTYPE_DISK; 976 3786 arutz } 977 3786 arutz } else { 978 3786 arutz rval = DDI_FAILURE; 979 3786 arutz goto error; 980 3786 arutz } 981 3786 arutz un->un_dp->name = "CCS"; 982 3786 arutz un->un_dp->options = 0; 983 3786 arutz } 984 3786 arutz 985 3786 arutz /* 986 3786 arutz * Allow I/O requests at un_secsize offset in multiple of un_secsize. 987 3786 arutz */ 988 3786 arutz un->un_secsize = DEV_BSIZE; 989 3786 arutz 990 3786 arutz /* 991 3786 arutz * If the device is not a removable media device, make sure that 992 3786 arutz * that the device is ready, by issuing the another identify but 993 3786 arutz * not needed. Get the capacity from identify data and store here. 994 3786 arutz */ 995 3786 arutz if (dcd_compute_dk_capacity(devp, &capacity) == 0) { 996 3786 arutz un->un_diskcapacity = capacity; 997 3786 arutz un->un_lbasize = DEV_BSIZE; 998 3786 arutz } 999 3786 arutz 1000 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "Geometry Data\n"); 1001 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "cyls %x, heads %x", 1002 3786 arutz devp->dcd_ident->dcd_fixcyls, 1003 3786 arutz devp->dcd_ident->dcd_heads); 1004 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "sectors %x,", 1005 3786 arutz devp->dcd_ident->dcd_sectors); 1006 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "capacity %llx\n", 1007 3786 arutz capacity); 1008 3786 arutz 1009 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1010 3786 arutz "dcdprobe: drive selected\n"); 1011 3786 arutz 1012 3786 arutz /* 1013 3786 arutz * Check for the property target<n>-dcd-options to find the option 1014 3786 arutz * set by the HBA driver for this target so that we can set the 1015 3786 arutz * Unit structure variable so that we can send commands accordingly. 1016 3786 arutz */ 1017 7875 Chris target = devp->dcd_address->da_target; 1018 3786 arutz (void) sprintf(prop_str, prop_template, target); 1019 3786 arutz options = ddi_prop_get_int(DDI_DEV_T_ANY, devi, DDI_PROP_NOTPROM, 1020 3786 arutz prop_str, -1); 1021 3786 arutz if (options < 0) { 1022 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1023 3786 arutz "No per target properties"); 1024 3786 arutz } else { 1025 3786 arutz if ((options & DCD_DMA_MODE) == DCD_DMA_MODE) { 1026 3786 arutz un->un_dp->options |= DMA_SUPPORTTED; 1027 3786 arutz un->un_dp->dma_mode = (options >> 3) & 0x03; 1028 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1029 3786 arutz "mode %x\n", un->un_dp->dma_mode); 1030 3786 arutz } else { 1031 3786 arutz un->un_dp->options &= ~DMA_SUPPORTTED; 1032 3786 arutz un->un_dp->pio_mode = options & 0x7; 1033 3786 arutz if (options & DCD_BLOCK_MODE) 1034 3786 arutz un->un_dp->options |= BLOCK_MODE; 1035 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1036 3786 arutz "mode %x\n", un->un_dp->pio_mode); 1037 3786 arutz } 1038 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1039 3786 arutz "options %x,", un->un_dp->options); 1040 3786 arutz } 1041 3786 arutz 1042 3786 arutz un->un_throttle = 2; 1043 3786 arutz /* 1044 3786 arutz * set default max_xfer_size - This should depend on whether the 1045 3786 arutz * Block mode is supported by the device or not. 1046 3786 arutz */ 1047 3786 arutz un->un_max_xfer_size = MAX_ATA_XFER_SIZE; 1048 3786 arutz 1049 3786 arutz /* 1050 3786 arutz * Set write cache enable softstate 1051 3786 arutz * 1052 3786 arutz * WCE is only supported in ATAPI-4 or higher; for 1053 3786 arutz * lower rev devices, must assume write cache is 1054 3786 arutz * enabled. 1055 3786 arutz */ 1056 3786 arutz mutex_enter(DCD_MUTEX); 1057 3786 arutz un->un_write_cache_enabled = (devp->dcd_ident->dcd_majvers == 0xffff) || 1058 3786 arutz ((devp->dcd_ident->dcd_majvers & IDENTIFY_80_ATAPI_4) == 0) || 1059 3786 arutz (devp->dcd_ident->dcd_features85 & IDENTIFY_85_WCE) != 0; 1060 3786 arutz mutex_exit(DCD_MUTEX); 1061 3786 arutz 1062 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1063 3786 arutz "dcd_doattach returns good\n"); 1064 3786 arutz 1065 3786 arutz return (rval); 1066 3786 arutz 1067 3786 arutz error: 1068 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcd_doattach failed\n"); 1069 3786 arutz dcd_free_softstate(un, devi); 1070 3786 arutz return (rval); 1071 3786 arutz } 1072 3786 arutz 1073 3786 arutz #ifdef NOTNEEDED 1074 3786 arutz /* 1075 3786 arutz * This routine is used to set the block mode of operation by issuing the 1076 3786 arutz * Set Block mode ata command with the maximum block mode possible 1077 3786 arutz */ 1078 3786 arutz dcd_set_multiple(struct dcd_disk *un) 1079 3786 arutz { 1080 3786 arutz int status; 1081 3786 arutz struct udcd_cmd ucmd; 1082 3786 arutz struct dcd_cmd cdb; 1083 3786 arutz dev_t dev; 1084 3786 arutz 1085 3786 arutz 1086 3786 arutz /* Zero all the required structure */ 1087 3786 arutz (void) bzero((caddr_t)&ucmd, sizeof (ucmd)); 1088 3786 arutz 1089 3786 arutz (void) bzero((caddr_t)&cdb, sizeof (struct dcd_cmd)); 1090 3786 arutz 1091 3786 arutz cdb.cmd = ATA_SET_MULTIPLE; 1092 3786 arutz /* 1093 3786 arutz * Here we should pass what needs to go into sector count REGISTER. 1094 3786 arutz * Eventhough this field indicates the number of bytes to read we 1095 3786 arutz * need to specify the block factor in terms of bytes so that it 1096 3786 arutz * will be programmed by the HBA driver into the sector count register. 1097 3786 arutz */ 1098 3786 arutz cdb.size = un->un_lbasize * un->un_dp->block_factor; 1099 3786 arutz 1100 3786 arutz cdb.sector_num.lba_num = 0; 1101 3786 arutz cdb.address_mode = ADD_LBA_MODE; 1102 3786 arutz cdb.direction = NO_DATA_XFER; 1103 3786 arutz 1104 3786 arutz ucmd.udcd_flags = 0; 1105 3786 arutz ucmd.udcd_cmd = &cdb; 1106 3786 arutz ucmd.udcd_bufaddr = NULL; 1107 3786 arutz ucmd.udcd_buflen = 0; 1108 3786 arutz ucmd.udcd_flags |= UDCD_SILENT; 1109 3786 arutz 1110 3786 arutz dev = makedevice(ddi_driver_major(DCD_DEVINFO), 1111 3786 arutz ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT); 1112 3786 arutz 1113 3786 arutz 1114 3786 arutz status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE); 1115 3786 arutz 1116 3786 arutz return (status); 1117 3786 arutz } 1118 3786 arutz /* 1119 3786 arutz * The following routine is used only for setting the transfer mode 1120 3786 arutz * and it is not designed for transferring any other features subcommand. 1121 3786 arutz */ 1122 3786 arutz dcd_set_features(struct dcd_disk *un, uchar_t mode) 1123 3786 arutz { 1124 3786 arutz int status; 1125 3786 arutz struct udcd_cmd ucmd; 1126 3786 arutz struct dcd_cmd cdb; 1127 3786 arutz dev_t dev; 1128 3786 arutz 1129 3786 arutz 1130 3786 arutz /* Zero all the required structure */ 1131 3786 arutz (void) bzero((caddr_t)&ucmd, sizeof (ucmd)); 1132 3786 arutz 1133 3786 arutz (void) bzero((caddr_t)&cdb, sizeof (struct dcd_cmd)); 1134 3786 arutz 1135 3786 arutz cdb.cmd = ATA_SET_FEATURES; 1136 3786 arutz /* 1137 3786 arutz * Here we need to pass what needs to go into the sector count register 1138 3786 arutz * But in the case of SET FEATURES command the value taken in the 1139 3786 arutz * sector count register depends what type of subcommand is 1140 3786 arutz * passed in the features register. Since we have defined the size to 1141 3786 arutz * be the size in bytes in this context it does not indicate bytes 1142 3786 arutz * instead it indicates the mode to be programmed. 1143 3786 arutz */ 1144 3786 arutz cdb.size = un->un_lbasize * mode; 1145 3786 arutz 1146 3786 arutz cdb.sector_num.lba_num = 0; 1147 3786 arutz cdb.address_mode = ADD_LBA_MODE; 1148 3786 arutz cdb.direction = NO_DATA_XFER; 1149 3786 arutz cdb.features = ATA_FEATURE_SET_MODE; 1150 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1151 3786 arutz "size %x, features %x, cmd %x\n", 1152 3786 arutz cdb.size, cdb.features, cdb.cmd); 1153 3786 arutz 1154 3786 arutz ucmd.udcd_flags = 0; 1155 3786 arutz ucmd.udcd_cmd = &cdb; 1156 3786 arutz ucmd.udcd_bufaddr = NULL; 1157 3786 arutz ucmd.udcd_buflen = 0; 1158 3786 arutz ucmd.udcd_flags |= UDCD_SILENT; 1159 3786 arutz 1160 3786 arutz dev = makedevice(ddi_driver_major(DCD_DEVINFO), 1161 3786 arutz ddi_get_instance(DCD_DEVINFO) << DCDUNIT_SHIFT); 1162 3786 arutz 1163 3786 arutz status = dcdioctl_cmd(dev, &ucmd, UIO_SYSSPACE, UIO_SYSSPACE); 1164 3786 arutz 1165 3786 arutz return (status); 1166 3786 arutz } 1167 3786 arutz #endif 1168 3786 arutz 1169 3786 arutz /* 1170 3786 arutz * Validate the geometry for this disk, e.g., 1171 3786 arutz * see whether it has a valid label. 1172 3786 arutz */ 1173 3786 arutz static int 1174 3786 arutz dcd_validate_geometry(struct dcd_disk *un) 1175 3786 arutz { 1176 3786 arutz int secsize = 0; 1177 3786 arutz struct dcd_device *devp; 1178 3786 arutz int secdiv; 1179 3786 arutz int rval; 1180 3786 arutz 1181 3786 arutz ASSERT(mutex_owned(DCD_MUTEX)); 1182 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1183 3786 arutz "dcd_validate_geometry: started \n"); 1184 3786 arutz 1185 3786 arutz if (un->un_lbasize < 0) { 1186 3786 arutz return (DCD_BAD_LABEL); 1187 3786 arutz } 1188 3786 arutz 1189 3786 arutz if (un->un_state == DCD_STATE_PM_SUSPENDED) { 1190 3786 arutz mutex_exit(DCD_MUTEX); 1191 7224 cth if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE) != 1192 7224 cth DDI_SUCCESS) { 1193 3786 arutz mutex_enter(DCD_MUTEX); 1194 3786 arutz return (DCD_BAD_LABEL); 1195 3786 arutz } 1196 3786 arutz mutex_enter(DCD_MUTEX); 1197 3786 arutz } 1198 3786 arutz 1199 3786 arutz secsize = un->un_secsize; 1200 3786 arutz 1201 3786 arutz /* 1202 3786 arutz * take a log base 2 of sector size (sorry) 1203 3786 arutz */ 1204 3786 arutz for (secdiv = 0; secsize = secsize >> 1; secdiv++) 1205 3786 arutz ; 1206 3786 arutz un->un_secdiv = secdiv; 1207 3786 arutz 1208 3786 arutz /* 1209 3786 arutz * Only DIRECT ACCESS devices will have Sun labels. 1210 3786 arutz * CD's supposedly have a Sun label, too 1211 3786 arutz */ 1212 3786 arutz 1213 3786 arutz devp = un->un_dcd; 1214 3786 arutz 1215 3786 arutz if (((devp->dcd_ident->dcd_config & ATAPI_DEVICE) == 0) && 1216 3786 arutz (devp->dcd_ident->dcd_config & ATANON_REMOVABLE)) { 1217 3786 arutz mutex_exit(DCD_MUTEX); 1218 3786 arutz rval = cmlb_validate(un->un_dklbhandle, 0, 0); 1219 3786 arutz mutex_enter(DCD_MUTEX); 1220 3786 arutz if (rval == ENOMEM) 1221 3786 arutz return (DCD_NO_MEM_FOR_LABEL); 1222 3786 arutz else if (rval != 0) 1223 3786 arutz return (DCD_BAD_LABEL); 1224 3786 arutz } else { 1225 3786 arutz /* it should never get here. */ 1226 3786 arutz return (DCD_BAD_LABEL); 1227 3786 arutz } 1228 3786 arutz 1229 3786 arutz /* 1230 3786 arutz * take a log base 2 of logical block size 1231 3786 arutz */ 1232 3786 arutz secsize = un->un_lbasize; 1233 3786 arutz for (secdiv = 0; secsize = secsize >> 1; secdiv++) 1234 3786 arutz ; 1235 3786 arutz un->un_lbadiv = secdiv; 1236 3786 arutz 1237 3786 arutz /* 1238 3786 arutz * take a log base 2 of the multiple of DEV_BSIZE blocks that 1239 3786 arutz * make up one logical block 1240 3786 arutz */ 1241 3786 arutz secsize = un->un_lbasize >> DEV_BSHIFT; 1242 3786 arutz for (secdiv = 0; secsize = secsize >> 1; secdiv++) 1243 3786 arutz ; 1244 3786 arutz un->un_blknoshift = secdiv; 1245 3786 arutz return (0); 1246 3786 arutz } 1247 3786 arutz 1248 3786 arutz /* 1249 3786 arutz * Unix Entry Points 1250 3786 arutz */ 1251 3786 arutz 1252 3786 arutz /* ARGSUSED3 */ 1253 3786 arutz static int 1254 3786 arutz dcdopen(dev_t *dev_p, int flag, int otyp, cred_t *cred_p) 1255 3786 arutz { 1256 3786 arutz dev_t dev = *dev_p; 1257 3786 arutz int rval = EIO; 1258 3786 arutz int partmask; 1259 3786 arutz int nodelay = (flag & (FNDELAY | FNONBLOCK)); 1260 3786 arutz int i; 1261 3786 arutz char kstatname[KSTAT_STRLEN]; 1262 3786 arutz diskaddr_t lblocks; 1263 3786 arutz char *partname; 1264 3786 arutz 1265 3786 arutz GET_SOFT_STATE(dev); 1266 3786 arutz 1267 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1268 3786 arutz "Inside Open flag %x, otyp %x\n", flag, otyp); 1269 3786 arutz 1270 3786 arutz if (otyp >= OTYPCNT) { 1271 3786 arutz return (EINVAL); 1272 3786 arutz } 1273 3786 arutz 1274 3786 arutz partmask = 1 << part; 1275 3786 arutz 1276 3786 arutz /* 1277 3786 arutz * We use a semaphore here in order to serialize 1278 3786 arutz * open and close requests on the device. 1279 3786 arutz */ 1280 3786 arutz sema_p(&un->un_semoclose); 1281 3786 arutz 1282 3786 arutz mutex_enter(DCD_MUTEX); 1283 3786 arutz 1284 3786 arutz if ((un->un_state & DCD_STATE_FATAL) == DCD_STATE_FATAL) { 1285 3786 arutz rval = ENXIO; 1286 3786 arutz goto done; 1287 3786 arutz } 1288 3786 arutz 1289 3786 arutz while (un->un_state == DCD_STATE_SUSPENDED) { 1290 3786 arutz cv_wait(&un->un_suspend_cv, DCD_MUTEX); 1291 3786 arutz } 1292 3786 arutz 1293 3786 arutz if ((un->un_state == DCD_STATE_PM_SUSPENDED) && (!nodelay)) { 1294 3786 arutz mutex_exit(DCD_MUTEX); 1295 3786 arutz if (pm_raise_power(DCD_DEVINFO, 0, DCD_DEVICE_ACTIVE) 1296 3786 arutz != DDI_SUCCESS) { 1297 3786 arutz mutex_enter(DCD_MUTEX); 1298 3786 arutz rval = EIO; 1299 3786 arutz goto done; 1300 3786 arutz } 1301 3786 arutz mutex_enter(DCD_MUTEX); 1302 3786 arutz } 1303 3786 arutz 1304 3786 arutz /* 1305 3786 arutz * set make_dcd_cmd() flags and stat_size here since these 1306 3786 arutz * are unlikely to change 1307 3786 arutz */ 1308 3786 arutz un->un_cmd_flags = 0; 1309 3786 arutz 1310 3786 arutz un->un_cmd_stat_size = 2; 1311 3786 arutz 1312 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdopen un=0x%p\n", 1313 3786 arutz (void *)un); 1314 3786 arutz /* 1315 3786 arutz * check for previous exclusive open 1316 3786 arutz */ 1317 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1318 3786 arutz "exclopen=%x, flag=%x, regopen=%x\n", 1319 3786 arutz un->un_exclopen, flag, un->un_ocmap.regopen[otyp]); 1320 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1321 3786 arutz "Exclusive open flag %x, partmask %x\n", 1322 3786 arutz un->un_exclopen, partmask); 1323 3786 arutz 1324 3786 arutz if (un->un_exclopen & (partmask)) { 1325 3786 arutz failed_exclusive: 1326 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1327 3786 arutz "exclusive open fails\n"); 1328 3786 arutz rval = EBUSY; 1329 3786 arutz goto done; 1330 3786 arutz } 1331 3786 arutz 1332 3786 arutz if (flag & FEXCL) { 1333 3786 arutz int i; 1334 3786 arutz if (un->un_ocmap.lyropen[part]) { 1335 3786 arutz goto failed_exclusive; 1336 3786 arutz } 1337 3786 arutz for (i = 0; i < (OTYPCNT - 1); i++) { 1338 3786 arutz if (un->un_ocmap.regopen[i] & (partmask)) { 1339 3786 arutz goto failed_exclusive; 1340 3786 arutz } 1341 3786 arutz } 1342 3786 arutz } 1343 3786 arutz if (flag & FWRITE) { 1344 3786 arutz mutex_exit(DCD_MUTEX); 1345 3786 arutz if (dcd_check_wp(dev)) { 1346 3786 arutz sema_v(&un->un_semoclose); 1347 3786 arutz return (EROFS); 1348 3786 arutz } 1349 3786 arutz mutex_enter(DCD_MUTEX); 1350 3786 arutz } 1351 3786 arutz 1352 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1353 3786 arutz "Check Write Protect handled\n"); 1354 3786 arutz 1355 3786 arutz if (!nodelay) { 1356 3786 arutz mutex_exit(DCD_MUTEX); 1357 3786 arutz if ((rval = dcd_ready_and_valid(dev, un)) != 0) { 1358 3786 arutz rval = EIO; 1359 3786 arutz } 1360 3786 arutz (void) pm_idle_component(DCD_DEVINFO, 0); 1361 3786 arutz /* 1362 3786 arutz * Fail if device is not ready or if the number of disk 1363 3786 arutz * blocks is zero or negative for non CD devices. 1364 3786 arutz */ 1365 3786 arutz if (rval || cmlb_partinfo(un->un_dklbhandle, 1366 3786 arutz part, &lblocks, NULL, &partname, NULL, 0) || 1367 3786 arutz lblocks <= 0) { 1368 3786 arutz rval = EIO; 1369 3786 arutz mutex_enter(DCD_MUTEX); 1370 3786 arutz goto done; 1371 3786 arutz } 1372 3786 arutz mutex_enter(DCD_MUTEX); 1373 3786 arutz } 1374 3786 arutz 1375 3786 arutz if (otyp == OTYP_LYR) { 1376 3786 arutz un->un_ocmap.lyropen[part]++; 1377 3786 arutz } else { 1378 3786 arutz un->un_ocmap.regopen[otyp] |= partmask; 1379 3786 arutz } 1380 3786 arutz 1381 3786 arutz /* 1382 3786 arutz * set up open and exclusive open flags 1383 3786 arutz */ 1384 3786 arutz if (flag & FEXCL) { 1385 3786 arutz un->un_exclopen |= (partmask); 1386 3786 arutz } 1387 3786 arutz 1388 3786 arutz 1389 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1390 3786 arutz "open of part %d type %d\n", 1391 3786 arutz part, otyp); 1392 3786 arutz 1393 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1394 3786 arutz "Kstats getting updated\n"); 1395 3786 arutz /* 1396 3786 arutz * only create kstats for disks, CD kstats created in dcdattach 1397 3786 arutz */ 1398 3786 arutz _NOTE(NO_COMPETING_THREADS_NOW); 1399 3786 arutz mutex_exit(DCD_MUTEX); 1400 3786 arutz if (un->un_stats == (kstat_t *)0) { 1401 3786 arutz un->un_stats = kstat_create("dad", instance, 1402 3786 arutz NULL, "disk", KSTAT_TYPE_IO, 1, 1403 3786 arutz KSTAT_FLAG_PERSISTENT); 1404 3786 arutz if (un->un_stats) { 1405 3786 arutz un->un_stats->ks_lock = DCD_MUTEX; 1406 3786 arutz kstat_install(un->un_stats); 1407 3786 arutz } 1408 3786 arutz 1409 3786 arutz /* 1410 3786 arutz * set up partition statistics for each partition 1411 3786 arutz * with number of blocks > 0 1412 3786 arutz */ 1413 3786 arutz if (!nodelay) { 1414 3786 arutz for (i = 0; i < NDKMAP; i++) { 1415 3786 arutz if ((un->un_pstats[i] == (kstat_t *)0) && 1416 3786 arutz (cmlb_partinfo(un->un_dklbhandle, 1417 3786 arutz i, &lblocks, NULL, &partname, 1418 3786 arutz NULL, 0) == 0) && lblocks > 0) { 1419 3786 arutz (void) sprintf(kstatname, "dad%d,%s", 1420 3786 arutz instance, partname); 1421 3786 arutz un->un_pstats[i] = kstat_create("dad", 1422 3786 arutz instance, 1423 3786 arutz kstatname, 1424 3786 arutz "partition", 1425 3786 arutz KSTAT_TYPE_IO, 1426 3786 arutz 1, 1427 3786 arutz KSTAT_FLAG_PERSISTENT); 1428 3786 arutz if (un->un_pstats[i]) { 1429 3786 arutz un->un_pstats[i]->ks_lock = 1430 3786 arutz DCD_MUTEX; 1431 3786 arutz kstat_install(un->un_pstats[i]); 1432 3786 arutz } 1433 3786 arutz } 1434 3786 arutz } 1435 3786 arutz } 1436 3786 arutz /* 1437 3786 arutz * set up error kstats 1438 3786 arutz */ 1439 3786 arutz (void) dcd_create_errstats(un, instance); 1440 3786 arutz } 1441 3786 arutz #ifndef lint 1442 3786 arutz _NOTE(COMPETING_THREADS_NOW); 1443 3786 arutz #endif 1444 3786 arutz 1445 3786 arutz sema_v(&un->un_semoclose); 1446 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "Open success\n"); 1447 3786 arutz return (0); 1448 3786 arutz 1449 3786 arutz done: 1450 3786 arutz mutex_exit(DCD_MUTEX); 1451 3786 arutz sema_v(&un->un_semoclose); 1452 3786 arutz return (rval); 1453 3786 arutz 1454 3786 arutz } 1455 3786 arutz 1456 3786 arutz /* 1457 3786 arutz * Test if disk is ready and has a valid geometry. 1458 3786 arutz */ 1459 3786 arutz static int 1460 3786 arutz dcd_ready_and_valid(dev_t dev, struct dcd_disk *un) 1461 3786 arutz { 1462 3786 arutz int rval = 1; 1463 3786 arutz int g_error = 0; 1464 3786 arutz 1465 3786 arutz mutex_enter(DCD_MUTEX); 1466 3786 arutz /* 1467 3786 arutz * cmds outstanding 1468 3786 arutz */ 1469 3786 arutz if (un->un_ncmds == 0) { 1470 3786 arutz (void) dcd_unit_ready(dev); 1471 3786 arutz } 1472 3786 arutz 1473 3786 arutz /* 1474 3786 arutz * If device is not yet ready here, inform it is offline 1475 3786 arutz */ 1476 3786 arutz if (un->un_state == DCD_STATE_NORMAL) { 1477 3786 arutz rval = dcd_unit_ready(dev); 1478 3786 arutz if (rval != 0 && rval != EACCES) { 1479 3786 arutz dcd_offline(un, 1); 1480 3786 arutz goto done; 1481 3786 arutz } 1482 3786 arutz } 1483 3786 arutz 1484 3786 arutz if (un->un_format_in_progress == 0) { 1485 3786 arutz g_error = dcd_validate_geometry(un); 1486 3786 arutz } 1487 3786 arutz 1488 3786 arutz /* 1489 3786 arutz * check if geometry was valid. We don't check the validity of 1490 3786 arutz * geometry for CDROMS. 1491 3786 arutz */ 1492 3786 arutz 1493 3786 arutz if (g_error == DCD_BAD_LABEL) { 1494 3786 arutz rval = 1; 1495 3786 arutz goto done; 1496 3786 arutz } 1497 3786 arutz 1498 3786 arutz 1499 3786 arutz /* 1500 3786 arutz * the state has changed; inform the media watch routines 1501 3786 arutz */ 1502 3786 arutz un->un_mediastate = DKIO_INSERTED; 1503 3786 arutz cv_broadcast(&un->un_state_cv); 1504 3786 arutz rval = 0; 1505 3786 arutz 1506 3786 arutz done: 1507 3786 arutz mutex_exit(DCD_MUTEX); 1508 3786 arutz return (rval); 1509 3786 arutz } 1510 3786 arutz 1511 3786 arutz 1512 3786 arutz /*ARGSUSED*/ 1513 3786 arutz static int 1514 3786 arutz dcdclose(dev_t dev, int flag, int otyp, cred_t *cred_p) 1515 3786 arutz { 1516 3786 arutz uchar_t *cp; 1517 3786 arutz int i; 1518 3786 arutz 1519 3786 arutz GET_SOFT_STATE(dev); 1520 3786 arutz 1521 3786 arutz 1522 3786 arutz if (otyp >= OTYPCNT) 1523 3786 arutz return (ENXIO); 1524 3786 arutz 1525 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1526 3786 arutz "close of part %d type %d\n", 1527 3786 arutz part, otyp); 1528 3786 arutz sema_p(&un->un_semoclose); 1529 3786 arutz 1530 3786 arutz mutex_enter(DCD_MUTEX); 1531 3786 arutz 1532 3786 arutz if (un->un_exclopen & (1<<part)) { 1533 3786 arutz un->un_exclopen &= ~(1<<part); 1534 3786 arutz } 1535 3786 arutz 1536 3786 arutz if (otyp == OTYP_LYR) { 1537 3786 arutz un->un_ocmap.lyropen[part] -= 1; 1538 3786 arutz } else { 1539 3786 arutz un->un_ocmap.regopen[otyp] &= ~(1<<part); 1540 3786 arutz } 1541 3786 arutz 1542 3786 arutz cp = &un->un_ocmap.chkd[0]; 1543 3786 arutz while (cp < &un->un_ocmap.chkd[OCSIZE]) { 1544 3786 arutz if (*cp != (uchar_t)0) { 1545 3786 arutz break; 1546 3786 arutz } 1547 3786 arutz cp++; 1548 3786 arutz } 1549 3786 arutz 1550 3786 arutz if (cp == &un->un_ocmap.chkd[OCSIZE]) { 1551 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, "last close\n"); 1552 3786 arutz if (un->un_state == DCD_STATE_OFFLINE) { 1553 3786 arutz dcd_offline(un, 1); 1554 3786 arutz } 1555 3786 arutz 1556 3786 arutz mutex_exit(DCD_MUTEX); 1557 3786 arutz (void) cmlb_close(un->un_dklbhandle, 0); 1558 3786 arutz 1559 3786 arutz _NOTE(NO_COMPETING_THREADS_NOW); 1560 3786 arutz if (un->un_stats) { 1561 3786 arutz kstat_delete(un->un_stats); 1562 3786 arutz un->un_stats = 0; 1563 3786 arutz } 1564 3786 arutz for (i = 0; i < NDKMAP; i++) { 1565 3786 arutz if (un->un_pstats[i]) { 1566 3786 arutz kstat_delete(un->un_pstats[i]); 1567 3786 arutz un->un_pstats[i] = (kstat_t *)0; 1568 3786 arutz } 1569 3786 arutz } 1570 3786 arutz 1571 3786 arutz if (un->un_errstats) { 1572 3786 arutz kstat_delete(un->un_errstats); 1573 3786 arutz un->un_errstats = (kstat_t *)0; 1574 3786 arutz } 1575 3786 arutz mutex_enter(DCD_MUTEX); 1576 3786 arutz 1577 3786 arutz #ifndef lint 1578 3786 arutz _NOTE(COMPETING_THREADS_NOW); 1579 3786 arutz #endif 1580 3786 arutz } 1581 3786 arutz 1582 3786 arutz mutex_exit(DCD_MUTEX); 1583 3786 arutz sema_v(&un->un_semoclose); 1584 3786 arutz return (0); 1585 3786 arutz } 1586 3786 arutz 1587 3786 arutz static void 1588 3786 arutz dcd_offline(struct dcd_disk *un, int bechatty) 1589 3786 arutz { 1590 3786 arutz if (bechatty) 1591 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "offline\n"); 1592 3786 arutz 1593 3786 arutz mutex_exit(DCD_MUTEX); 1594 3786 arutz cmlb_invalidate(un->un_dklbhandle, 0); 1595 3786 arutz mutex_enter(DCD_MUTEX); 1596 3786 arutz } 1597 3786 arutz 1598 3786 arutz /* 1599 3786 arutz * Given the device number return the devinfo pointer 1600 3786 arutz * from the scsi_device structure. 1601 3786 arutz */ 1602 3786 arutz /*ARGSUSED*/ 1603 3786 arutz static int 1604 3786 arutz dcdinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 1605 3786 arutz { 1606 3786 arutz dev_t dev; 1607 3786 arutz struct dcd_disk *un; 1608 3786 arutz int instance, error; 1609 3786 arutz 1610 3786 arutz 1611 3786 arutz switch (infocmd) { 1612 3786 arutz case DDI_INFO_DEVT2DEVINFO: 1613 3786 arutz dev = (dev_t)arg; 1614 3786 arutz instance = DCDUNIT(dev); 1615 3786 arutz if ((un = ddi_get_soft_state(dcd_state, instance)) == NULL) 1616 3786 arutz return (DDI_FAILURE); 1617 3786 arutz *result = (void *) DCD_DEVINFO; 1618 3786 arutz error = DDI_SUCCESS; 1619 3786 arutz break; 1620 3786 arutz case DDI_INFO_DEVT2INSTANCE: 1621 3786 arutz dev = (dev_t)arg; 1622 3786 arutz instance = DCDUNIT(dev); 1623 3786 arutz *result = (void *)(uintptr_t)instance; 1624 3786 arutz error = DDI_SUCCESS; 1625 3786 arutz break; 1626 3786 arutz default: 1627 3786 arutz error = DDI_FAILURE; 1628 3786 arutz } 1629 3786 arutz return (error); 1630 3786 arutz } 1631 3786 arutz 1632 3786 arutz /* 1633 3786 arutz * property operation routine. return the number of blocks for the partition 1634 3786 arutz * in question or forward the request to the propery facilities. 1635 3786 arutz */ 1636 3786 arutz static int 1637 3786 arutz dcd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1638 3786 arutz char *name, caddr_t valuep, int *lengthp) 1639 3786 arutz { 1640 3786 arutz struct dcd_disk *un; 1641 7224 cth 1642 7224 cth if ((un = ddi_get_soft_state(dcd_state, ddi_get_instance(dip))) == NULL) 1643 3786 arutz return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1644 3786 arutz name, valuep, lengthp)); 1645 7224 cth 1646 7224 cth return (cmlb_prop_op(un->un_dklbhandle, 1647 7224 cth dev, dip, prop_op, mod_flags, name, valuep, lengthp, 1648 7224 cth DCDPART(dev), NULL)); 1649 3786 arutz } 1650 3786 arutz 1651 3786 arutz /* 1652 3786 arutz * These routines perform raw i/o operations. 1653 3786 arutz */ 1654 3786 arutz /*ARGSUSED*/ 1655 3786 arutz void 1656 3786 arutz dcduscsimin(struct buf *bp) 1657 3786 arutz { 1658 3786 arutz 1659 3786 arutz } 1660 3786 arutz 1661 3786 arutz 1662 3786 arutz static void 1663 3786 arutz dcdmin(struct buf *bp) 1664 3786 arutz { 1665 3786 arutz struct dcd_disk *un; 1666 3786 arutz int instance; 1667 3786 arutz minor_t minor = getminor(bp->b_edev); 1668 3786 arutz instance = minor >> DCDUNIT_SHIFT; 1669 3786 arutz un = ddi_get_soft_state(dcd_state, instance); 1670 3786 arutz 1671 3786 arutz if (bp->b_bcount > un->un_max_xfer_size) 1672 3786 arutz bp->b_bcount = un->un_max_xfer_size; 1673 3786 arutz } 1674 3786 arutz 1675 3786 arutz 1676 3786 arutz /* ARGSUSED2 */ 1677 3786 arutz static int 1678 3786 arutz dcdread(dev_t dev, struct uio *uio, cred_t *cred_p) 1679 3786 arutz { 1680 3786 arutz int secmask; 1681 3786 arutz GET_SOFT_STATE(dev); 1682 3786 arutz #ifdef lint 1683 3786 arutz part = part; 1684 3786 arutz #endif /* lint */ 1685 3786 arutz secmask = un->un_secsize - 1; 1686 3786 arutz 1687 3786 arutz if (uio->uio_loffset & ((offset_t)(secmask))) { 1688 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1689 3786 arutz "file offset not modulo %d\n", 1690 3786 arutz un->un_secsize); 1691 3786 arutz return (EINVAL); 1692 3786 arutz } else if (uio->uio_iov->iov_len & (secmask)) { 1693 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1694 3786 arutz "transfer length not modulo %d\n", un->un_secsize); 1695 3786 arutz return (EINVAL); 1696 3786 arutz } 1697 3786 arutz return (physio(dcdstrategy, (struct buf *)0, dev, B_READ, dcdmin, uio)); 1698 3786 arutz } 1699 3786 arutz 1700 3786 arutz /* ARGSUSED2 */ 1701 3786 arutz static int 1702 3786 arutz dcdaread(dev_t dev, struct aio_req *aio, cred_t *cred_p) 1703 3786 arutz { 1704 3786 arutz int secmask; 1705 3786 arutz struct uio *uio = aio->aio_uio; 1706 3786 arutz GET_SOFT_STATE(dev); 1707 3786 arutz #ifdef lint 1708 3786 arutz part = part; 1709 3786 arutz #endif /* lint */ 1710 3786 arutz secmask = un->un_secsize - 1; 1711 3786 arutz 1712 3786 arutz if (uio->uio_loffset & ((offset_t)(secmask))) { 1713 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1714 3786 arutz "file offset not modulo %d\n", 1715 3786 arutz un->un_secsize); 1716 3786 arutz return (EINVAL); 1717 3786 arutz } else if (uio->uio_iov->iov_len & (secmask)) { 1718 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1719 3786 arutz "transfer length not modulo %d\n", un->un_secsize); 1720 3786 arutz return (EINVAL); 1721 3786 arutz } 1722 3786 arutz return (aphysio(dcdstrategy, anocancel, dev, B_READ, dcdmin, aio)); 1723 3786 arutz } 1724 3786 arutz 1725 3786 arutz /* ARGSUSED2 */ 1726 3786 arutz static int 1727 3786 arutz dcdwrite(dev_t dev, struct uio *uio, cred_t *cred_p) 1728 3786 arutz { 1729 3786 arutz int secmask; 1730 3786 arutz GET_SOFT_STATE(dev); 1731 3786 arutz #ifdef lint 1732 3786 arutz part = part; 1733 3786 arutz #endif /* lint */ 1734 3786 arutz secmask = un->un_secsize - 1; 1735 3786 arutz 1736 3786 arutz if (uio->uio_loffset & ((offset_t)(secmask))) { 1737 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1738 3786 arutz "file offset not modulo %d\n", 1739 3786 arutz un->un_secsize); 1740 3786 arutz return (EINVAL); 1741 3786 arutz } else if (uio->uio_iov->iov_len & (secmask)) { 1742 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1743 3786 arutz "transfer length not modulo %d\n", un->un_secsize); 1744 3786 arutz return (EINVAL); 1745 3786 arutz } 1746 3786 arutz return (physio(dcdstrategy, (struct buf *)0, dev, B_WRITE, dcdmin, 1747 3786 arutz uio)); 1748 3786 arutz } 1749 3786 arutz 1750 3786 arutz /* ARGSUSED2 */ 1751 3786 arutz static int 1752 3786 arutz dcdawrite(dev_t dev, struct aio_req *aio, cred_t *cred_p) 1753 3786 arutz { 1754 3786 arutz int secmask; 1755 3786 arutz struct uio *uio = aio->aio_uio; 1756 3786 arutz GET_SOFT_STATE(dev); 1757 3786 arutz #ifdef lint 1758 3786 arutz part = part; 1759 3786 arutz #endif /* lint */ 1760 3786 arutz secmask = un->un_secsize - 1; 1761 3786 arutz 1762 3786 arutz if (uio->uio_loffset & ((offset_t)(secmask))) { 1763 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1764 3786 arutz "file offset not modulo %d\n", 1765 3786 arutz un->un_secsize); 1766 3786 arutz return (EINVAL); 1767 3786 arutz } else if (uio->uio_iov->iov_len & (secmask)) { 1768 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1769 3786 arutz "transfer length not modulo %d\n", un->un_secsize); 1770 3786 arutz return (EINVAL); 1771 3786 arutz } 1772 3786 arutz return (aphysio(dcdstrategy, anocancel, dev, B_WRITE, dcdmin, aio)); 1773 3786 arutz } 1774 3786 arutz 1775 3786 arutz /* 1776 3786 arutz * strategy routine 1777 3786 arutz */ 1778 3786 arutz static int 1779 3786 arutz dcdstrategy(struct buf *bp) 1780 3786 arutz { 1781 3786 arutz struct dcd_disk *un; 1782 3786 arutz struct diskhd *dp; 1783 3786 arutz int i; 1784 3786 arutz minor_t minor = getminor(bp->b_edev); 1785 3786 arutz diskaddr_t p_lblksrt; 1786 3786 arutz diskaddr_t lblocks; 1787 3786 arutz diskaddr_t bn; 1788 3786 arutz 1789 3786 arutz if ((un = ddi_get_soft_state(dcd_state, 1790 3786 arutz minor >> DCDUNIT_SHIFT)) == NULL || 1791 3786 arutz un->un_state == DCD_STATE_DUMPING || 1792 3786 arutz ((un->un_state & DCD_STATE_FATAL) == DCD_STATE_FATAL)) { 1793 3786 arutz SET_BP_ERROR(bp, ((un) ? ENXIO : EIO)); 1794 3786 arutz error: 1795 3786 arutz bp->b_resid = bp->b_bcount; 1796 3786 arutz biodone(bp); 1797 3786 arutz return (0); 1798 3786 arutz } 1799 3786 arutz 1800 3786 arutz /* 1801 3786 arutz * If the request size (buf->b_bcount)is greater than the size 1802 3786 arutz * (un->un_max_xfer_size) supported by the target driver fail 1803 3786 arutz * the request with EINVAL error code. 1804 3786 arutz * 1805 3786 arutz * We are not supposed to receive requests exceeding 1806 3786 arutz * un->un_max_xfer_size size because the caller is expected to 1807 3786 arutz * check what is the maximum size that is supported by this 1808 3786 arutz * driver either through ioctl or dcdmin routine(which is private 1809 3786 arutz * to this driver). 1810 3786 arutz * But we have seen cases (like meta driver(md))where dcdstrategy 1811 3786 arutz * called with more than supported size and cause data corruption. 1812 3786 arutz */ 1813 3786 arutz 1814 3786 arutz if (bp->b_bcount > un->un_max_xfer_size) { 1815 3786 arutz SET_BP_ERROR(bp, EINVAL); 1816 3786 arutz goto error; 1817 3786 arutz } 1818 3786 arutz 1819 3786 arutz TRACE_2(TR_FAC_DADA, TR_DCDSTRATEGY_START, 1820 3786 arutz "dcdstrategy_start: bp 0x%p un 0x%p", bp, un); 1821 3786 arutz 1822 3786 arutz /* 1823 3786 arutz * Commands may sneak in while we released the mutex in 1824 3786 arutz * DDI_SUSPEND, we should block new commands. 1825 3786 arutz */ 1826 3786 arutz mutex_enter(DCD_MUTEX); 1827 3786 arutz while (un->un_state == DCD_STATE_SUSPENDED) { 1828 3786 arutz cv_wait(&un->un_suspend_cv, DCD_MUTEX); 1829 3786 arutz } 1830 3786 arutz 1831 3786 arutz if (un->un_state == DCD_STATE_PM_SUSPENDED) { 1832 3786 arutz mutex_exit(DCD_MUTEX); 1833 3786 arutz (void) pm_idle_component(DCD_DEVINFO, 0); 1834 3786 arutz if (pm_raise_power(DCD_DEVINFO, 0, 1835 7224 cth DCD_DEVICE_ACTIVE) != DDI_SUCCESS) { 1836 3786 arutz SET_BP_ERROR(bp, EIO); 1837 3786 arutz goto error; 1838 3786 arutz } 1839 3786 arutz mutex_enter(DCD_MUTEX); 1840 3786 arutz } 1841 3786 arutz mutex_exit(DCD_MUTEX); 1842 3786 arutz 1843 3786 arutz /* 1844 3786 arutz * Map-in the buffer in case starting address is not word aligned. 1845 3786 arutz */ 1846 3786 arutz 1847 3786 arutz if (((uintptr_t)bp->b_un.b_addr) & 0x1) 1848 3786 arutz bp_mapin(bp); 1849 3786 arutz 1850 3786 arutz bp->b_flags &= ~(B_DONE|B_ERROR); 1851 3786 arutz bp->b_resid = 0; 1852 3786 arutz bp->av_forw = 0; 1853 3786 arutz 1854 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1855 3786 arutz "bp->b_bcount %lx\n", bp->b_bcount); 1856 3786 arutz 1857 3786 arutz if (bp != un->un_sbufp) { 1858 3786 arutz validated: if (cmlb_partinfo(un->un_dklbhandle, 1859 3786 arutz minor & DCDPART_MASK, 1860 3786 arutz &lblocks, 1861 3786 arutz &p_lblksrt, 1862 3786 arutz NULL, 1863 3786 arutz NULL, 1864 3786 arutz 0) == 0) { 1865 3786 arutz 1866 3786 arutz bn = dkblock(bp); 1867 3786 arutz 1868 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1869 3786 arutz "dkblock(bp) is %llu\n", bn); 1870 3786 arutz 1871 3786 arutz i = 0; 1872 3786 arutz if (bn < 0) { 1873 3786 arutz i = -1; 1874 3786 arutz } else if (bn >= lblocks) { 1875 3786 arutz /* 1876 3786 arutz * For proper comparison, file system block 1877 3786 arutz * number has to be scaled to actual CD 1878 3786 arutz * transfer size. 1879 3786 arutz * Since all the CDROM operations 1880 3786 arutz * that have Sun Labels are in the correct 1881 3786 arutz * block size this will work for CD's. This 1882 3786 arutz * will have to change when we have different 1883 3786 arutz * sector sizes. 1884 3786 arutz * 1885 3786 arutz * if bn == lblocks, 1886 3786 arutz * Not an error, resid == count 1887 3786 arutz */ 1888 3786 arutz if (bn > lblocks) { 1889 3786 arutz i = -1; 1890 3786 arutz } else { 1891 3786 arutz i = 1; 1892 3786 arutz } 1893 3786 arutz } else if (bp->b_bcount & (un->un_secsize-1)) { 1894 3786 arutz /* 1895 3786 arutz * This should really be: 1896 3786 arutz * 1897 3786 arutz * ... if (bp->b_bcount & (un->un_lbasize-1)) 1898 3786 arutz * 1899 3786 arutz */ 1900 3786 arutz i = -1; 1901 3786 arutz } else { 1902 3786 arutz if (!bp->b_bcount) { 1903 3786 arutz printf("Waring : Zero read or Write\n"); 1904 3786 arutz goto error; 1905 3786 arutz } 1906 3786 arutz /* 1907 3786 arutz * sort by absolute block number. 1908 3786 arutz */ 1909 3786 arutz bp->b_resid = bn; 1910 3786 arutz bp->b_resid += p_lblksrt; 1911 3786 arutz /* 1912 3786 arutz * zero out av_back - this will be a signal 1913 3786 arutz * to dcdstart to go and fetch the resources 1914 3786 arutz */ 1915 3786 arutz bp->av_back = NO_PKT_ALLOCATED; 1916 3786 arutz } 1917 3786 arutz 1918 3786 arutz /* 1919 3786 arutz * Check to see whether or not we are done 1920 3786 arutz * (with or without errors). 1921 3786 arutz */ 1922 3786 arutz 1923 3786 arutz if (i != 0) { 1924 3786 arutz if (i < 0) { 1925 3786 arutz bp->b_flags |= B_ERROR; 1926 3786 arutz } 1927 3786 arutz goto error; 1928 3786 arutz } 1929 3786 arutz } else { 1930 3786 arutz /* 1931 3786 arutz * opened in NDELAY/NONBLOCK mode? 1932 3786 arutz * Check if disk is ready and has a valid geometry 1933 3786 arutz */ 1934 3786 arutz if (dcd_ready_and_valid(bp->b_edev, un) == 0) { 1935 3786 arutz goto validated; 1936 3786 arutz } else { 1937 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 1938 3786 arutz "i/o to invalid geometry\n"); 1939 3786 arutz SET_BP_ERROR(bp, EIO); 1940 3786 arutz goto error; 1941 3786 arutz } 1942 3786 arutz } 1943 3786 arutz } else if (BP_HAS_NO_PKT(bp)) { 1944 3786 arutz struct udcd_cmd *tscmdp; 1945 3786 arutz struct dcd_cmd *tcmdp; 1946 3786 arutz /* 1947 3786 arutz * This indicates that it is a special buffer 1948 3786 arutz * This could be a udcd-cmd and hence call bp_mapin just 1949 3786 arutz * in case that it could be a PIO command issued. 1950 3786 arutz */ 1951 3786 arutz tscmdp = (struct udcd_cmd *)bp->b_forw; 1952 3786 arutz tcmdp = tscmdp->udcd_cmd; 1953 3786 arutz if ((tcmdp->cmd != ATA_READ_DMA) && (tcmdp->cmd != 0xc9) && 1954 3786 arutz (tcmdp->cmd != ATA_WRITE_DMA) && (tcmdp->cmd != 0xcb) && 1955 3786 arutz (tcmdp->cmd != IDENTIFY_DMA) && 1956 3786 arutz (tcmdp->cmd != ATA_FLUSH_CACHE)) { 1957 3786 arutz bp_mapin(bp); 1958 3786 arutz } 1959 3786 arutz } 1960 3786 arutz 1961 3786 arutz /* 1962 3786 arutz * We are doing it a bit non-standard. That is, the 1963 3786 arutz * head of the b_actf chain is *not* the active command- 1964 3786 arutz * it is just the head of the wait queue. The reason 1965 3786 arutz * we do this is that the head of the b_actf chain is 1966 3786 arutz * guaranteed to not be moved by disksort(), so that 1967 3786 arutz * our restart command (pointed to by 1968 3786 arutz * b_forw) and the head of the wait queue (b_actf) can 1969 3786 arutz * have resources granted without it getting lost in 1970 3786 arutz * the queue at some later point (where we would have 1971 3786 arutz * to go and look for it). 1972 3786 arutz */ 1973 3786 arutz mutex_enter(DCD_MUTEX); 1974 3786 arutz 1975 3786 arutz DCD_DO_KSTATS(un, kstat_waitq_enter, bp); 1976 3786 arutz 1977 3786 arutz dp = &un->un_utab; 1978 3786 arutz 1979 3786 arutz if (dp->b_actf == NULL) { 1980 3786 arutz dp->b_actf = bp; 1981 3786 arutz dp->b_actl = bp; 1982 3786 arutz } else if ((un->un_state == DCD_STATE_SUSPENDED) && 1983 3786 arutz bp == un->un_sbufp) { 1984 3786 arutz bp->b_actf = dp->b_actf; 1985 3786 arutz dp->b_actf = bp; 1986 3786 arutz } else { 1987 3786 arutz TRACE_3(TR_FAC_DADA, TR_DCDSTRATEGY_DISKSORT_START, 1988 3786 arutz "dcdstrategy_disksort_start: dp 0x%p bp 0x%p un 0x%p", 1989 3786 arutz dp, bp, un); 1990 3786 arutz disksort(dp, bp); 1991 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_DISKSORT_END, 1992 3786 arutz "dcdstrategy_disksort_end"); 1993 3786 arutz } 1994 3786 arutz 1995 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 1996 3786 arutz "ncmd %x , throttle %x, forw 0x%p\n", 1997 3786 arutz un->un_ncmds, un->un_throttle, (void *)dp->b_forw); 1998 3786 arutz ASSERT(un->un_ncmds >= 0); 1999 3786 arutz ASSERT(un->un_throttle >= 0); 2000 3786 arutz if ((un->un_ncmds < un->un_throttle) && (dp->b_forw == NULL)) { 2001 3786 arutz dcdstart(un); 2002 3786 arutz } else if (BP_HAS_NO_PKT(dp->b_actf)) { 2003 3786 arutz struct buf *cmd_bp; 2004 3786 arutz 2005 3786 arutz cmd_bp = dp->b_actf; 2006 3786 arutz cmd_bp->av_back = ALLOCATING_PKT; 2007 3786 arutz mutex_exit(DCD_MUTEX); 2008 3786 arutz /* 2009 3786 arutz * try and map this one 2010 3786 arutz */ 2011 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_SMALL_WINDOW_START, 2012 3786 arutz "dcdstrategy_small_window_call (begin)"); 2013 3786 arutz 2014 3786 arutz make_dcd_cmd(un, cmd_bp, NULL_FUNC); 2015 3786 arutz 2016 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_SMALL_WINDOW_END, 2017 3786 arutz "dcdstrategy_small_window_call (end)"); 2018 3786 arutz 2019 3786 arutz /* 2020 3786 arutz * there is a small window where the active cmd 2021 3786 arutz * completes before make_dcd_cmd returns. 2022 3786 arutz * consequently, this cmd never gets started so 2023 3786 arutz * we start it from here 2024 3786 arutz */ 2025 3786 arutz mutex_enter(DCD_MUTEX); 2026 3786 arutz if ((un->un_ncmds < un->un_throttle) && 2027 3786 arutz (dp->b_forw == NULL)) { 2028 3786 arutz dcdstart(un); 2029 3786 arutz } 2030 3786 arutz } 2031 3786 arutz mutex_exit(DCD_MUTEX); 2032 3786 arutz 2033 3786 arutz done: 2034 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTRATEGY_END, "dcdstrategy_end"); 2035 3786 arutz return (0); 2036 3786 arutz } 2037 3786 arutz 2038 3786 arutz 2039 3786 arutz /* 2040 3786 arutz * Unit start and Completion 2041 3786 arutz * NOTE: we assume that the caller has at least checked for: 2042 3786 arutz * (un->un_ncmds < un->un_throttle) 2043 3786 arutz * if not, there is no real harm done, dcd_transport() will 2044 3786 arutz * return BUSY 2045 3786 arutz */ 2046 3786 arutz static void 2047 3786 arutz dcdstart(struct dcd_disk *un) 2048 3786 arutz { 2049 3786 arutz int status, sort_key; 2050 3786 arutz struct buf *bp; 2051 3786 arutz struct diskhd *dp; 2052 3786 arutz uchar_t state = un->un_last_state; 2053 3786 arutz 2054 3786 arutz TRACE_1(TR_FAC_DADA, TR_DCDSTART_START, "dcdstart_start: un 0x%p", un); 2055 3786 arutz 2056 3786 arutz retry: 2057 3786 arutz ASSERT(mutex_owned(DCD_MUTEX)); 2058 3786 arutz 2059 3786 arutz dp = &un->un_utab; 2060 3786 arutz if (((bp = dp->b_actf) == NULL) || (bp->av_back == ALLOCATING_PKT) || 2061 3786 arutz (dp->b_forw != NULL)) { 2062 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTART_NO_WORK_END, 2063 3786 arutz "dcdstart_end (no work)"); 2064 3786 arutz return; 2065 3786 arutz } 2066 3786 arutz 2067 3786 arutz /* 2068 3786 arutz * remove from active queue 2069 3786 arutz */ 2070 3786 arutz dp->b_actf = bp->b_actf; 2071 3786 arutz bp->b_actf = 0; 2072 3786 arutz 2073 3786 arutz /* 2074 3786 arutz * increment ncmds before calling dcd_transport because dcdintr 2075 3786 arutz * may be called before we return from dcd_transport! 2076 3786 arutz */ 2077 3786 arutz un->un_ncmds++; 2078 3786 arutz 2079 3786 arutz /* 2080 3786 arutz * If measuring stats, mark exit from wait queue and 2081 3786 arutz * entrance into run 'queue' if and only if we are 2082 3786 arutz * going to actually start a command. 2083 3786 arutz * Normally the bp already has a packet at this point 2084 3786 arutz */ 2085 3786 arutz DCD_DO_KSTATS(un, kstat_waitq_to_runq, bp); 2086 3786 arutz 2087 3786 arutz mutex_exit(DCD_MUTEX); 2088 3786 arutz 2089 3786 arutz if (BP_HAS_NO_PKT(bp)) { 2090 3786 arutz make_dcd_cmd(un, bp, dcdrunout); 2091 3786 arutz if (BP_HAS_NO_PKT(bp) && !(bp->b_flags & B_ERROR)) { 2092 3786 arutz mutex_enter(DCD_MUTEX); 2093 3786 arutz DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp); 2094 3786 arutz 2095 3786 arutz bp->b_actf = dp->b_actf; 2096 3786 arutz dp->b_actf = bp; 2097 3786 arutz New_state(un, DCD_STATE_RWAIT); 2098 3786 arutz un->un_ncmds--; 2099 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTART_NO_RESOURCES_END, 2100 3786 arutz "dcdstart_end (No Resources)"); 2101 3786 arutz goto done; 2102 3786 arutz 2103 3786 arutz } else if (bp->b_flags & B_ERROR) { 2104 3786 arutz mutex_enter(DCD_MUTEX); 2105 3786 arutz DCD_DO_KSTATS(un, kstat_runq_exit, bp); 2106 3786 arutz 2107 3786 arutz un->un_ncmds--; 2108 3786 arutz bp->b_resid = bp->b_bcount; 2109 3786 arutz if (bp->b_error == 0) { 2110 3786 arutz SET_BP_ERROR(bp, EIO); 2111 3786 arutz } 2112 3786 arutz 2113 3786 arutz /* 2114 3786 arutz * restore old state 2115 3786 arutz */ 2116 3786 arutz un->un_state = un->un_last_state; 2117 3786 arutz un->un_last_state = state; 2118 3786 arutz 2119 3786 arutz mutex_exit(DCD_MUTEX); 2120 3786 arutz 2121 3786 arutz biodone(bp); 2122 3786 arutz mutex_enter(DCD_MUTEX); 2123 3786 arutz if (un->un_state == DCD_STATE_SUSPENDED) { 2124 3786 arutz cv_broadcast(&un->un_disk_busy_cv); 2125 3786 arutz } 2126 3786 arutz 2127 3786 arutz if ((un->un_ncmds < un->un_throttle) && 2128 3786 arutz (dp->b_forw == NULL)) { 2129 3786 arutz goto retry; 2130 3786 arutz } else { 2131 3786 arutz goto done; 2132 3786 arutz } 2133 3786 arutz } 2134 3786 arutz } 2135 3786 arutz 2136 3786 arutz /* 2137 3786 arutz * Restore resid from the packet, b_resid had been the 2138 3786 arutz * disksort key. 2139 3786 arutz */ 2140 3786 arutz sort_key = bp->b_resid; 2141 3786 arutz bp->b_resid = BP_PKT(bp)->pkt_resid; 2142 3786 arutz BP_PKT(bp)->pkt_resid = 0; 2143 3786 arutz 2144 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2145 3786 arutz "bp->b_resid %lx, pkt_resid %lx\n", 2146 3786 arutz bp->b_resid, BP_PKT(bp)->pkt_resid); 2147 3786 arutz 2148 3786 arutz /* 2149 3786 arutz * We used to check whether or not to try and link commands here. 2150 3786 arutz * Since we have found that there is no performance improvement 2151 3786 arutz * for linked commands, this has not made much sense. 2152 3786 arutz */ 2153 3786 arutz if ((status = dcd_transport((struct dcd_pkt *)BP_PKT(bp))) 2154 3786 arutz != TRAN_ACCEPT) { 2155 3786 arutz mutex_enter(DCD_MUTEX); 2156 3786 arutz un->un_ncmds--; 2157 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2158 3786 arutz "transport returned %x\n", status); 2159 3786 arutz if (status == TRAN_BUSY) { 2160 3786 arutz DCD_DO_ERRSTATS(un, dcd_transerrs); 2161 3786 arutz DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp); 2162 3786 arutz dcd_handle_tran_busy(bp, dp, un); 2163 3786 arutz if (un->un_ncmds > 0) { 2164 3786 arutz bp->b_resid = sort_key; 2165 3786 arutz } 2166 3786 arutz } else { 2167 3786 arutz DCD_DO_KSTATS(un, kstat_runq_exit, bp); 2168 3786 arutz mutex_exit(DCD_MUTEX); 2169 3786 arutz 2170 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2171 3786 arutz "transport rejected (%d)\n", 2172 3786 arutz status); 2173 3786 arutz SET_BP_ERROR(bp, EIO); 2174 3786 arutz bp->b_resid = bp->b_bcount; 2175 3786 arutz if (bp != un->un_sbufp) { 2176 3786 arutz dcd_destroy_pkt(BP_PKT(bp)); 2177 3786 arutz } 2178 3786 arutz biodone(bp); 2179 3786 arutz 2180 3786 arutz mutex_enter(DCD_MUTEX); 2181 3786 arutz if (un->un_state == DCD_STATE_SUSPENDED) { 2182 3786 arutz cv_broadcast(&un->un_disk_busy_cv); 2183 3786 arutz } 2184 3786 arutz if ((un->un_ncmds < un->un_throttle) && 2185 3786 arutz (dp->b_forw == NULL)) { 2186 3786 arutz goto retry; 2187 3786 arutz } 2188 3786 arutz } 2189 3786 arutz } else { 2190 3786 arutz mutex_enter(DCD_MUTEX); 2191 3786 arutz 2192 3786 arutz if (dp->b_actf && BP_HAS_NO_PKT(dp->b_actf)) { 2193 3786 arutz struct buf *cmd_bp; 2194 3786 arutz 2195 3786 arutz cmd_bp = dp->b_actf; 2196 3786 arutz cmd_bp->av_back = ALLOCATING_PKT; 2197 3786 arutz mutex_exit(DCD_MUTEX); 2198 3786 arutz /* 2199 3786 arutz * try and map this one 2200 3786 arutz */ 2201 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCASTART_SMALL_WINDOW_START, 2202 3786 arutz "dcdstart_small_window_start"); 2203 3786 arutz 2204 3786 arutz make_dcd_cmd(un, cmd_bp, NULL_FUNC); 2205 3786 arutz 2206 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTART_SMALL_WINDOW_END, 2207 3786 arutz "dcdstart_small_window_end"); 2208 3786 arutz /* 2209 3786 arutz * there is a small window where the active cmd 2210 3786 arutz * completes before make_dcd_cmd returns. 2211 3786 arutz * consequently, this cmd never gets started so 2212 3786 arutz * we start it from here 2213 3786 arutz */ 2214 3786 arutz mutex_enter(DCD_MUTEX); 2215 3786 arutz if ((un->un_ncmds < un->un_throttle) && 2216 3786 arutz (dp->b_forw == NULL)) { 2217 3786 arutz goto retry; 2218 3786 arutz } 2219 3786 arutz } 2220 3786 arutz } 2221 3786 arutz 2222 3786 arutz done: 2223 3786 arutz ASSERT(mutex_owned(DCD_MUTEX)); 2224 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDSTART_END, "dcdstart_end"); 2225 3786 arutz } 2226 3786 arutz 2227 3786 arutz /* 2228 3786 arutz * make_dcd_cmd: create a pkt 2229 3786 arutz */ 2230 3786 arutz static void 2231 3786 arutz make_dcd_cmd(struct dcd_disk *un, struct buf *bp, int (*func)()) 2232 3786 arutz { 2233 3786 arutz auto int count, com, direction; 2234 3786 arutz struct dcd_pkt *pkt; 2235 3786 arutz int flags, tval; 2236 3786 arutz 2237 3786 arutz _NOTE(DATA_READABLE_WITHOUT_LOCK(dcd_disk::un_dp)) 2238 3786 arutz TRACE_3(TR_FAC_DADA, TR_MAKE_DCD_CMD_START, 2239 3786 arutz "make_dcd_cmd_start: un 0x%p bp 0x%p un 0x%p", un, bp, un); 2240 3786 arutz 2241 3786 arutz 2242 3786 arutz flags = un->un_cmd_flags; 2243 3786 arutz 2244 3786 arutz if (bp != un->un_sbufp) { 2245 3786 arutz int partition = DCDPART(bp->b_edev); 2246 3786 arutz diskaddr_t p_lblksrt; 2247 3786 arutz diskaddr_t lblocks; 2248 3786 arutz long secnt; 2249 3786 arutz uint32_t blkno; 2250 3786 arutz int dkl_nblk, delta; 2251 3786 arutz long resid; 2252 3786 arutz 2253 3786 arutz if (cmlb_partinfo(un->un_dklbhandle, 2254 3786 arutz partition, 2255 3786 arutz &lblocks, 2256 3786 arutz &p_lblksrt, 2257 3786 arutz NULL, 2258 3786 arutz NULL, 2259 3786 arutz 0) != NULL) { 2260 3786 arutz lblocks = 0; 2261 3786 arutz p_lblksrt = 0; 2262 3786 arutz } 2263 3786 arutz 2264 3786 arutz dkl_nblk = (int)lblocks; 2265 3786 arutz 2266 3786 arutz /* 2267 3786 arutz * Make sure we don't run off the end of a partition. 2268 3786 arutz * 2269 3786 arutz * Put this test here so that we can adjust b_count 2270 3786 arutz * to accurately reflect the actual amount we are 2271 3786 arutz * goint to transfer. 2272 3786 arutz */ 2273 3786 arutz 2274 3786 arutz /* 2275 3786 arutz * First, compute partition-relative block number 2276 3786 arutz */ 2277 3786 arutz blkno = dkblock(bp); 2278 3786 arutz secnt = (bp->b_bcount + (un->un_secsize - 1)) >> un->un_secdiv; 2279 3786 arutz count = MIN(secnt, dkl_nblk - blkno); 2280 3786 arutz if (count != secnt) { 2281 3786 arutz /* 2282 3786 arutz * We have an overrun 2283 3786 arutz */ 2284 3786 arutz resid = (secnt - count) << un->un_secdiv; 2285 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2286 3786 arutz "overrun by %ld sectors\n", 2287 3786 arutz secnt - count); 2288 3786 arutz bp->b_bcount -= resid; 2289 3786 arutz } else { 2290 3786 arutz resid = 0; 2291 3786 arutz } 2292 3786 arutz 2293 3786 arutz /* 2294 3786 arutz * Adjust block number to absolute 2295 3786 arutz */ 2296 3786 arutz delta = (int)p_lblksrt; 2297 3786 arutz blkno += delta; 2298 3786 arutz 2299 3786 arutz mutex_enter(DCD_MUTEX); 2300 3786 arutz /* 2301 3786 arutz * This is for devices having block size different from 2302 3786 arutz * from DEV_BSIZE (e.g. 2K CDROMs). 2303 3786 arutz */ 2304 3786 arutz if (un->un_lbasize != un->un_secsize) { 2305 3786 arutz blkno >>= un->un_blknoshift; 2306 3786 arutz count >>= un->un_blknoshift; 2307 3786 arutz } 2308 3786 arutz mutex_exit(DCD_MUTEX); 2309 3786 arutz 2310 3786 arutz TRACE_0(TR_FAC_DADA, TR_MAKE_DCD_CMD_INIT_PKT_START, 2311 3786 arutz "make_dcd_cmd_init_pkt_call (begin)"); 2312 3786 arutz pkt = dcd_init_pkt(ROUTE, NULL, bp, 2313 3786 arutz (uint32_t)sizeof (struct dcd_cmd), 2314 3786 arutz un->un_cmd_stat_size, PP_LEN, PKT_CONSISTENT, 2315 3786 arutz func, (caddr_t)un); 2316 3786 arutz TRACE_1(TR_FAC_DADA, TR_MAKE_DCD_CMD_INIT_PKT_END, 2317 3786 arutz "make_dcd_cmd_init_pkt_call (end): pkt 0x%p", pkt); 2318 3786 arutz if (!pkt) { 2319 3786 arutz bp->b_bcount += resid; 2320 3786 arutz bp->av_back = NO_PKT_ALLOCATED; 2321 3786 arutz TRACE_0(TR_FAC_DADA, 2322 3786 arutz TR_MAKE_DCD_CMD_NO_PKT_ALLOCATED1_END, 2323 3786 arutz "make_dcd_cmd_end (NO_PKT_ALLOCATED1)"); 2324 3786 arutz return; 2325 3786 arutz } 2326 3786 arutz if (bp->b_flags & B_READ) { 2327 3786 arutz if ((un->un_dp->options & DMA_SUPPORTTED) == 2328 3786 arutz DMA_SUPPORTTED) { 2329 3786 arutz com = ATA_READ_DMA; 2330 3786 arutz } else { 2331 3786 arutz if (un->un_dp->options & BLOCK_MODE) 2332 3786 arutz com = ATA_READ_MULTIPLE; 2333 3786 arutz else 2334 3786 arutz com = ATA_READ; 2335 3786 arutz } 2336 3786 arutz direction = DATA_READ; 2337 3786 arutz } else { 2338 3786 arutz if ((un->un_dp->options & DMA_SUPPORTTED) == 2339 3786 arutz DMA_SUPPORTTED) { 2340 3786 arutz com = ATA_WRITE_DMA; 2341 3786 arutz } else { 2342 3786 arutz if (un->un_dp->options & BLOCK_MODE) 2343 3786 arutz com = ATA_WRITE_MULTIPLE; 2344 3786 arutz else 2345 3786 arutz com = ATA_WRITE; 2346 3786 arutz } 2347 3786 arutz direction = DATA_WRITE; 2348 3786 arutz } 2349 3786 arutz 2350 3786 arutz /* 2351 3786 arutz * Save the resid in the packet, temporarily until 2352 3786 arutz * we transport the command. 2353 3786 arutz */ 2354 3786 arutz pkt->pkt_resid = resid; 2355 3786 arutz 2356 3786 arutz makecommand(pkt, flags, com, blkno, ADD_LBA_MODE, 2357 3786 arutz bp->b_bcount, direction, 0); 2358 3786 arutz tval = dcd_io_time; 2359 3786 arutz } else { 2360 3786 arutz 2361 3786 arutz struct udcd_cmd *scmd = (struct udcd_cmd *)bp->b_forw; 2362 3786 arutz 2363 3786 arutz /* 2364 3786 arutz * set options 2365 3786 arutz */ 2366 3786 arutz if ((scmd->udcd_flags & UDCD_SILENT) && !(DEBUGGING)) { 2367 3786 arutz flags |= FLAG_SILENT; 2368 3786 arutz } 2369 3786 arutz if (scmd->udcd_flags & UDCD_DIAGNOSE) 2370 3786 arutz flags |= FLAG_DIAGNOSE; 2371 3786 arutz 2372 3786 arutz if (scmd->udcd_flags & UDCD_NOINTR) 2373 3786 arutz flags |= FLAG_NOINTR; 2374 3786 arutz 2375 3786 arutz pkt = dcd_init_pkt(ROUTE, (struct dcd_pkt *)NULL, 2376 3786 arutz (bp->b_bcount)? bp: NULL, 2377 3786 arutz (uint32_t)sizeof (struct dcd_cmd), 2378 3786 arutz 2, PP_LEN, PKT_CONSISTENT, func, (caddr_t)un); 2379 3786 arutz 2380 3786 arutz if (!pkt) { 2381 3786 arutz bp->av_back = NO_PKT_ALLOCATED; 2382 3786 arutz return; 2383 3786 arutz } 2384 3786 arutz 2385 3786 arutz makecommand(pkt, 0, scmd->udcd_cmd->cmd, 2386 3786 arutz scmd->udcd_cmd->sector_num.lba_num, 2387 3786 arutz scmd->udcd_cmd->address_mode, 2388 3786 arutz scmd->udcd_cmd->size, 2389 3786 arutz scmd->udcd_cmd->direction, scmd->udcd_cmd->features); 2390 3786 arutz 2391 3786 arutz pkt->pkt_flags = flags; 2392 3786 arutz if (scmd->udcd_timeout == 0) 2393 3786 arutz tval = dcd_io_time; 2394 3786 arutz else 2395 3786 arutz tval = scmd->udcd_timeout; 2396 3786 arutz /* UDAD interface should be decided. */ 2397 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2398 3786 arutz "udcd interface\n"); 2399 3786 arutz } 2400 3786 arutz 2401 3786 arutz pkt->pkt_comp = dcdintr; 2402 3786 arutz pkt->pkt_time = tval; 2403 3786 arutz PKT_SET_BP(pkt, bp); 2404 3786 arutz bp->av_back = (struct buf *)pkt; 2405 3786 arutz 2406 3786 arutz TRACE_0(TR_FAC_DADA, TR_MAKE_DCD_CMD_END, "make_dcd_cmd_end"); 2407 3786 arutz } 2408 3786 arutz 2409 3786 arutz /* 2410 3786 arutz * Command completion processing 2411 3786 arutz */ 2412 3786 arutz static void 2413 3786 arutz dcdintr(struct dcd_pkt *pkt) 2414 3786 arutz { 2415 3786 arutz struct dcd_disk *un; 2416 3786 arutz struct buf *bp; 2417 3786 arutz int action; 2418 3786 arutz int status; 2419 3786 arutz 2420 3786 arutz bp = PKT_GET_BP(pkt); 2421 3786 arutz un = ddi_get_soft_state(dcd_state, DCDUNIT(bp->b_edev)); 2422 3786 arutz 2423 3786 arutz TRACE_1(TR_FAC_DADA, TR_DCDINTR_START, "dcdintr_start: un 0x%p", un); 2424 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, "dcdintr\n"); 2425 3786 arutz 2426 3786 arutz mutex_enter(DCD_MUTEX); 2427 3786 arutz un->un_ncmds--; 2428 3786 arutz DCD_DO_KSTATS(un, kstat_runq_exit, bp); 2429 3786 arutz ASSERT(un->un_ncmds >= 0); 2430 3786 arutz 2431 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2432 3786 arutz "reason %x and Status %x\n", pkt->pkt_reason, SCBP_C(pkt)); 2433 3786 arutz 2434 3786 arutz /* 2435 3786 arutz * do most common case first 2436 3786 arutz */ 2437 3786 arutz if ((pkt->pkt_reason == CMD_CMPLT) && (SCBP_C(pkt) == 0)) { 2438 3786 arutz int com = GETATACMD((struct dcd_cmd *)pkt->pkt_cdbp); 2439 3786 arutz 2440 3786 arutz if (un->un_state == DCD_STATE_OFFLINE) { 2441 3786 arutz un->un_state = un->un_last_state; 2442 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_NOTE, 2443 3786 arutz (const char *) diskokay); 2444 3786 arutz } 2445 3786 arutz /* 2446 3786 arutz * If the command is a read or a write, and we have 2447 3786 arutz * a non-zero pkt_resid, that is an error. We should 2448 3786 arutz * attempt to retry the operation if possible. 2449 3786 arutz */ 2450 3786 arutz action = COMMAND_DONE; 2451 3786 arutz if (pkt->pkt_resid && (com == ATA_READ || com == ATA_WRITE)) { 2452 3786 arutz DCD_DO_ERRSTATS(un, dcd_harderrs); 2453 3786 arutz if ((int)PKT_GET_RETRY_CNT(pkt) < dcd_retry_count) { 2454 3786 arutz PKT_INCR_RETRY_CNT(pkt, 1); 2455 3786 arutz action = QUE_COMMAND; 2456 3786 arutz } else { 2457 3786 arutz /* 2458 3786 arutz * if we have exhausted retries 2459 3786 arutz * a command with a residual is in error in 2460 3786 arutz * this case. 2461 3786 arutz */ 2462 3786 arutz action = COMMAND_DONE_ERROR; 2463 3786 arutz } 2464 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, 2465 3786 arutz CE_WARN, "incomplete %s- %s\n", 2466 3786 arutz (bp->b_flags & B_READ)? "read" : "write", 2467 3786 arutz (action == QUE_COMMAND)? "retrying" : 2468 3786 arutz "giving up"); 2469 3786 arutz } 2470 3786 arutz 2471 3786 arutz /* 2472 3786 arutz * pkt_resid will reflect, at this point, a residual 2473 3786 arutz * of how many bytes left to be transferred there were 2474 3786 arutz * from the actual scsi command. Add this to b_resid i.e 2475 3786 arutz * the amount this driver could not see to transfer, 2476 3786 arutz * to get the total number of bytes not transfered. 2477 3786 arutz */ 2478 3786 arutz if (action != QUE_COMMAND) { 2479 3786 arutz bp->b_resid += pkt->pkt_resid; 2480 3786 arutz } 2481 3786 arutz 2482 3786 arutz } else if (pkt->pkt_reason != CMD_CMPLT) { 2483 3786 arutz action = dcd_handle_incomplete(un, bp); 2484 3786 arutz } 2485 3786 arutz 2486 3786 arutz /* 2487 3786 arutz * If we are in the middle of syncing or dumping, we have got 2488 3786 arutz * here because dcd_transport has called us explictly after 2489 3786 arutz * completing the command in a polled mode. We don't want to 2490 3786 arutz * have a recursive call into dcd_transport again. 2491 3786 arutz */ 2492 3786 arutz if (ddi_in_panic() && (action == QUE_COMMAND)) { 2493 3786 arutz action = COMMAND_DONE_ERROR; 2494 3786 arutz } 2495 3786 arutz 2496 3786 arutz /* 2497 3786 arutz * save pkt reason; consecutive failures are not reported unless 2498 3786 arutz * fatal 2499 3786 arutz * do not reset last_pkt_reason when the cmd was retried and 2500 3786 arutz * succeeded because 2501 3786 arutz * there maybe more commands comming back with last_pkt_reason 2502 3786 arutz */ 2503 3786 arutz if ((un->un_last_pkt_reason != pkt->pkt_reason) && 2504 3786 arutz ((pkt->pkt_reason != CMD_CMPLT) || 2505 3786 arutz (PKT_GET_RETRY_CNT(pkt) == 0))) { 2506 3786 arutz un->un_last_pkt_reason = pkt->pkt_reason; 2507 3786 arutz } 2508 3786 arutz 2509 3786 arutz switch (action) { 2510 3786 arutz case COMMAND_DONE_ERROR: 2511 3786 arutz error: 2512 3786 arutz if (bp->b_resid == 0) { 2513 3786 arutz bp->b_resid = bp->b_bcount; 2514 3786 arutz } 2515 3786 arutz if (bp->b_error == 0) { 2516 3786 arutz struct dcd_cmd *cdbp = (struct dcd_cmd *)pkt->pkt_cdbp; 2517 3786 arutz if (cdbp->cmd == ATA_FLUSH_CACHE && 2518 3786 arutz (pkt->pkt_scbp[0] & STATUS_ATA_ERR) && 2519 3786 arutz (pkt->pkt_scbp[1] & ERR_ABORT)) { 2520 3786 arutz SET_BP_ERROR(bp, ENOTSUP); 2521 3786 arutz un->un_flush_not_supported = 1; 2522 3786 arutz } else { 2523 3786 arutz SET_BP_ERROR(bp, EIO); 2524 3786 arutz } 2525 3786 arutz } 2526 3786 arutz bp->b_flags |= B_ERROR; 2527 3786 arutz /*FALLTHROUGH*/ 2528 3786 arutz case COMMAND_DONE: 2529 3786 arutz dcddone_and_mutex_exit(un, bp); 2530 3786 arutz 2531 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDINTR_COMMAND_DONE_END, 2532 3786 arutz "dcdintr_end (COMMAND_DONE)"); 2533 3786 arutz return; 2534 3786 arutz 2535 3786 arutz case QUE_COMMAND: 2536 3786 arutz if (un->un_ncmds >= un->un_throttle) { 2537 3786 arutz struct diskhd *dp = &un->un_utab; 2538 3786 arutz 2539 3786 arutz bp->b_actf = dp->b_actf; 2540 3786 arutz dp->b_actf = bp; 2541 3786 arutz 2542 3786 arutz DCD_DO_KSTATS(un, kstat_waitq_enter, bp); 2543 3786 arutz 2544 3786 arutz mutex_exit(DCD_MUTEX); 2545 3786 arutz goto exit; 2546 3786 arutz } 2547 3786 arutz 2548 3786 arutz un->un_ncmds++; 2549 3786 arutz /* reset the pkt reason again */ 2550 3786 arutz pkt->pkt_reason = 0; 2551 3786 arutz DCD_DO_KSTATS(un, kstat_runq_enter, bp); 2552 3786 arutz mutex_exit(DCD_MUTEX); 2553 3786 arutz if ((status = dcd_transport(BP_PKT(bp))) != TRAN_ACCEPT) { 2554 3786 arutz struct diskhd *dp = &un->un_utab; 2555 3786 arutz 2556 3786 arutz mutex_enter(DCD_MUTEX); 2557 3786 arutz un->un_ncmds--; 2558 3786 arutz if (status == TRAN_BUSY) { 2559 3786 arutz DCD_DO_KSTATS(un, kstat_runq_back_to_waitq, bp); 2560 3786 arutz dcd_handle_tran_busy(bp, dp, un); 2561 3786 arutz mutex_exit(DCD_MUTEX); 2562 3786 arutz goto exit; 2563 3786 arutz } 2564 3786 arutz DCD_DO_ERRSTATS(un, dcd_transerrs); 2565 3786 arutz DCD_DO_KSTATS(un, kstat_runq_exit, bp); 2566 3786 arutz 2567 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2568 3786 arutz "requeue of command fails (%x)\n", status); 2569 3786 arutz SET_BP_ERROR(bp, EIO); 2570 3786 arutz bp->b_resid = bp->b_bcount; 2571 3786 arutz 2572 3786 arutz dcddone_and_mutex_exit(un, bp); 2573 3786 arutz goto exit; 2574 3786 arutz } 2575 3786 arutz break; 2576 3786 arutz 2577 3786 arutz case JUST_RETURN: 2578 3786 arutz default: 2579 3786 arutz DCD_DO_KSTATS(un, kstat_waitq_enter, bp); 2580 3786 arutz mutex_exit(DCD_MUTEX); 2581 3786 arutz break; 2582 3786 arutz } 2583 3786 arutz 2584 3786 arutz exit: 2585 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDINTR_END, "dcdintr_end"); 2586 3786 arutz } 2587 3786 arutz 2588 3786 arutz 2589 3786 arutz /* 2590 3786 arutz * Done with a command. 2591 3786 arutz */ 2592 3786 arutz static void 2593 3786 arutz dcddone_and_mutex_exit(struct dcd_disk *un, register struct buf *bp) 2594 3786 arutz { 2595 3786 arutz struct diskhd *dp; 2596 3786 arutz 2597 3786 arutz TRACE_1(TR_FAC_DADA, TR_DCDONE_START, "dcddone_start: un 0x%p", un); 2598 3786 arutz 2599 3786 arutz _NOTE(LOCK_RELEASED_AS_SIDE_EFFECT(&un->un_dcd->dcd_mutex)); 2600 3786 arutz 2601 3786 arutz dp = &un->un_utab; 2602 3786 arutz if (bp == dp->b_forw) { 2603 3786 arutz dp->b_forw = NULL; 2604 3786 arutz } 2605 3786 arutz 2606 3786 arutz if (un->un_stats) { 2607 3786 arutz ulong_t n_done = bp->b_bcount - bp->b_resid; 2608 3786 arutz if (bp->b_flags & B_READ) { 2609 3786 arutz IOSP->reads++; 2610 3786 arutz IOSP->nread += n_done; 2611 3786 arutz } else { 2612 3786 arutz IOSP->writes++; 2613 3786 arutz IOSP->nwritten += n_done; 2614 3786 arutz } 2615 3786 arutz } 2616 3786 arutz if (IO_PARTITION_STATS) { 2617 3786 arutz ulong_t n_done = bp->b_bcount - bp->b_resid; 2618 3786 arutz if (bp->b_flags & B_READ) { 2619 3786 arutz IOSP_PARTITION->reads++; 2620 3786 arutz IOSP_PARTITION->nread += n_done; 2621 3786 arutz } else { 2622 3786 arutz IOSP_PARTITION->writes++; 2623 3786 arutz IOSP_PARTITION->nwritten += n_done; 2624 3786 arutz } 2625 3786 arutz } 2626 3786 arutz 2627 3786 arutz /* 2628 3786 arutz * Start the next one before releasing resources on this one 2629 3786 arutz */ 2630 3786 arutz if (un->un_state == DCD_STATE_SUSPENDED) { 2631 3786 arutz cv_broadcast(&un->un_disk_busy_cv); 2632 3786 arutz } else if (dp->b_actf && (un->un_ncmds < un->un_throttle) && 2633 3786 arutz (dp->b_forw == NULL && un->un_state != DCD_STATE_SUSPENDED)) { 2634 3786 arutz dcdstart(un); 2635 3786 arutz } 2636 3786 arutz 2637 3786 arutz mutex_exit(DCD_MUTEX); 2638 3786 arutz 2639 3786 arutz if (bp != un->un_sbufp) { 2640 3786 arutz dcd_destroy_pkt(BP_PKT(bp)); 2641 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2642 3786 arutz "regular done: resid %ld\n", bp->b_resid); 2643 3786 arutz } else { 2644 3786 arutz ASSERT(un->un_sbuf_busy); 2645 3786 arutz } 2646 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDDONE_BIODONE_CALL, "dcddone_biodone_call"); 2647 3786 arutz 2648 3786 arutz biodone(bp); 2649 3786 arutz 2650 3786 arutz (void) pm_idle_component(DCD_DEVINFO, 0); 2651 3786 arutz 2652 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCDDONE_END, "dcddone end"); 2653 3786 arutz } 2654 3786 arutz 2655 3786 arutz 2656 3786 arutz /* 2657 3786 arutz * reset the disk unless the transport layer has already 2658 3786 arutz * cleared the problem 2659 3786 arutz */ 2660 3786 arutz #define C1 (STAT_ATA_BUS_RESET|STAT_ATA_DEV_RESET|STAT_ATA_ABORTED) 2661 3786 arutz static void 2662 3786 arutz dcd_reset_disk(struct dcd_disk *un, struct dcd_pkt *pkt) 2663 3786 arutz { 2664 3786 arutz 2665 3786 arutz if ((pkt->pkt_statistics & C1) == 0) { 2666 3786 arutz mutex_exit(DCD_MUTEX); 2667 3786 arutz if (!dcd_reset(ROUTE, RESET_ALL)) { 2668 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2669 3786 arutz "Reset failed"); 2670 3786 arutz } 2671 3786 arutz mutex_enter(DCD_MUTEX); 2672 3786 arutz } 2673 3786 arutz } 2674 3786 arutz 2675 3786 arutz static int 2676 3786 arutz dcd_handle_incomplete(struct dcd_disk *un, struct buf *bp) 2677 3786 arutz { 2678 3786 arutz static char *fail = "ATA transport failed: reason '%s': %s\n"; 2679 3786 arutz static char *notresp = "disk not responding to selection\n"; 2680 3786 arutz int rval = COMMAND_DONE_ERROR; 2681 3786 arutz int action = COMMAND_SOFT_ERROR; 2682 3786 arutz struct dcd_pkt *pkt = BP_PKT(bp); 2683 3786 arutz int be_chatty = (un->un_state != DCD_STATE_SUSPENDED) && 2684 3786 arutz (bp != un->un_sbufp || !(pkt->pkt_flags & FLAG_SILENT)); 2685 3786 arutz 2686 3786 arutz ASSERT(mutex_owned(DCD_MUTEX)); 2687 3786 arutz 2688 3786 arutz switch (pkt->pkt_reason) { 2689 3786 arutz 2690 3786 arutz case CMD_TIMEOUT: 2691 3786 arutz /* 2692 3786 arutz * This Indicates the already the HBA would have reset 2693 3786 arutz * so Just indicate to retry the command 2694 3786 arutz */ 2695 3786 arutz break; 2696 3786 arutz 2697 3786 arutz case CMD_INCOMPLETE: 2698 3786 arutz action = dcd_check_error(un, bp); 2699 3786 arutz DCD_DO_ERRSTATS(un, dcd_transerrs); 2700 4137 kc28005 if (action == COMMAND_HARD_ERROR) { 2701 4137 kc28005 (void) dcd_reset_disk(un, pkt); 2702 4137 kc28005 } 2703 3786 arutz break; 2704 3786 arutz 2705 3786 arutz case CMD_FATAL: 2706 3786 arutz /* 2707 3786 arutz * Something drastic has gone wrong 2708 3786 arutz */ 2709 3786 arutz break; 2710 3786 arutz case CMD_DMA_DERR: 2711 3786 arutz case CMD_DATA_OVR: 2712 3786 arutz /* FALLTHROUGH */ 2713 3786 arutz 2714 3786 arutz default: 2715 3786 arutz /* 2716 3786 arutz * the target may still be running the command, 2717 3786 arutz * so we should try and reset that target. 2718 3786 arutz */ 2719 3786 arutz DCD_DO_ERRSTATS(un, dcd_transerrs); 2720 3786 arutz if ((pkt->pkt_reason != CMD_RESET) && 2721 7224 cth (pkt->pkt_reason != CMD_ABORTED)) { 2722 3786 arutz (void) dcd_reset_disk(un, pkt); 2723 3786 arutz } 2724 3786 arutz break; 2725 3786 arutz } 2726 3786 arutz 2727 3786 arutz /* 2728 3786 arutz * If pkt_reason is CMD_RESET/ABORTED, chances are that this pkt got 2729 3786 arutz * reset/aborted because another disk on this bus caused it. 2730 3786 arutz * The disk that caused it, should get CMD_TIMEOUT with pkt_statistics 2731 3786 arutz * of STAT_TIMEOUT/STAT_DEV_RESET 2732 3786 arutz */ 2733 3786 arutz if ((pkt->pkt_reason == CMD_RESET) ||(pkt->pkt_reason == CMD_ABORTED)) { 2734 3786 arutz /* To be written : XXX */ 2735 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2736 3786 arutz "Command aborted\n"); 2737 3786 arutz } 2738 3786 arutz 2739 3786 arutz if (bp == un->un_sbufp && (pkt->pkt_flags & FLAG_DIAGNOSE)) { 2740 3786 arutz rval = COMMAND_DONE_ERROR; 2741 3786 arutz } else { 2742 3786 arutz if ((rval == COMMAND_DONE_ERROR) && 2743 3786 arutz (action == COMMAND_SOFT_ERROR) && 2744 3786 arutz ((int)PKT_GET_RETRY_CNT(pkt) < dcd_retry_count)) { 2745 3786 arutz PKT_INCR_RETRY_CNT(pkt, 1); 2746 3786 arutz rval = QUE_COMMAND; 2747 3786 arutz } 2748 3786 arutz } 2749 3786 arutz 2750 3786 arutz if (pkt->pkt_reason == CMD_INCOMPLETE && rval == COMMAND_DONE_ERROR) { 2751 3786 arutz /* 2752 3786 arutz * Looks like someone turned off this shoebox. 2753 3786 arutz */ 2754 3786 arutz if (un->un_state != DCD_STATE_OFFLINE) { 2755 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2756 7224 cth (const char *) notresp); 2757 3786 arutz New_state(un, DCD_STATE_OFFLINE); 2758 3786 arutz } 2759 3786 arutz } else if (pkt->pkt_reason == CMD_FATAL) { 2760 3786 arutz /* 2761 3786 arutz * Suppressing the following message for the time being 2762 3786 arutz * dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2763 3786 arutz * (const char *) notresp); 2764 3786 arutz */ 2765 3786 arutz PKT_INCR_RETRY_CNT(pkt, 6); 2766 3786 arutz rval = COMMAND_DONE_ERROR; 2767 3786 arutz New_state(un, DCD_STATE_FATAL); 2768 3786 arutz } else if (be_chatty) { 2769 3786 arutz int in_panic = ddi_in_panic(); 2770 3786 arutz if (!in_panic || (rval == COMMAND_DONE_ERROR)) { 2771 3786 arutz if (((pkt->pkt_reason != un->un_last_pkt_reason) && 2772 3786 arutz (pkt->pkt_reason != CMD_RESET)) || 2773 3786 arutz (rval == COMMAND_DONE_ERROR) || 2774 3786 arutz (dcd_error_level == DCD_ERR_ALL)) { 2775 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2776 3786 arutz fail, dcd_rname(pkt->pkt_reason), 2777 3786 arutz (rval == COMMAND_DONE_ERROR) ? 2778 3786 arutz "giving up": "retrying command"); 2779 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2780 3786 arutz "retrycount=%x\n", 2781 3786 arutz PKT_GET_RETRY_CNT(pkt)); 2782 3786 arutz } 2783 3786 arutz } 2784 3786 arutz } 2785 3786 arutz error: 2786 3786 arutz return (rval); 2787 3786 arutz } 2788 3786 arutz 2789 3786 arutz static int 2790 3786 arutz dcd_check_error(struct dcd_disk *un, struct buf *bp) 2791 3786 arutz { 2792 3786 arutz struct diskhd *dp = &un->un_utab; 2793 3786 arutz struct dcd_pkt *pkt = BP_PKT(bp); 2794 3786 arutz int rval = 0; 2795 3786 arutz unsigned char status; 2796 3786 arutz unsigned char error; 2797 3786 arutz 2798 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCD_CHECK_ERROR_START, "dcd_check_error_start"); 2799 3786 arutz ASSERT(mutex_owned(DCD_MUTEX)); 2800 3786 arutz 2801 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 2802 3786 arutz "Pkt: 0x%p dp: 0x%p\n", (void *)pkt, (void *)dp); 2803 3786 arutz 2804 3786 arutz /* 2805 3786 arutz * Here we need to check status first and then if error is indicated 2806 3786 arutz * Then the error register. 2807 3786 arutz */ 2808 3786 arutz 2809 3786 arutz status = (pkt->pkt_scbp)[0]; 2810 3786 arutz if ((status & STATUS_ATA_DWF) == STATUS_ATA_DWF) { 2811 3786 arutz /* 2812 3786 arutz * There has been a Device Fault - reason for such error 2813 3786 arutz * is vendor specific 2814 3786 arutz * Action to be taken is - Indicate error and reset device. 2815 3786 arutz */ 2816 3786 arutz 2817 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, "Device Fault\n"); 2818 3786 arutz rval = COMMAND_HARD_ERROR; 2819 3786 arutz } else if ((status & STATUS_ATA_CORR) == STATUS_ATA_CORR) { 2820 3786 arutz 2821 3786 arutz /* 2822 3786 arutz * The sector read or written is marginal and hence ECC 2823 3786 arutz * Correction has been applied. Indicate to repair 2824 3786 arutz * Here we need to probably re-assign based on the badblock 2825 3786 arutz * mapping. 2826 3786 arutz */ 2827 3786 arutz 2828 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2829 3786 arutz "Soft Error on block %x\n", 2830 3786 arutz ((struct dcd_cmd *)pkt->pkt_cdbp)->sector_num.lba_num); 2831 3786 arutz rval = COMMAND_SOFT_ERROR; 2832 3786 arutz } else if ((status & STATUS_ATA_ERR) == STATUS_ATA_ERR) { 2833 3786 arutz error = pkt->pkt_scbp[1]; 2834 3786 arutz 2835 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2836 3786 arutz "Command:0x%x,Error:0x%x,Status:0x%x\n", 2837 3786 arutz GETATACMD((struct dcd_cmd *)pkt->pkt_cdbp), 2838 3786 arutz error, status); 2839 3786 arutz if ((error & ERR_AMNF) == ERR_AMNF) { 2840 3786 arutz /* Address make not found */ 2841 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2842 3786 arutz "Address Mark Not Found"); 2843 3786 arutz } else if ((error & ERR_TKONF) == ERR_TKONF) { 2844 3786 arutz /* Track 0 Not found */ 2845 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2846 3786 arutz "Track 0 Not found \n"); 2847 3786 arutz } else if ((error & ERR_IDNF) == ERR_IDNF) { 2848 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2849 3786 arutz " ID not found \n"); 2850 3786 arutz } else if ((error & ERR_UNC) == ERR_UNC) { 2851 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2852 3786 arutz "Uncorrectable data Error: Block %x\n", 2853 7224 cth ((struct dcd_cmd *)pkt->pkt_cdbp)-> 2854 7224 cth sector_num.lba_num); 2855 3786 arutz } else if ((error & ERR_BBK) == ERR_BBK) { 2856 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2857 3786 arutz "Bad block detected: Block %x\n", 2858 7224 cth ((struct dcd_cmd *)pkt->pkt_cdbp)-> 2859 7224 cth sector_num.lba_num); 2860 3786 arutz } else if ((error & ERR_ABORT) == ERR_ABORT) { 2861 3786 arutz /* Aborted Command */ 2862 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2863 3786 arutz " Aborted Command \n"); 2864 3786 arutz } 2865 3786 arutz /* 2866 3786 arutz * Return the soft error so that the command 2867 3786 arutz * will be retried. 2868 3786 arutz */ 2869 3786 arutz rval = COMMAND_SOFT_ERROR; 2870 3786 arutz } 2871 3786 arutz 2872 3786 arutz TRACE_0(TR_FAC_DADA, TR_DCD_CHECK_ERROR_END, "dcd_check_error_end"); 2873 3786 arutz return (rval); 2874 3786 arutz } 2875 3786 arutz 2876 3786 arutz 2877 3786 arutz /* 2878 3786 arutz * System Crash Dump routine 2879 3786 arutz */ 2880 3786 arutz 2881 3786 arutz #define NDUMP_RETRIES 5 2882 3786 arutz 2883 3786 arutz static int 2884 3786 arutz dcddump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk) 2885 3786 arutz { 2886 3786 arutz struct dcd_pkt *pkt; 2887 3786 arutz int i; 2888 3786 arutz struct buf local, *bp; 2889 3786 arutz int err; 2890 3786 arutz unsigned char com; 2891 3786 arutz diskaddr_t p_lblksrt; 2892 3786 arutz diskaddr_t lblocks; 2893 3786 arutz 2894 3786 arutz GET_SOFT_STATE(dev); 2895 3786 arutz #ifdef lint 2896 3786 arutz part = part; 2897 3786 arutz #endif /* lint */ 2898 3786 arutz 2899 3786 arutz _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*un)) 2900 3786 arutz 2901 3786 arutz if ((un->un_state & DCD_STATE_FATAL) == DCD_STATE_FATAL) 2902 3786 arutz return (ENXIO); 2903 3786 arutz 2904 3786 arutz if (cmlb_partinfo(un->un_dklbhandle, DCDPART(dev), 2905 3786 arutz &lblocks, &p_lblksrt, NULL, NULL, 0)) 2906 3786 arutz return (ENXIO); 2907 3786 arutz 2908 3786 arutz if (blkno+nblk > lblocks) { 2909 3786 arutz return (EINVAL); 2910 3786 arutz } 2911 3786 arutz 2912 3786 arutz 2913 3786 arutz if ((un->un_state == DCD_STATE_SUSPENDED) || 2914 3786 arutz (un->un_state == DCD_STATE_PM_SUSPENDED)) { 2915 3786 arutz if (pm_raise_power(DCD_DEVINFO, 0, 2916 3786 arutz DCD_DEVICE_ACTIVE) != DDI_SUCCESS) { 2917 3786 arutz return (EIO); 2918 3786 arutz } 2919 3786 arutz } 2920 3786 arutz 2921 3786 arutz /* 2922 3786 arutz * When cpr calls dcddump, we know that dad is in a 2923 3786 arutz * a good state, so no bus reset is required 2924 3786 arutz */ 2925 3786 arutz un->un_throttle = 0; 2926 3786 arutz 2927 3786 arutz if ((un->un_state != DCD_STATE_SUSPENDED) && 2928 3786 arutz (un->un_state != DCD_STATE_DUMPING)) { 2929 3786 arutz 2930 3786 arutz New_state(un, DCD_STATE_DUMPING); 2931 3786 arutz 2932 3786 arutz /* 2933 3786 arutz * Reset the bus. I'd like to not have to do this, 2934 3786 arutz * but this is the safest thing to do... 2935 3786 arutz */ 2936 3786 arutz 2937 3786 arutz if (dcd_reset(ROUTE, RESET_ALL) == 0) { 2938 3786 arutz return (EIO); 2939 3786 arutz } 2940 3786 arutz 2941 3786 arutz } 2942 3786 arutz 2943 3786 arutz blkno += p_lblksrt; 2944 3786 arutz 2945 3786 arutz /* 2946 3786 arutz * It should be safe to call the allocator here without 2947 3786 arutz * worrying about being locked for DVMA mapping because 2948 3786 arutz * the address we're passed is already a DVMA mapping 2949 3786 arutz * 2950 3786 arutz * We are also not going to worry about semaphore ownership 2951 3786 arutz * in the dump buffer. Dumping is single threaded at present. 2952 3786 arutz */ 2953 3786 arutz 2954 3786 arutz bp = &local; 2955 3786 arutz bzero((caddr_t)bp, sizeof (*bp)); 2956 3786 arutz bp->b_flags = B_BUSY; 2957 3786 arutz bp->b_un.b_addr = addr; 2958 3786 arutz bp->b_bcount = nblk << DEV_BSHIFT; 2959 3786 arutz bp->b_resid = 0; 2960 3786 arutz 2961 3786 arutz for (i = 0; i < NDUMP_RETRIES; i++) { 2962 3786 arutz bp->b_flags &= ~B_ERROR; 2963 3786 arutz if ((pkt = dcd_init_pkt(ROUTE, NULL, bp, 2964 3786 arutz (uint32_t)sizeof (struct dcd_cmd), 2, PP_LEN, 2965 3786 arutz PKT_CONSISTENT, NULL_FUNC, NULL)) != NULL) { 2966 3786 arutz break; 2967 3786 arutz } 2968 3786 arutz if (i == 0) { 2969 3786 arutz if (bp->b_flags & B_ERROR) { 2970 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2971 3786 arutz "no resources for dumping; " 2972 3786 arutz "error code: 0x%x, retrying", 2973 3786 arutz geterror(bp)); 2974 3786 arutz } else { 2975 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_WARN, 2976 3786 arutz "no resources for dumping; retrying"); 2977 3786 arutz } 2978 3786 arutz } else if (i != (NDUMP_RETRIES - 1)) { 2979 3786 arutz if (bp->b_flags & B_ERROR) { 2980 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_CONT, "no " 2981 3786 arutz "resources for dumping; error code: 0x%x, " 2982 3786 arutz "retrying\n", geterror(bp)); 2983 3786 arutz } 2984 3786 arutz } else { 2985 3786 arutz if (bp->b_flags & B_ERROR) { 2986 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_CONT, 2987 3786 arutz "no resources for dumping; " 2988 3786 arutz "error code: 0x%x, retries failed, " 2989 3786 arutz "giving up.\n", geterror(bp)); 2990 3786 arutz } else { 2991 3786 arutz dcd_log(DCD_DEVINFO, dcd_label, CE_CONT, 2992 3786 arutz "no resources for dumping; " 2993 3786 arutz "retries failed, giving up.\n"); 2994 3786 arutz } 2995 3786 arutz return (EIO); 2996 3786 arutz } 2997 3786 arutz delay(10); 2998 3786 arutz } 2999 3786 arutz if ((un->un_dp->options & DMA_SUPPORTTED) == DMA_SUPPORTTED) { 3000 3786 arutz com = ATA_WRITE_DMA; 3001 3786 arutz } else { 3002 3786 arutz if (un->un_dp->options & BLOCK_MODE) 3003 3786 arutz com = ATA_WRITE_MULTIPLE; 3004 3786 arutz else 3005 3786 arutz com = ATA_WRITE; 3006 3786 arutz } 3007 3786 arutz 3008 3786 arutz makecommand(pkt, 0, com, blkno, ADD_LBA_MODE, 3009 3786 arutz (int)nblk*un->un_secsize, DATA_WRITE, 0); 3010 3786 arutz 3011 3786 arutz for (err = EIO, i = 0; i < NDUMP_RETRIES && err == EIO; i++) { 3012 3786 arutz 3013 3786 arutz if (dcd_poll(pkt) == 0) { 3014 3786 arutz switch (SCBP_C(pkt)) { 3015 3786 arutz case STATUS_GOOD: 3016 3786 arutz if (pkt->pkt_resid == 0) { 3017 3786 arutz err = 0; 3018 3786 arutz } 3019 3786 arutz break; 3020 3786 arutz case STATUS_ATA_BUSY: 3021 3786 arutz (void) dcd_reset(ROUTE, RESET_TARGET); 3022 3786 arutz break; 3023 3786 arutz default: 3024 3786 arutz mutex_enter(DCD_MUTEX); 3025 3786 arutz (void) dcd_reset_disk(un, pkt); 3026 3786 arutz mutex_exit(DCD_MUTEX); 3027 3786 arutz break; 3028 3786 arutz } 3029 3786 arutz } else if (i > NDUMP_RETRIES/2) { 3030 3786 arutz (void) dcd_reset(ROUTE, RESET_ALL); 3031 3786 arutz } 3032 3786 arutz 3033 3786 arutz } 3034 3786 arutz dcd_destroy_pkt(pkt); 3035 3786 arutz return (err); 3036 3786 arutz } 3037 3786 arutz 3038 3786 arutz /* 3039 3786 arutz * This routine implements the ioctl calls. It is called 3040 3786 arutz * from the device switch at normal priority. 3041 3786 arutz */ 3042 3786 arutz /* ARGSUSED3 */ 3043 3786 arutz static int 3044 3786 arutz dcdioctl(dev_t dev, int cmd, intptr_t arg, int flag, 3045 3786 arutz cred_t *cred_p, int *rval_p) 3046 3786 arutz { 3047 3786 arutz auto int32_t data[512 / (sizeof (int32_t))]; 3048 3786 arutz struct dk_cinfo *info; 3049 3786 arutz struct dk_minfo media_info; 3050 3786 arutz struct udcd_cmd *scmd; 3051 3786 arutz int i, err; 3052 3786 arutz enum uio_seg uioseg = 0; 3053 3786 arutz enum dkio_state state = 0; 3054 3786 arutz #ifdef _MULTI_DATAMODEL 3055 3786 arutz struct dadkio_rwcmd rwcmd; 3056 3786 arutz #endif 3057 3786 arutz struct dadkio_rwcmd32 rwcmd32; 3058 3786 arutz struct dcd_cmd dcdcmd; 3059 3786 arutz 3060 3786 arutz GET_SOFT_STATE(dev); 3061 3786 arutz #ifdef lint 3062 3786 arutz part = part; 3063 3786 arutz state = state; 3064 3786 arutz uioseg = uioseg; 3065 3786 arutz #endif /* lint */ 3066 3786 arutz 3067 3786 arutz DAD_DEBUG2(DCD_DEVINFO, dcd_label, DCD_DEBUG, 3068 3786 arutz "dcd_ioctl : cmd %x, arg %lx\n", cmd, arg); 3069 3786 arutz 3070 3786 arutz bzero((caddr_t)data, sizeof (data)); 3071 3786 arutz 3072 3786 arutz switch (cmd) { 3073 3786 arutz 3074 3786 arutz #ifdef DCDDEBUG 3075 3786 arutz /* 3076 3786 arutz * Following ioctl are for testing RESET/ABORTS 3077 3786 arutz */ 3078 3786 arutz #define DKIOCRESET (DKIOC|14) 3079 3786 arutz #define DKIOCABORT (DKIOC|15) 3080 3786 arutz 3081 3786 arutz case DKIOCRESET: 3082 3786 arutz if (ddi_copyin((caddr_t)arg, (caddr_t)data, 4, flag)) 3083 3786 arutz return (EFAULT); 3084 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 3085 3786 arutz "DKIOCRESET: data = 0x%x\n", data[0]); 3086 3786 arutz if (dcd_reset(ROUTE, data[0])) { 3087 3786 arutz return (0); 3088 3786 arutz } else { 3089 3786 arutz return (EIO); 3090 3786 arutz } 3091 3786 arutz case DKIOCABORT: 3092 3786 arutz DAD_DEBUG(DCD_DEVINFO, dcd_label, DCD_DEBUG, 3093 3786 arutz "DKIOCABORT:\n"); 3094 3786 arutz if (dcd_abort(ROUTE, (struct dcd_pkt *)0)) { 3095 3786 arutz return (0); 3096 3786 arutz } else { 3097 3786 arutz return (EIO); 3098 3786 arutz } 3099 3786 arutz #endif 3100 3786 arutz 3101 3786 arutz case DKIOCINFO: 3102 3786 arutz /* 3103 3786 arutz * Controller Information 3104 3786 arutz */ 3105 3786 arutz info = (struct dk_cinfo *)data; 3106 3786 arutz 3107 3786 arutz mutex_enter(DCD_MUTEX); 3108 3786 arutz switch (un->un_dp->ctype) { 3109 3786 arutz default: 3110 3786 arutz info->dki_ctype = DKC_DIRECT; 3111 3786 arutz break; 3112 3786 arutz } 3113 3786 arutz mutex_exit(DCD_MUTEX); 3114 3786 arutz info->dki_cnum = ddi_get_instance(ddi_get_parent(DCD_DEVINFO)); 3115 3786 arutz (void) strcpy(info->dki_cname, 3116 3786 arutz ddi_get_name(ddi_get_parent(DCD_DEVINFO))); 3117 3786 arutz /* 3118 3786 arutz * Unit Information 3119 3786 arutz */ 3120 3786 arutz info->dki_unit = ddi_get_instance(DCD_DEVINFO); 3121 3786 arutz info->dki_slave = (Tgt(DCD_DCD_DEVP)<<3); 3122 3786 arutz (void) strcpy(info->dki_dname, ddi_driver_name(DCD_DEVINFO)); 3123 3786 arutz info->dki_flags = DKI_FMTVOL; 3124 3786 arutz info->dki_partition = DCDPART(dev); 3125 3786 arutz 3126 3786 arutz /* 3127 3786 arutz * Max Transfer size of this device in blocks 3128 3786 arutz */ 3129 3786 arutz info->dki_maxtransfer = un->un_max_xfer_size / DEV_BSIZE; 3130 3786 arutz 3131 3786 arutz /* 3132 3786 arutz * We can't get from here to there yet 3133