1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * Floppy Disk driver 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * Set CMOS feature: 35*7c478bd9Sstevel@tonic-gate * CMOS_CONF_MEM: CMOS memory contains configuration info 36*7c478bd9Sstevel@tonic-gate */ 37*7c478bd9Sstevel@tonic-gate #define CMOS_CONF_MEM 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/open.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/ddidmareq.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/fdio.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/fdc.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/fd_debug.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/fdmedia.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * Local Function Prototypes 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate static int fd_unit_is_open(struct fdisk *); 68*7c478bd9Sstevel@tonic-gate static int fdgetlabel(struct fcu_obj *, int); 69*7c478bd9Sstevel@tonic-gate static void fdstart(struct fcu_obj *); 70*7c478bd9Sstevel@tonic-gate static int fd_build_label_vtoc(struct fcu_obj *, struct fdisk *, 71*7c478bd9Sstevel@tonic-gate struct vtoc *, struct dk_label *); 72*7c478bd9Sstevel@tonic-gate static void fd_build_user_vtoc(struct fcu_obj *, struct fdisk *, 73*7c478bd9Sstevel@tonic-gate struct vtoc *); 74*7c478bd9Sstevel@tonic-gate static int fd_rawioctl(struct fcu_obj *, int, caddr_t, int); 75*7c478bd9Sstevel@tonic-gate static void fd_media_watch(void *); 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate static int fd_open(dev_t *, int, int, cred_t *); 78*7c478bd9Sstevel@tonic-gate static int fd_close(dev_t, int, int, cred_t *); 79*7c478bd9Sstevel@tonic-gate static int fd_strategy(struct buf *); 80*7c478bd9Sstevel@tonic-gate static int fd_read(dev_t, struct uio *, cred_t *); 81*7c478bd9Sstevel@tonic-gate static int fd_write(dev_t, struct uio *, cred_t *); 82*7c478bd9Sstevel@tonic-gate static int fd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 83*7c478bd9Sstevel@tonic-gate static int fd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, 84*7c478bd9Sstevel@tonic-gate caddr_t, int *); 85*7c478bd9Sstevel@tonic-gate static int fd_check_media(dev_t dev, enum dkio_state state); 86*7c478bd9Sstevel@tonic-gate static int fd_get_media_info(struct fcu_obj *fjp, caddr_t buf, int flag); 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static struct cb_ops fd_cb_ops = { 89*7c478bd9Sstevel@tonic-gate fd_open, /* open */ 90*7c478bd9Sstevel@tonic-gate fd_close, /* close */ 91*7c478bd9Sstevel@tonic-gate fd_strategy, /* strategy */ 92*7c478bd9Sstevel@tonic-gate nodev, /* print */ 93*7c478bd9Sstevel@tonic-gate nodev, /* dump */ 94*7c478bd9Sstevel@tonic-gate fd_read, /* read */ 95*7c478bd9Sstevel@tonic-gate fd_write, /* write */ 96*7c478bd9Sstevel@tonic-gate fd_ioctl, /* ioctl */ 97*7c478bd9Sstevel@tonic-gate nodev, /* devmap */ 98*7c478bd9Sstevel@tonic-gate nodev, /* mmap */ 99*7c478bd9Sstevel@tonic-gate nodev, /* segmap */ 100*7c478bd9Sstevel@tonic-gate nochpoll, /* poll */ 101*7c478bd9Sstevel@tonic-gate fd_prop_op, /* cb_prop_op */ 102*7c478bd9Sstevel@tonic-gate 0, /* streamtab */ 103*7c478bd9Sstevel@tonic-gate D_NEW | D_MP /* Driver compatibility flag */ 104*7c478bd9Sstevel@tonic-gate }; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate static int fd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 107*7c478bd9Sstevel@tonic-gate static int fd_probe(dev_info_t *); 108*7c478bd9Sstevel@tonic-gate static int fd_attach(dev_info_t *, ddi_attach_cmd_t); 109*7c478bd9Sstevel@tonic-gate static int fd_detach(dev_info_t *, ddi_detach_cmd_t); 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate static struct dev_ops fd_ops = { 112*7c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 113*7c478bd9Sstevel@tonic-gate 0, /* refcnt */ 114*7c478bd9Sstevel@tonic-gate fd_getinfo, /* getinfo */ 115*7c478bd9Sstevel@tonic-gate nulldev, /* identify */ 116*7c478bd9Sstevel@tonic-gate fd_probe, /* probe */ 117*7c478bd9Sstevel@tonic-gate fd_attach, /* attach */ 118*7c478bd9Sstevel@tonic-gate fd_detach, /* detach */ 119*7c478bd9Sstevel@tonic-gate nodev, /* reset */ 120*7c478bd9Sstevel@tonic-gate &fd_cb_ops, /* driver operations */ 121*7c478bd9Sstevel@tonic-gate (struct bus_ops *)0 /* bus operations */ 122*7c478bd9Sstevel@tonic-gate }; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate /* 126*7c478bd9Sstevel@tonic-gate * static data 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate static void *fd_state_head; /* opaque handle top of state structs */ 129*7c478bd9Sstevel@tonic-gate static int fd_check_media_time = 5000000; /* 5 second state check */ 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate /* 132*7c478bd9Sstevel@tonic-gate * error handling 133*7c478bd9Sstevel@tonic-gate * 134*7c478bd9Sstevel@tonic-gate * for debugging, 135*7c478bd9Sstevel@tonic-gate * set fderrlevel to 1 136*7c478bd9Sstevel@tonic-gate * set fderrmask to 224 or 644 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 139*7c478bd9Sstevel@tonic-gate static uint_t fderrmask = FDEM_ALL; 140*7c478bd9Sstevel@tonic-gate #endif 141*7c478bd9Sstevel@tonic-gate static int fderrlevel = 5; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate #define KIOSP KSTAT_IO_PTR(fdp->d_iostat) 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate static struct driver_minor_data { 146*7c478bd9Sstevel@tonic-gate char *name; 147*7c478bd9Sstevel@tonic-gate int minor; 148*7c478bd9Sstevel@tonic-gate int type; 149*7c478bd9Sstevel@tonic-gate } fd_minor [] = { 150*7c478bd9Sstevel@tonic-gate { "a", 0, S_IFBLK}, 151*7c478bd9Sstevel@tonic-gate { "b", 1, S_IFBLK}, 152*7c478bd9Sstevel@tonic-gate { "c", 2, S_IFBLK}, 153*7c478bd9Sstevel@tonic-gate { "a,raw", 0, S_IFCHR}, 154*7c478bd9Sstevel@tonic-gate { "b,raw", 1, S_IFCHR}, 155*7c478bd9Sstevel@tonic-gate { "c,raw", 2, S_IFCHR}, 156*7c478bd9Sstevel@tonic-gate {0} 157*7c478bd9Sstevel@tonic-gate }; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 160*7c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a driver */ 161*7c478bd9Sstevel@tonic-gate "Floppy Disk driver %I%", /* Name of the module. */ 162*7c478bd9Sstevel@tonic-gate &fd_ops, /* driver ops */ 163*7c478bd9Sstevel@tonic-gate }; 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 166*7c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 167*7c478bd9Sstevel@tonic-gate }; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate int 171*7c478bd9Sstevel@tonic-gate _init(void) 172*7c478bd9Sstevel@tonic-gate { 173*7c478bd9Sstevel@tonic-gate int retval; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate if ((retval = ddi_soft_state_init(&fd_state_head, 176*7c478bd9Sstevel@tonic-gate sizeof (struct fdisk) + sizeof (struct fd_drive) + 177*7c478bd9Sstevel@tonic-gate sizeof (struct fd_char) + sizeof (struct fdattr), 0)) != 0) 178*7c478bd9Sstevel@tonic-gate return (retval); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate if ((retval = mod_install(&modlinkage)) != 0) 181*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&fd_state_head); 182*7c478bd9Sstevel@tonic-gate return (retval); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate int 186*7c478bd9Sstevel@tonic-gate _fini(void) 187*7c478bd9Sstevel@tonic-gate { 188*7c478bd9Sstevel@tonic-gate int retval; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if ((retval = mod_remove(&modlinkage)) != 0) 191*7c478bd9Sstevel@tonic-gate return (retval); 192*7c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&fd_state_head); 193*7c478bd9Sstevel@tonic-gate return (retval); 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate int 197*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate static int 204*7c478bd9Sstevel@tonic-gate fd_getdrive(dev_t dev, struct fcu_obj **fjpp, struct fdisk **fdpp) 205*7c478bd9Sstevel@tonic-gate { 206*7c478bd9Sstevel@tonic-gate if (fdpp) { 207*7c478bd9Sstevel@tonic-gate *fdpp = ddi_get_soft_state(fd_state_head, DRIVE(dev)); 208*7c478bd9Sstevel@tonic-gate if (*fdpp && fjpp) { 209*7c478bd9Sstevel@tonic-gate *fjpp = (*fdpp)->d_obj; 210*7c478bd9Sstevel@tonic-gate if (*fjpp) 211*7c478bd9Sstevel@tonic-gate return ((*fjpp)->fj_unit); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate return (-1); 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 218*7c478bd9Sstevel@tonic-gate static int 219*7c478bd9Sstevel@tonic-gate fd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 220*7c478bd9Sstevel@tonic-gate { 221*7c478bd9Sstevel@tonic-gate dev_t dev = (dev_t)arg; 222*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 223*7c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 224*7c478bd9Sstevel@tonic-gate int rval; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate switch (cmd) { 227*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 228*7c478bd9Sstevel@tonic-gate (void) fd_getdrive(dev, &fjp, &fdp); 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * Ignoring return value because success is checked by 231*7c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate if (fjp && fdp) { 234*7c478bd9Sstevel@tonic-gate *result = fjp->fj_dip; 235*7c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 236*7c478bd9Sstevel@tonic-gate } else 237*7c478bd9Sstevel@tonic-gate rval = DDI_FAILURE; 238*7c478bd9Sstevel@tonic-gate break; 239*7c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 240*7c478bd9Sstevel@tonic-gate *result = (void *)(uintptr_t)DRIVE(dev); 241*7c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 242*7c478bd9Sstevel@tonic-gate break; 243*7c478bd9Sstevel@tonic-gate default: 244*7c478bd9Sstevel@tonic-gate rval = DDI_FAILURE; 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate return (rval); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 250*7c478bd9Sstevel@tonic-gate #define CMOS_ADDR 0x70 251*7c478bd9Sstevel@tonic-gate #define CMOS_DATA 0x71 252*7c478bd9Sstevel@tonic-gate #define CMOS_FDRV 0x10 253*7c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate static int 256*7c478bd9Sstevel@tonic-gate fd_probe(dev_info_t *dip) 257*7c478bd9Sstevel@tonic-gate { 258*7c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 259*7c478bd9Sstevel@tonic-gate int cmos; 260*7c478bd9Sstevel@tonic-gate int drive_type; 261*7c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 262*7c478bd9Sstevel@tonic-gate int debug[2]; 263*7c478bd9Sstevel@tonic-gate int drive_size; 264*7c478bd9Sstevel@tonic-gate int len; 265*7c478bd9Sstevel@tonic-gate int unit_num; 266*7c478bd9Sstevel@tonic-gate char density[8]; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate len = sizeof (debug); 269*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 270*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "debug", (caddr_t)debug, &len) == 271*7c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 272*7c478bd9Sstevel@tonic-gate fderrlevel = debug[0]; 273*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 274*7c478bd9Sstevel@tonic-gate fderrmask = (uint_t)debug[1]; 275*7c478bd9Sstevel@tonic-gate #endif 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate len = sizeof (unit_num); 278*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 279*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "unit", (caddr_t)&unit_num, &len) != 280*7c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 281*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 282*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_probe failed: dip %p", (void *)dip)); 283*7c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 287*7c478bd9Sstevel@tonic-gate /* get the cmos memory values quick and dirty */ 288*7c478bd9Sstevel@tonic-gate outb(CMOS_ADDR, CMOS_FDRV); 289*7c478bd9Sstevel@tonic-gate cmos = drive_type = (int)inb(CMOS_DATA); 290*7c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate switch (unit_num) { 293*7c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 294*7c478bd9Sstevel@tonic-gate case 0: 295*7c478bd9Sstevel@tonic-gate drive_type = drive_type >> 4; 296*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 297*7c478bd9Sstevel@tonic-gate case 1: 298*7c478bd9Sstevel@tonic-gate if (cmos && (drive_type & 0x0F)) { 299*7c478bd9Sstevel@tonic-gate break; 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate /* 302*7c478bd9Sstevel@tonic-gate * Some enhanced floppy-disk controller adaptor cards 303*7c478bd9Sstevel@tonic-gate * require NO drives defined in the CMOS configuration 304*7c478bd9Sstevel@tonic-gate * memory. 305*7c478bd9Sstevel@tonic-gate * So fall through 306*7c478bd9Sstevel@tonic-gate */ 307*7c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 308*7c478bd9Sstevel@tonic-gate default: /* need to check conf file */ 309*7c478bd9Sstevel@tonic-gate len = sizeof (density); 310*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 311*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "density", (caddr_t)&density, &len) != 312*7c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 313*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 314*7c478bd9Sstevel@tonic-gate (CE_WARN, 315*7c478bd9Sstevel@tonic-gate "fd_probe failed density: dip %p unit %d", 316*7c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 317*7c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate len = sizeof (drive_size); 320*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 321*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "size", (caddr_t)&drive_size, &len) != 322*7c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 323*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 324*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_probe failed size: dip %p unit %d", 325*7c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 326*7c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 330*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_probe dip %p unit %d", (void *)dip, unit_num)); 331*7c478bd9Sstevel@tonic-gate return (DDI_PROBE_SUCCESS); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 336*7c478bd9Sstevel@tonic-gate static int 337*7c478bd9Sstevel@tonic-gate fd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 338*7c478bd9Sstevel@tonic-gate { 339*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 340*7c478bd9Sstevel@tonic-gate struct fdisk *fdp; 341*7c478bd9Sstevel@tonic-gate struct driver_minor_data *dmdp; 342*7c478bd9Sstevel@tonic-gate int mode_3D; 343*7c478bd9Sstevel@tonic-gate int drive_num, drive_size, drive_type; 344*7c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 345*7c478bd9Sstevel@tonic-gate int cmos; 346*7c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 347*7c478bd9Sstevel@tonic-gate int len, sig_minor; 348*7c478bd9Sstevel@tonic-gate int unit_num; 349*7c478bd9Sstevel@tonic-gate char density[8]; 350*7c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate switch (cmd) { 353*7c478bd9Sstevel@tonic-gate case DDI_ATTACH: 354*7c478bd9Sstevel@tonic-gate len = sizeof (unit_num); 355*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 356*7c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "unit", (caddr_t)&unit_num, &len) != 357*7c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 358*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 359*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach failed: dip %p", (void *)dip)); 360*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 364*7c478bd9Sstevel@tonic-gate outb(CMOS_ADDR, CMOS_FDRV); 365*7c478bd9Sstevel@tonic-gate cmos = drive_type = (int)inb(CMOS_DATA); 366*7c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate switch (unit_num) { 369*7c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 370*7c478bd9Sstevel@tonic-gate case 0: 371*7c478bd9Sstevel@tonic-gate drive_type = drive_type >> 4; 372*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 373*7c478bd9Sstevel@tonic-gate case 1: 374*7c478bd9Sstevel@tonic-gate drive_type = drive_type & 0x0F; 375*7c478bd9Sstevel@tonic-gate if (cmos) 376*7c478bd9Sstevel@tonic-gate break; 377*7c478bd9Sstevel@tonic-gate /* 378*7c478bd9Sstevel@tonic-gate * Some enhanced floppy-disk controller adaptor cards 379*7c478bd9Sstevel@tonic-gate * require NO drives defined in the CMOS configuration 380*7c478bd9Sstevel@tonic-gate * memory. 381*7c478bd9Sstevel@tonic-gate * So fall through 382*7c478bd9Sstevel@tonic-gate */ 383*7c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 384*7c478bd9Sstevel@tonic-gate default: /* need to check .conf file */ 385*7c478bd9Sstevel@tonic-gate drive_type = 0; 386*7c478bd9Sstevel@tonic-gate len = sizeof (density); 387*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, 388*7c478bd9Sstevel@tonic-gate PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "density", 389*7c478bd9Sstevel@tonic-gate (caddr_t)&density, &len) != DDI_PROP_SUCCESS) 390*7c478bd9Sstevel@tonic-gate density[0] = '\0'; 391*7c478bd9Sstevel@tonic-gate len = sizeof (drive_size); 392*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, 393*7c478bd9Sstevel@tonic-gate PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "size", 394*7c478bd9Sstevel@tonic-gate (caddr_t)&drive_size, &len) != DDI_PROP_SUCCESS) 395*7c478bd9Sstevel@tonic-gate drive_size = 0; 396*7c478bd9Sstevel@tonic-gate if (strcmp(density, "DSDD") == 0) { 397*7c478bd9Sstevel@tonic-gate if (drive_size == 5) 398*7c478bd9Sstevel@tonic-gate drive_type = 1; 399*7c478bd9Sstevel@tonic-gate else if (drive_size == 3) 400*7c478bd9Sstevel@tonic-gate drive_type = 3; 401*7c478bd9Sstevel@tonic-gate } else if (strcmp(density, "DSHD") == 0) { 402*7c478bd9Sstevel@tonic-gate if (drive_size == 5) 403*7c478bd9Sstevel@tonic-gate drive_type = 2; 404*7c478bd9Sstevel@tonic-gate else if (drive_size == 3) 405*7c478bd9Sstevel@tonic-gate drive_type = 4; 406*7c478bd9Sstevel@tonic-gate } else if (strcmp(density, "DSED") == 0 && 407*7c478bd9Sstevel@tonic-gate drive_size == 3) { 408*7c478bd9Sstevel@tonic-gate drive_type = 6; 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate break; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate if (drive_type == 0) { 413*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 414*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach failed type: dip %p unit %d", 415*7c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 416*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate drive_num = ddi_get_instance(dip); 420*7c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(fd_state_head, drive_num) != 0) 421*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 422*7c478bd9Sstevel@tonic-gate fdp = ddi_get_soft_state(fd_state_head, drive_num); 423*7c478bd9Sstevel@tonic-gate fjp = fdp->d_obj = ddi_get_driver_private(dip); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate mutex_init(&fjp->fj_lock, NULL, MUTEX_DRIVER, *fjp->fj_iblock); 426*7c478bd9Sstevel@tonic-gate sema_init(&fdp->d_ocsem, 1, NULL, SEMA_DRIVER, NULL); 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate fjp->fj_drive = (struct fd_drive *)(fdp + 1); 429*7c478bd9Sstevel@tonic-gate fjp->fj_chars = (struct fd_char *)(fjp->fj_drive + 1); 430*7c478bd9Sstevel@tonic-gate fjp->fj_attr = (struct fdattr *)(fjp->fj_chars + 1); 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate /* 433*7c478bd9Sstevel@tonic-gate * set default floppy drive characteristics & geometry 434*7c478bd9Sstevel@tonic-gate */ 435*7c478bd9Sstevel@tonic-gate switch (drive_type) { /* assume doubled sided */ 436*7c478bd9Sstevel@tonic-gate case 2: /* 5.25 high density */ 437*7c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_525HD; 438*7c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_5H | 1<<FMT_5D9 | 1<<FMT_5D8 | 439*7c478bd9Sstevel@tonic-gate 1<<FMT_5D4 | 1<<FMT_5D16; 440*7c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_5H; 441*7c478bd9Sstevel@tonic-gate break; 442*7c478bd9Sstevel@tonic-gate case 4: /* 3.5 high density */ 443*7c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_350HD; 444*7c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_3H | 1<<FMT_3I | 1<<FMT_3D; 445*7c478bd9Sstevel@tonic-gate len = sizeof (mode_3D); 446*7c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, 447*7c478bd9Sstevel@tonic-gate PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "mode_3D", 448*7c478bd9Sstevel@tonic-gate (caddr_t)&mode_3D, &len) != DDI_PROP_SUCCESS) 449*7c478bd9Sstevel@tonic-gate mode_3D = 0; 450*7c478bd9Sstevel@tonic-gate if (mode_3D && (fjp->fj_fdc->c_flags & FCFLG_3DMODE)) 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * 3D mode should be enabled only if a dual- 453*7c478bd9Sstevel@tonic-gate * speed 3.5" high-density drive and a 454*7c478bd9Sstevel@tonic-gate * supported floppy controller are installed. 455*7c478bd9Sstevel@tonic-gate */ 456*7c478bd9Sstevel@tonic-gate fdp->d_media |= 1 << FMT_3M; 457*7c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_3H; 458*7c478bd9Sstevel@tonic-gate break; 459*7c478bd9Sstevel@tonic-gate case 1: /* 5.25 double density */ 460*7c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_525DD; 461*7c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_5D9 | 1<<FMT_5D8 | 1<<FMT_5D4 | 462*7c478bd9Sstevel@tonic-gate 1<<FMT_5D16; 463*7c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_5D9; 464*7c478bd9Sstevel@tonic-gate break; 465*7c478bd9Sstevel@tonic-gate case 3: /* 3.5 double density */ 466*7c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_350HD; 467*7c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_3D; 468*7c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_3D; 469*7c478bd9Sstevel@tonic-gate break; 470*7c478bd9Sstevel@tonic-gate case 5: /* 3.5 extended density */ 471*7c478bd9Sstevel@tonic-gate case 6: 472*7c478bd9Sstevel@tonic-gate case 7: 473*7c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_350ED; 474*7c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_3E | 1<<FMT_3H | 1<<FMT_3I | 475*7c478bd9Sstevel@tonic-gate 1<<FMT_3D; 476*7c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_3E; 477*7c478bd9Sstevel@tonic-gate break; 478*7c478bd9Sstevel@tonic-gate case 0: /* no drive defined */ 479*7c478bd9Sstevel@tonic-gate default: 480*7c478bd9Sstevel@tonic-gate goto no_attach; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_deffdtype]; 483*7c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_deffdtype]; 484*7c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_deffdtype], fdp->d_part, 485*7c478bd9Sstevel@tonic-gate sizeof (struct partition) * NDKMAP); 486*7c478bd9Sstevel@tonic-gate fjp->fj_rotspd = fdtypes[fdp->d_deffdtype].fda_rotatespd; 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate sig_minor = drive_num << 3; 489*7c478bd9Sstevel@tonic-gate for (dmdp = fd_minor; dmdp->name != NULL; dmdp++) { 490*7c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, dmdp->name, dmdp->type, 491*7c478bd9Sstevel@tonic-gate sig_minor | dmdp->minor, DDI_NT_FD, NULL) 492*7c478bd9Sstevel@tonic-gate == DDI_FAILURE) { 493*7c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 494*7c478bd9Sstevel@tonic-gate goto no_attach; 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 499*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach: dip %p unit %d", 500*7c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 501*7c478bd9Sstevel@tonic-gate (void) sprintf(name, "fd%d", drive_num); 502*7c478bd9Sstevel@tonic-gate fdp->d_iostat = kstat_create("fd", drive_num, name, "disk", 503*7c478bd9Sstevel@tonic-gate KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT); 504*7c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 505*7c478bd9Sstevel@tonic-gate fdp->d_iostat->ks_lock = &fjp->fj_lock; 506*7c478bd9Sstevel@tonic-gate kstat_install(fdp->d_iostat); 507*7c478bd9Sstevel@tonic-gate } 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate fjp->fj_data = (caddr_t)fdp; 510*7c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_DRVATCH; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* 513*7c478bd9Sstevel@tonic-gate * Add a zero-length attribute to tell the world we support 514*7c478bd9Sstevel@tonic-gate * kernel ioctls (for layered drivers) 515*7c478bd9Sstevel@tonic-gate */ 516*7c478bd9Sstevel@tonic-gate (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 517*7c478bd9Sstevel@tonic-gate DDI_KERNEL_IOCTL, NULL, 0); 518*7c478bd9Sstevel@tonic-gate /* 519*7c478bd9Sstevel@tonic-gate * Ignoring return value because, for passed arguments, only 520*7c478bd9Sstevel@tonic-gate * DDI_SUCCESS is returned. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 523*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate #ifdef NOT_YET 526*7c478bd9Sstevel@tonic-gate case DDI_RESUME: 527*7c478bd9Sstevel@tonic-gate drive_num = ddi_get_instance(dip); 528*7c478bd9Sstevel@tonic-gate if (!(fdp = ddi_get_soft_state(fd_state_head, drive_num))) 529*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 530*7c478bd9Sstevel@tonic-gate fjp = (struct fcu_obj *)fdp->d_obj; 531*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 532*7c478bd9Sstevel@tonic-gate if (!fjp->fj_suspended) { 533*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 534*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate fjp->fj_fdc->c_curpcyl[drive_num & 3] = -1; 537*7c478bd9Sstevel@tonic-gate fjp->fj_suspended = 0; 538*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 539*7c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 540*7c478bd9Sstevel@tonic-gate #endif 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate default: 543*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate no_attach: 546*7c478bd9Sstevel@tonic-gate fjp->fj_drive = NULL; 547*7c478bd9Sstevel@tonic-gate fjp->fj_chars = NULL; 548*7c478bd9Sstevel@tonic-gate fjp->fj_attr = NULL; 549*7c478bd9Sstevel@tonic-gate mutex_destroy(&fjp->fj_lock); 550*7c478bd9Sstevel@tonic-gate sema_destroy(&fdp->d_ocsem); 551*7c478bd9Sstevel@tonic-gate ddi_soft_state_free(fd_state_head, drive_num); 552*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 553*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach failed: dip %p unit %d", 554*7c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 555*7c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 560*7c478bd9Sstevel@tonic-gate static int 561*7c478bd9Sstevel@tonic-gate fd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 562*7c478bd9Sstevel@tonic-gate { 563*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 564*7c478bd9Sstevel@tonic-gate struct fdisk *fdp; 565*7c478bd9Sstevel@tonic-gate int drive_num; 566*7c478bd9Sstevel@tonic-gate int rval = DDI_SUCCESS; 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, (CE_WARN, "fd_detach dip %p", 569*7c478bd9Sstevel@tonic-gate (void *)dip)); 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate drive_num = ddi_get_instance(dip); 572*7c478bd9Sstevel@tonic-gate if (!(fdp = ddi_get_soft_state(fd_state_head, drive_num))) 573*7c478bd9Sstevel@tonic-gate return (rval); 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate switch (cmd) { 576*7c478bd9Sstevel@tonic-gate case DDI_DETACH: 577*7c478bd9Sstevel@tonic-gate if (fd_unit_is_open(fdp)) { 578*7c478bd9Sstevel@tonic-gate rval = EBUSY; 579*7c478bd9Sstevel@tonic-gate break; 580*7c478bd9Sstevel@tonic-gate } 581*7c478bd9Sstevel@tonic-gate kstat_delete(fdp->d_iostat); 582*7c478bd9Sstevel@tonic-gate fdp->d_iostat = NULL; 583*7c478bd9Sstevel@tonic-gate fjp = (struct fcu_obj *)fdp->d_obj; 584*7c478bd9Sstevel@tonic-gate fjp->fj_data = NULL; 585*7c478bd9Sstevel@tonic-gate fjp->fj_drive = NULL; 586*7c478bd9Sstevel@tonic-gate fjp->fj_chars = NULL; 587*7c478bd9Sstevel@tonic-gate fjp->fj_attr = NULL; 588*7c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip); 589*7c478bd9Sstevel@tonic-gate mutex_destroy(&fjp->fj_lock); 590*7c478bd9Sstevel@tonic-gate sema_destroy(&fdp->d_ocsem); 591*7c478bd9Sstevel@tonic-gate ddi_soft_state_free(fd_state_head, drive_num); 592*7c478bd9Sstevel@tonic-gate break; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate #ifdef NOT_YET 595*7c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 596*7c478bd9Sstevel@tonic-gate fjp = (struct fcu_obj *)fdp->d_obj; 597*7c478bd9Sstevel@tonic-gate fjp->fj_suspended = 1; /* Must be before mutex */ 598*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 599*7c478bd9Sstevel@tonic-gate while (fjp->fj_flags & FUNIT_BUSY) { 600*7c478bd9Sstevel@tonic-gate /* Wait for I/O to finish */ 601*7c478bd9Sstevel@tonic-gate cv_wait(&fjp->fj_flags, &fjp->fj_lock); 602*7c478bd9Sstevel@tonic-gate } 603*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 604*7c478bd9Sstevel@tonic-gate break; 605*7c478bd9Sstevel@tonic-gate #endif 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate default: 608*7c478bd9Sstevel@tonic-gate rval = EINVAL; 609*7c478bd9Sstevel@tonic-gate break; 610*7c478bd9Sstevel@tonic-gate } 611*7c478bd9Sstevel@tonic-gate return (rval); 612*7c478bd9Sstevel@tonic-gate } 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate static int 616*7c478bd9Sstevel@tonic-gate fd_part_is_open(struct fdisk *fdp, int part) 617*7c478bd9Sstevel@tonic-gate { 618*7c478bd9Sstevel@tonic-gate int i; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate for (i = 0; i < (OTYPCNT - 1); i++) 621*7c478bd9Sstevel@tonic-gate if (fdp->d_regopen[i] & (1 << part)) 622*7c478bd9Sstevel@tonic-gate return (1); 623*7c478bd9Sstevel@tonic-gate return (0); 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate static int 627*7c478bd9Sstevel@tonic-gate fd_unit_is_open(struct fdisk *fdp) 628*7c478bd9Sstevel@tonic-gate { 629*7c478bd9Sstevel@tonic-gate int i; 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) 632*7c478bd9Sstevel@tonic-gate if (fdp->d_lyropen[i]) 633*7c478bd9Sstevel@tonic-gate return (1); 634*7c478bd9Sstevel@tonic-gate for (i = 0; i < (OTYPCNT - 1); i++) 635*7c478bd9Sstevel@tonic-gate if (fdp->d_regopen[i]) 636*7c478bd9Sstevel@tonic-gate return (1); 637*7c478bd9Sstevel@tonic-gate return (0); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 641*7c478bd9Sstevel@tonic-gate static int 642*7c478bd9Sstevel@tonic-gate fd_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) 643*7c478bd9Sstevel@tonic-gate { 644*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 645*7c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 646*7c478bd9Sstevel@tonic-gate struct partition *pp; 647*7c478bd9Sstevel@tonic-gate dev_t dev; 648*7c478bd9Sstevel@tonic-gate int part, unit; 649*7c478bd9Sstevel@tonic-gate int part_is_open; 650*7c478bd9Sstevel@tonic-gate int rval; 651*7c478bd9Sstevel@tonic-gate uint_t pbit; 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate dev = *devp; 654*7c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 655*7c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 656*7c478bd9Sstevel@tonic-gate return (ENXIO); 657*7c478bd9Sstevel@tonic-gate part = PARTITION(dev); 658*7c478bd9Sstevel@tonic-gate pbit = 1 << part; 659*7c478bd9Sstevel@tonic-gate pp = &fdp->d_part[part]; 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate /* 662*7c478bd9Sstevel@tonic-gate * Serialize opens/closes 663*7c478bd9Sstevel@tonic-gate */ 664*7c478bd9Sstevel@tonic-gate sema_p(&fdp->d_ocsem); 665*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_OPEN, 666*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_open: fd%d part %d flag %x otype %x\n", DRIVE(dev), 667*7c478bd9Sstevel@tonic-gate part, flag, otyp)); 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate /* 670*7c478bd9Sstevel@tonic-gate * Check for previous exclusive open, or trying to exclusive open 671*7c478bd9Sstevel@tonic-gate * An "exclusive open" on any partition is not guaranteed to 672*7c478bd9Sstevel@tonic-gate * protect against opens on another partition that overlaps it. 673*7c478bd9Sstevel@tonic-gate */ 674*7c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) { 675*7c478bd9Sstevel@tonic-gate part_is_open = (fdp->d_lyropen[part] != 0); 676*7c478bd9Sstevel@tonic-gate } else { 677*7c478bd9Sstevel@tonic-gate part_is_open = fd_part_is_open(fdp, part); 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate if ((fdp->d_exclmask & pbit) || ((flag & FEXCL) && part_is_open)) { 680*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_OPEN, (CE_CONT, 681*7c478bd9Sstevel@tonic-gate "fd_open: exclparts %lx openparts %lx lyrcnt %lx pbit %x\n", 682*7c478bd9Sstevel@tonic-gate fdp->d_exclmask, fdp->d_regopen[otyp], fdp->d_lyropen[part], 683*7c478bd9Sstevel@tonic-gate pbit)); 684*7c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 685*7c478bd9Sstevel@tonic-gate return (EBUSY); 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate /* 689*7c478bd9Sstevel@tonic-gate * Ensure that drive is recalibrated on first open of new diskette. 690*7c478bd9Sstevel@tonic-gate */ 691*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 692*7c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit) != 0) { 693*7c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_rcseek(fjp, unit, -1, 0)) { 694*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L2, FDEM_OPEN, 695*7c478bd9Sstevel@tonic-gate (CE_NOTE, "fd_open fd%d: not ready", DRIVE(dev))); 696*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 697*7c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 698*7c478bd9Sstevel@tonic-gate return (ENXIO); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 701*7c478bd9Sstevel@tonic-gate } 702*7c478bd9Sstevel@tonic-gate if (flag & (FNDELAY | FNONBLOCK)) { 703*7c478bd9Sstevel@tonic-gate /* don't attempt access, just return successfully */ 704*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 705*7c478bd9Sstevel@tonic-gate goto out; 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* 709*7c478bd9Sstevel@tonic-gate * auto-sense the density/format of the diskette 710*7c478bd9Sstevel@tonic-gate */ 711*7c478bd9Sstevel@tonic-gate rval = fdgetlabel(fjp, unit); 712*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 713*7c478bd9Sstevel@tonic-gate if (rval) { 714*7c478bd9Sstevel@tonic-gate /* didn't find label (couldn't read anything) */ 715*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L2, FDEM_OPEN, 716*7c478bd9Sstevel@tonic-gate (CE_NOTE, "fd%d: drive not ready", DRIVE(dev))); 717*7c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 718*7c478bd9Sstevel@tonic-gate return (EIO); 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate /* check partition */ 721*7c478bd9Sstevel@tonic-gate if (pp->p_size == 0) { 722*7c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 723*7c478bd9Sstevel@tonic-gate return (ENXIO); 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate /* 726*7c478bd9Sstevel@tonic-gate * if opening for writing, check write protect on diskette 727*7c478bd9Sstevel@tonic-gate */ 728*7c478bd9Sstevel@tonic-gate if ((flag & FWRITE) && (fdp->d_obj->fj_flags & FUNIT_WPROT)) { 729*7c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 730*7c478bd9Sstevel@tonic-gate return (EROFS); 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate out: 734*7c478bd9Sstevel@tonic-gate /* 735*7c478bd9Sstevel@tonic-gate * mark open as having succeeded 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate if (flag & FEXCL) 738*7c478bd9Sstevel@tonic-gate fdp->d_exclmask |= pbit; 739*7c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) 740*7c478bd9Sstevel@tonic-gate fdp->d_lyropen[part]++; 741*7c478bd9Sstevel@tonic-gate else 742*7c478bd9Sstevel@tonic-gate fdp->d_regopen[otyp] |= 1 << part; 743*7c478bd9Sstevel@tonic-gate 744*7c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 745*7c478bd9Sstevel@tonic-gate return (0); 746*7c478bd9Sstevel@tonic-gate } 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate /* 749*7c478bd9Sstevel@tonic-gate * fdgetlabel - read the SunOS label off the diskette 750*7c478bd9Sstevel@tonic-gate * if it can read a valid label it does so, else it will use a 751*7c478bd9Sstevel@tonic-gate * default. If it can`t read the diskette - that is an error. 752*7c478bd9Sstevel@tonic-gate * 753*7c478bd9Sstevel@tonic-gate * RETURNS: 0 for ok - meaning that it could at least read the device, 754*7c478bd9Sstevel@tonic-gate * !0 for error XXX TBD NYD error codes 755*7c478bd9Sstevel@tonic-gate */ 756*7c478bd9Sstevel@tonic-gate static int 757*7c478bd9Sstevel@tonic-gate fdgetlabel(struct fcu_obj *fjp, int unit) 758*7c478bd9Sstevel@tonic-gate { 759*7c478bd9Sstevel@tonic-gate struct dk_label *label; 760*7c478bd9Sstevel@tonic-gate struct fdisk *fdp; 761*7c478bd9Sstevel@tonic-gate char *newlabel; 762*7c478bd9Sstevel@tonic-gate short *sp; 763*7c478bd9Sstevel@tonic-gate short count; 764*7c478bd9Sstevel@tonic-gate short xsum; 765*7c478bd9Sstevel@tonic-gate int tries, try_this; 766*7c478bd9Sstevel@tonic-gate uint_t nexttype; 767*7c478bd9Sstevel@tonic-gate int rval; 768*7c478bd9Sstevel@tonic-gate short oldlvl; 769*7c478bd9Sstevel@tonic-gate int i; 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, 772*7c478bd9Sstevel@tonic-gate (CE_CONT, "fdgetlabel fd unit %d\n", unit)); 773*7c478bd9Sstevel@tonic-gate fdp = (struct fdisk *)fjp->fj_data; 774*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_UNLABELED); 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate /* 777*7c478bd9Sstevel@tonic-gate * get some space to play with the label 778*7c478bd9Sstevel@tonic-gate */ 779*7c478bd9Sstevel@tonic-gate label = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 780*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, (CE_CONT, 781*7c478bd9Sstevel@tonic-gate "fdgetlabel fd unit %d kmem_zalloc: ptr = %p, size = %lx\n", 782*7c478bd9Sstevel@tonic-gate unit, (void *)label, (size_t)sizeof (struct dk_label))); 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate /* 785*7c478bd9Sstevel@tonic-gate * read block 0 (0/0/1) to find the label 786*7c478bd9Sstevel@tonic-gate * (disk is potentially not present or unformatted) 787*7c478bd9Sstevel@tonic-gate */ 788*7c478bd9Sstevel@tonic-gate /* noerrprint since this is a private cmd */ 789*7c478bd9Sstevel@tonic-gate oldlvl = fderrlevel; 790*7c478bd9Sstevel@tonic-gate fderrlevel = FDEP_LMAX; 791*7c478bd9Sstevel@tonic-gate /* 792*7c478bd9Sstevel@tonic-gate * try different characteristics (ie densities) 793*7c478bd9Sstevel@tonic-gate * 794*7c478bd9Sstevel@tonic-gate * if fdp->d_curfdtype is -1 then the current characteristics 795*7c478bd9Sstevel@tonic-gate * were set by ioctl and need to try it as well as everything 796*7c478bd9Sstevel@tonic-gate * in the table 797*7c478bd9Sstevel@tonic-gate */ 798*7c478bd9Sstevel@tonic-gate nexttype = fdp->d_deffdtype; 799*7c478bd9Sstevel@tonic-gate try_this = 1; /* always try the current characteristics */ 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate for (tries = nfdtypes; tries; tries--) { 802*7c478bd9Sstevel@tonic-gate if (try_this) { 803*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate /* try reading last sector of cyl 1, head 0 */ 806*7c478bd9Sstevel@tonic-gate if (!(rval = fjp->fj_ops->fco_rw(fjp, unit, 807*7c478bd9Sstevel@tonic-gate FDREAD, 1, 0, fjp->fj_chars->fdc_secptrack, 808*7c478bd9Sstevel@tonic-gate (caddr_t)label, 809*7c478bd9Sstevel@tonic-gate sizeof (struct dk_label))) && 810*7c478bd9Sstevel@tonic-gate /* and last sector plus 1 of cylinder 1 */ 811*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_rw(fjp, unit, FDREAD, 1, 812*7c478bd9Sstevel@tonic-gate 0, fjp->fj_chars->fdc_secptrack + 1, 813*7c478bd9Sstevel@tonic-gate (caddr_t)label, 814*7c478bd9Sstevel@tonic-gate sizeof (struct dk_label)) && 815*7c478bd9Sstevel@tonic-gate /* and label sector on cylinder 0 */ 816*7c478bd9Sstevel@tonic-gate !(rval = fjp->fj_ops->fco_rw(fjp, unit, 817*7c478bd9Sstevel@tonic-gate FDREAD, 0, 0, 1, (caddr_t)label, 818*7c478bd9Sstevel@tonic-gate sizeof (struct dk_label)))) 819*7c478bd9Sstevel@tonic-gate break; 820*7c478bd9Sstevel@tonic-gate if (rval == ENXIO) 821*7c478bd9Sstevel@tonic-gate break; 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate /* 824*7c478bd9Sstevel@tonic-gate * try the next entry in the characteristics tbl 825*7c478bd9Sstevel@tonic-gate */ 826*7c478bd9Sstevel@tonic-gate fdp->d_curfdtype = (signed char)nexttype; 827*7c478bd9Sstevel@tonic-gate nexttype = (nexttype + 1) % nfdtypes; 828*7c478bd9Sstevel@tonic-gate if ((1 << fdp->d_curfdtype) & fdp->d_media) { 829*7c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_curfdtype]; 830*7c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_curfdtype]; 831*7c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_curfdtype], fdp->d_part, 832*7c478bd9Sstevel@tonic-gate sizeof (struct partition) * NDKMAP); 833*7c478bd9Sstevel@tonic-gate /* 834*7c478bd9Sstevel@tonic-gate * check for a double_density diskette 835*7c478bd9Sstevel@tonic-gate * in a high_density 5.25" drive 836*7c478bd9Sstevel@tonic-gate */ 837*7c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_transfer_rate == 250 && 838*7c478bd9Sstevel@tonic-gate fjp->fj_rotspd > fjp->fj_attr->fda_rotatespd) { 839*7c478bd9Sstevel@tonic-gate /* 840*7c478bd9Sstevel@tonic-gate * yes - adjust transfer rate since we don't 841*7c478bd9Sstevel@tonic-gate * know if we have a 5.25" dual-speed drive 842*7c478bd9Sstevel@tonic-gate */ 843*7c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = 360; 844*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_transfer_rate = 300; 845*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_medium = 5; 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate if ((2 * fjp->fj_chars->fdc_ncyl) == 848*7c478bd9Sstevel@tonic-gate defchar[fdp->d_deffdtype]->fdc_ncyl) { 849*7c478bd9Sstevel@tonic-gate /* yes - adjust steps per cylinder */ 850*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 2; 851*7c478bd9Sstevel@tonic-gate } else 852*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 1; 853*7c478bd9Sstevel@tonic-gate try_this = 1; 854*7c478bd9Sstevel@tonic-gate } else 855*7c478bd9Sstevel@tonic-gate try_this = 0; 856*7c478bd9Sstevel@tonic-gate } 857*7c478bd9Sstevel@tonic-gate fderrlevel = oldlvl; /* print errors again */ 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate if (rval) { 860*7c478bd9Sstevel@tonic-gate fdp->d_curfdtype = fdp->d_deffdtype; 861*7c478bd9Sstevel@tonic-gate goto out; /* couldn't read anything */ 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, 865*7c478bd9Sstevel@tonic-gate (CE_CONT, 866*7c478bd9Sstevel@tonic-gate "fdgetlabel fd unit=%d ncyl=%d nsct=%d step=%d rpm=%d intlv=%d\n", 867*7c478bd9Sstevel@tonic-gate unit, fjp->fj_chars->fdc_ncyl, fjp->fj_chars->fdc_secptrack, 868*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps, fjp->fj_attr->fda_rotatespd, 869*7c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv)); 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate /* 872*7c478bd9Sstevel@tonic-gate * _something_ was read - look for unixtype label 873*7c478bd9Sstevel@tonic-gate */ 874*7c478bd9Sstevel@tonic-gate if (label->dkl_magic != DKL_MAGIC || 875*7c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_sanity != VTOC_SANE) { 876*7c478bd9Sstevel@tonic-gate /* not a label - no magic number */ 877*7c478bd9Sstevel@tonic-gate goto nolabel; /* no errors, but no label */ 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate 880*7c478bd9Sstevel@tonic-gate count = sizeof (struct dk_label) / sizeof (short); 881*7c478bd9Sstevel@tonic-gate sp = (short *)label; 882*7c478bd9Sstevel@tonic-gate xsum = 0; 883*7c478bd9Sstevel@tonic-gate while (count--) 884*7c478bd9Sstevel@tonic-gate xsum ^= *sp++; /* should add up to 0 */ 885*7c478bd9Sstevel@tonic-gate if (xsum) { 886*7c478bd9Sstevel@tonic-gate /* not a label - checksum didn't compute */ 887*7c478bd9Sstevel@tonic-gate goto nolabel; /* no errors, but no label */ 888*7c478bd9Sstevel@tonic-gate } 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate /* 891*7c478bd9Sstevel@tonic-gate * the SunOS label overrides current diskette characteristics 892*7c478bd9Sstevel@tonic-gate */ 893*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl = label->dkl_pcyl; 894*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_nhead = label->dkl_nhead; 895*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack = (label->dkl_nsect * DEV_BSIZE) / 896*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size; 897*7c478bd9Sstevel@tonic-gate if (defchar[fdp->d_deffdtype]->fdc_ncyl == 2 * fjp->fj_chars->fdc_ncyl) 898*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 2; 899*7c478bd9Sstevel@tonic-gate else 900*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 1; 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = label->dkl_rpm; 903*7c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv = label->dkl_intrlv; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate fdp->d_vtoc_version = label->dkl_vtoc.v_version; 906*7c478bd9Sstevel@tonic-gate bcopy(label->dkl_vtoc.v_volume, fdp->d_vtoc_volume, LEN_DKL_VVOL); 907*7c478bd9Sstevel@tonic-gate bcopy(label->dkl_vtoc.v_asciilabel, 908*7c478bd9Sstevel@tonic-gate fdp->d_vtoc_asciilabel, LEN_DKL_ASCII); 909*7c478bd9Sstevel@tonic-gate /* 910*7c478bd9Sstevel@tonic-gate * logical partitions 911*7c478bd9Sstevel@tonic-gate */ 912*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 913*7c478bd9Sstevel@tonic-gate fdp->d_part[i].p_tag = label->dkl_vtoc.v_part[i].p_tag; 914*7c478bd9Sstevel@tonic-gate fdp->d_part[i].p_flag = label->dkl_vtoc.v_part[i].p_flag; 915*7c478bd9Sstevel@tonic-gate fdp->d_part[i].p_start = label->dkl_vtoc.v_part[i].p_start; 916*7c478bd9Sstevel@tonic-gate fdp->d_part[i].p_size = label->dkl_vtoc.v_part[i].p_size; 917*7c478bd9Sstevel@tonic-gate 918*7c478bd9Sstevel@tonic-gate fdp->d_vtoc_timestamp[i] = label->dkl_vtoc.timestamp[i]; 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_LABELOK; 922*7c478bd9Sstevel@tonic-gate goto out; 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate nolabel: 925*7c478bd9Sstevel@tonic-gate /* 926*7c478bd9Sstevel@tonic-gate * if not found, fill in label info from default (mark default used) 927*7c478bd9Sstevel@tonic-gate */ 928*7c478bd9Sstevel@tonic-gate if (fdp->d_media & (1<<FMT_3D)) 929*7c478bd9Sstevel@tonic-gate newlabel = deflabel_35; 930*7c478bd9Sstevel@tonic-gate else /* if (fdp->d_media & (1<<FMT_5D9)) */ 931*7c478bd9Sstevel@tonic-gate newlabel = deflabel_525; 932*7c478bd9Sstevel@tonic-gate bzero(fdp->d_vtoc_volume, LEN_DKL_VVOL); 933*7c478bd9Sstevel@tonic-gate (void) sprintf(fdp->d_vtoc_asciilabel, newlabel, 934*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl, fjp->fj_chars->fdc_nhead, 935*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack); 936*7c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_UNLABELED; 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate out: 939*7c478bd9Sstevel@tonic-gate kmem_free(label, sizeof (struct dk_label)); 940*7c478bd9Sstevel@tonic-gate return (rval); 941*7c478bd9Sstevel@tonic-gate } 942*7c478bd9Sstevel@tonic-gate 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 945*7c478bd9Sstevel@tonic-gate static int 946*7c478bd9Sstevel@tonic-gate fd_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 947*7c478bd9Sstevel@tonic-gate { 948*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 949*7c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 950*7c478bd9Sstevel@tonic-gate int part, part_is_closed; 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 953*7c478bd9Sstevel@tonic-gate int unit; 954*7c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN unit= 955*7c478bd9Sstevel@tonic-gate #else 956*7c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN (void) 957*7c478bd9Sstevel@tonic-gate #endif 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate DEBUG_ASSIGN fd_getdrive(dev, &fjp, &fdp); 960*7c478bd9Sstevel@tonic-gate /* 961*7c478bd9Sstevel@tonic-gate * Ignoring return in non DEBUG mode because success is checked by 962*7c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 963*7c478bd9Sstevel@tonic-gate */ 964*7c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 965*7c478bd9Sstevel@tonic-gate return (ENXIO); 966*7c478bd9Sstevel@tonic-gate part = PARTITION(dev); 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate sema_p(&fdp->d_ocsem); 969*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_CLOS, 970*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_close: fd unit %d part %d otype %x\n", 971*7c478bd9Sstevel@tonic-gate unit, part, otyp)); 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) { 974*7c478bd9Sstevel@tonic-gate if (fdp->d_lyropen[part]) 975*7c478bd9Sstevel@tonic-gate fdp->d_lyropen[part]--; 976*7c478bd9Sstevel@tonic-gate part_is_closed = (fdp->d_lyropen[part] == 0); 977*7c478bd9Sstevel@tonic-gate } else { 978*7c478bd9Sstevel@tonic-gate fdp->d_regopen[otyp] &= ~(1<<part); 979*7c478bd9Sstevel@tonic-gate part_is_closed = 1; 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate if (part_is_closed) { 982*7c478bd9Sstevel@tonic-gate if (part == 2 && fdp->d_exclmask&(1<<part)) 983*7c478bd9Sstevel@tonic-gate fdp->d_exclmask = 0; 984*7c478bd9Sstevel@tonic-gate else 985*7c478bd9Sstevel@tonic-gate fdp->d_exclmask &= ~(1<<part); 986*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_CLOS, 987*7c478bd9Sstevel@tonic-gate (CE_CONT, 988*7c478bd9Sstevel@tonic-gate "fd_close: exclparts %lx openparts %lx lyrcnt %lx\n", 989*7c478bd9Sstevel@tonic-gate fdp->d_exclmask, fdp->d_regopen[otyp], 990*7c478bd9Sstevel@tonic-gate fdp->d_lyropen[part])); 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate if (fd_unit_is_open(fdp) == 0) 993*7c478bd9Sstevel@tonic-gate fdp->d_obj->fj_flags &= ~FUNIT_CHANGED; 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 996*7c478bd9Sstevel@tonic-gate return (0); 997*7c478bd9Sstevel@tonic-gate } 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1000*7c478bd9Sstevel@tonic-gate static int 1001*7c478bd9Sstevel@tonic-gate fd_read(dev_t dev, struct uio *uio, cred_t *cred_p) 1002*7c478bd9Sstevel@tonic-gate { 1003*7c478bd9Sstevel@tonic-gate return (physio(fd_strategy, NULL, dev, B_READ, minphys, uio)); 1004*7c478bd9Sstevel@tonic-gate } 1005*7c478bd9Sstevel@tonic-gate 1006*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1007*7c478bd9Sstevel@tonic-gate static int 1008*7c478bd9Sstevel@tonic-gate fd_write(dev_t dev, struct uio *uio, cred_t *cred_p) 1009*7c478bd9Sstevel@tonic-gate { 1010*7c478bd9Sstevel@tonic-gate return (physio(fd_strategy, NULL, dev, B_WRITE, minphys, uio)); 1011*7c478bd9Sstevel@tonic-gate } 1012*7c478bd9Sstevel@tonic-gate 1013*7c478bd9Sstevel@tonic-gate /* 1014*7c478bd9Sstevel@tonic-gate * fd_strategy 1015*7c478bd9Sstevel@tonic-gate * checks operation, hangs buf struct off fdcntlr, calls fdstart 1016*7c478bd9Sstevel@tonic-gate * if not already busy. Note that if we call start, then the operation 1017*7c478bd9Sstevel@tonic-gate * will already be done on return (start sleeps). 1018*7c478bd9Sstevel@tonic-gate */ 1019*7c478bd9Sstevel@tonic-gate static int 1020*7c478bd9Sstevel@tonic-gate fd_strategy(struct buf *bp) 1021*7c478bd9Sstevel@tonic-gate { 1022*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 1023*7c478bd9Sstevel@tonic-gate struct fdisk *fdp; 1024*7c478bd9Sstevel@tonic-gate struct partition *pp; 1025*7c478bd9Sstevel@tonic-gate 1026*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_STRA, 1027*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_strategy: bp = 0x%p, dev = 0x%lx\n", 1028*7c478bd9Sstevel@tonic-gate (void *)bp, bp->b_edev)); 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate (void) fd_getdrive(bp->b_edev, &fjp, &fdp); 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate /* 1033*7c478bd9Sstevel@tonic-gate * Ignoring return because device exist. 1034*7c478bd9Sstevel@tonic-gate * Returned unit value is not used. 1035*7c478bd9Sstevel@tonic-gate */ 1036*7c478bd9Sstevel@tonic-gate pp = &fdp->d_part[PARTITION(bp->b_edev)]; 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_sec_size > NBPSCTR && (bp->b_blkno & 1)) { 1039*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 1040*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: block %ld is not start of sector!", 1041*7c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), (long)bp->b_blkno)); 1042*7c478bd9Sstevel@tonic-gate bp->b_error = EINVAL; 1043*7c478bd9Sstevel@tonic-gate goto bad; 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate if ((bp->b_blkno > pp->p_size)) { 1047*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 1048*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: block %ld is past the end! (nblk=%ld)", 1049*7c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), (long)bp->b_blkno, pp->p_size)); 1050*7c478bd9Sstevel@tonic-gate bp->b_error = ENOSPC; 1051*7c478bd9Sstevel@tonic-gate goto bad; 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate /* if at end of file, skip out now */ 1055*7c478bd9Sstevel@tonic-gate if (bp->b_blkno == pp->p_size) { 1056*7c478bd9Sstevel@tonic-gate if ((bp->b_flags & B_READ) == 0) { 1057*7c478bd9Sstevel@tonic-gate /* a write needs to get an error! */ 1058*7c478bd9Sstevel@tonic-gate bp->b_error = ENOSPC; 1059*7c478bd9Sstevel@tonic-gate goto bad; 1060*7c478bd9Sstevel@tonic-gate } 1061*7c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; 1062*7c478bd9Sstevel@tonic-gate biodone(bp); 1063*7c478bd9Sstevel@tonic-gate return (0); 1064*7c478bd9Sstevel@tonic-gate } 1065*7c478bd9Sstevel@tonic-gate 1066*7c478bd9Sstevel@tonic-gate /* if operation not a multiple of sector size, is error! */ 1067*7c478bd9Sstevel@tonic-gate if (bp->b_bcount % fjp->fj_chars->fdc_sec_size) { 1068*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 1069*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: count %ld must be a multiple of %d", 1070*7c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), bp->b_bcount, 1071*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size)); 1072*7c478bd9Sstevel@tonic-gate bp->b_error = EINVAL; 1073*7c478bd9Sstevel@tonic-gate goto bad; 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate /* 1077*7c478bd9Sstevel@tonic-gate * Put the buf request in the drive's queue, FIFO. 1078*7c478bd9Sstevel@tonic-gate */ 1079*7c478bd9Sstevel@tonic-gate bp->av_forw = 0; 1080*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1081*7c478bd9Sstevel@tonic-gate if (fdp->d_iostat) 1082*7c478bd9Sstevel@tonic-gate kstat_waitq_enter(KIOSP); 1083*7c478bd9Sstevel@tonic-gate if (fdp->d_actf) 1084*7c478bd9Sstevel@tonic-gate fdp->d_actl->av_forw = bp; 1085*7c478bd9Sstevel@tonic-gate else 1086*7c478bd9Sstevel@tonic-gate fdp->d_actf = bp; 1087*7c478bd9Sstevel@tonic-gate fdp->d_actl = bp; 1088*7c478bd9Sstevel@tonic-gate if (!(fjp->fj_flags & FUNIT_BUSY)) { 1089*7c478bd9Sstevel@tonic-gate fdstart(fjp); 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1092*7c478bd9Sstevel@tonic-gate return (0); 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate bad: 1095*7c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; 1096*7c478bd9Sstevel@tonic-gate bp->b_flags |= B_ERROR; 1097*7c478bd9Sstevel@tonic-gate biodone(bp); 1098*7c478bd9Sstevel@tonic-gate return (0); 1099*7c478bd9Sstevel@tonic-gate } 1100*7c478bd9Sstevel@tonic-gate 1101*7c478bd9Sstevel@tonic-gate /* 1102*7c478bd9Sstevel@tonic-gate * fdstart 1103*7c478bd9Sstevel@tonic-gate * called from fd_strategy() or from fdXXXX() to setup and 1104*7c478bd9Sstevel@tonic-gate * start operations of read or write only (using buf structs). 1105*7c478bd9Sstevel@tonic-gate * Because the chip doesn't handle crossing cylinder boundaries on 1106*7c478bd9Sstevel@tonic-gate * the fly, this takes care of those boundary conditions. Note that 1107*7c478bd9Sstevel@tonic-gate * it sleeps until the operation is done *within fdstart* - so that 1108*7c478bd9Sstevel@tonic-gate * when fdstart returns, the operation is already done. 1109*7c478bd9Sstevel@tonic-gate */ 1110*7c478bd9Sstevel@tonic-gate static void 1111*7c478bd9Sstevel@tonic-gate fdstart(struct fcu_obj *fjp) 1112*7c478bd9Sstevel@tonic-gate { 1113*7c478bd9Sstevel@tonic-gate struct buf *bp; 1114*7c478bd9Sstevel@tonic-gate struct fdisk *fdp = (struct fdisk *)fjp->fj_data; 1115*7c478bd9Sstevel@tonic-gate struct fd_char *chp; 1116*7c478bd9Sstevel@tonic-gate struct partition *pp; 1117*7c478bd9Sstevel@tonic-gate uint_t ptend; 1118*7c478bd9Sstevel@tonic-gate uint_t bincyl; /* (the number of the desired) block in cyl. */ 1119*7c478bd9Sstevel@tonic-gate uint_t blk, len, tlen; 1120*7c478bd9Sstevel@tonic-gate uint_t secpcyl; /* number of sectors per cylinder */ 1121*7c478bd9Sstevel@tonic-gate int cyl, head, sect; 1122*7c478bd9Sstevel@tonic-gate int sctrshft, unit; 1123*7c478bd9Sstevel@tonic-gate caddr_t addr; 1124*7c478bd9Sstevel@tonic-gate 1125*7c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fjp->fj_lock)); 1126*7c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_BUSY; 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate while ((bp = fdp->d_actf) != NULL) { 1129*7c478bd9Sstevel@tonic-gate fdp->d_actf = bp->av_forw; 1130*7c478bd9Sstevel@tonic-gate fdp->d_current = bp; 1131*7c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 1132*7c478bd9Sstevel@tonic-gate kstat_waitq_to_runq(KIOSP); 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1135*7c478bd9Sstevel@tonic-gate 1136*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, 1137*7c478bd9Sstevel@tonic-gate (CE_CONT, "fdstart: bp=0x%p blkno=0x%lx bcount=0x%lx\n", 1138*7c478bd9Sstevel@tonic-gate (void *)bp, (long)bp->b_blkno, bp->b_bcount)); 1139*7c478bd9Sstevel@tonic-gate bp->b_flags &= ~B_ERROR; 1140*7c478bd9Sstevel@tonic-gate bp->b_error = 0; 1141*7c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; /* init resid */ 1142*7c478bd9Sstevel@tonic-gate 1143*7c478bd9Sstevel@tonic-gate ASSERT(DRIVE(bp->b_edev) == ddi_get_instance(fjp->fj_dip)); 1144*7c478bd9Sstevel@tonic-gate unit = fjp->fj_unit; 1145*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 1146*7c478bd9Sstevel@tonic-gate 1147*7c478bd9Sstevel@tonic-gate bp_mapin(bp); /* map in buffers */ 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate pp = &fdp->d_part[PARTITION(bp->b_edev)]; 1150*7c478bd9Sstevel@tonic-gate /* starting blk adjusted for the partition */ 1151*7c478bd9Sstevel@tonic-gate blk = bp->b_blkno + pp->p_start; 1152*7c478bd9Sstevel@tonic-gate ptend = pp->p_start + pp->p_size; /* end of the partition */ 1153*7c478bd9Sstevel@tonic-gate 1154*7c478bd9Sstevel@tonic-gate chp = fjp->fj_chars; 1155*7c478bd9Sstevel@tonic-gate secpcyl = chp->fdc_nhead * chp->fdc_secptrack; 1156*7c478bd9Sstevel@tonic-gate switch (chp->fdc_sec_size) { 1157*7c478bd9Sstevel@tonic-gate /* convert logical block numbers to sector numbers */ 1158*7c478bd9Sstevel@tonic-gate case 1024: 1159*7c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT + 1; 1160*7c478bd9Sstevel@tonic-gate blk >>= 1; 1161*7c478bd9Sstevel@tonic-gate ptend >>= 1; 1162*7c478bd9Sstevel@tonic-gate break; 1163*7c478bd9Sstevel@tonic-gate default: 1164*7c478bd9Sstevel@tonic-gate case NBPSCTR: 1165*7c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT; 1166*7c478bd9Sstevel@tonic-gate break; 1167*7c478bd9Sstevel@tonic-gate case 256: 1168*7c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT - 1; 1169*7c478bd9Sstevel@tonic-gate blk <<= 1; 1170*7c478bd9Sstevel@tonic-gate ptend <<= 1; 1171*7c478bd9Sstevel@tonic-gate break; 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate 1174*7c478bd9Sstevel@tonic-gate /* 1175*7c478bd9Sstevel@tonic-gate * If off the end, limit to actual amount that 1176*7c478bd9Sstevel@tonic-gate * can be transferred. 1177*7c478bd9Sstevel@tonic-gate */ 1178*7c478bd9Sstevel@tonic-gate if ((blk + (bp->b_bcount >> sctrshft)) > ptend) 1179*7c478bd9Sstevel@tonic-gate /* to end of partition */ 1180*7c478bd9Sstevel@tonic-gate len = (ptend - blk) << sctrshft; 1181*7c478bd9Sstevel@tonic-gate else 1182*7c478bd9Sstevel@tonic-gate len = bp->b_bcount; 1183*7c478bd9Sstevel@tonic-gate addr = bp->b_un.b_addr; /* data buffer address */ 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate /* 1186*7c478bd9Sstevel@tonic-gate * now we have the real start blk, addr and len for xfer op 1187*7c478bd9Sstevel@tonic-gate */ 1188*7c478bd9Sstevel@tonic-gate while (len != 0) { 1189*7c478bd9Sstevel@tonic-gate /* start cyl of req */ 1190*7c478bd9Sstevel@tonic-gate cyl = blk / secpcyl; 1191*7c478bd9Sstevel@tonic-gate bincyl = blk % secpcyl; 1192*7c478bd9Sstevel@tonic-gate /* start head of req */ 1193*7c478bd9Sstevel@tonic-gate head = bincyl / chp->fdc_secptrack; 1194*7c478bd9Sstevel@tonic-gate /* start sector of req */ 1195*7c478bd9Sstevel@tonic-gate sect = (bincyl % chp->fdc_secptrack) + 1; 1196*7c478bd9Sstevel@tonic-gate /* 1197*7c478bd9Sstevel@tonic-gate * If the desired block and length will go beyond the 1198*7c478bd9Sstevel@tonic-gate * cylinder end, then limit it to the cylinder end. 1199*7c478bd9Sstevel@tonic-gate */ 1200*7c478bd9Sstevel@tonic-gate if (bp->b_flags & B_READ) { 1201*7c478bd9Sstevel@tonic-gate if (len > ((secpcyl - bincyl) << sctrshft)) 1202*7c478bd9Sstevel@tonic-gate tlen = (secpcyl - bincyl) << sctrshft; 1203*7c478bd9Sstevel@tonic-gate else 1204*7c478bd9Sstevel@tonic-gate tlen = len; 1205*7c478bd9Sstevel@tonic-gate } else { 1206*7c478bd9Sstevel@tonic-gate if (len > 1207*7c478bd9Sstevel@tonic-gate ((chp->fdc_secptrack - sect + 1) << 1208*7c478bd9Sstevel@tonic-gate sctrshft)) 1209*7c478bd9Sstevel@tonic-gate tlen = 1210*7c478bd9Sstevel@tonic-gate (chp->fdc_secptrack - sect + 1) << 1211*7c478bd9Sstevel@tonic-gate sctrshft; 1212*7c478bd9Sstevel@tonic-gate else 1213*7c478bd9Sstevel@tonic-gate tlen = len; 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, (CE_CONT, 1217*7c478bd9Sstevel@tonic-gate " blk 0x%x addr 0x%p len 0x%x " 1218*7c478bd9Sstevel@tonic-gate "cyl %d head %d sec %d\n resid 0x%lx, tlen %d\n", 1219*7c478bd9Sstevel@tonic-gate blk, (void *)addr, len, cyl, head, sect, 1220*7c478bd9Sstevel@tonic-gate bp->b_resid, tlen)); 1221*7c478bd9Sstevel@tonic-gate 1222*7c478bd9Sstevel@tonic-gate /* 1223*7c478bd9Sstevel@tonic-gate * (try to) do the operation - failure returns an errno 1224*7c478bd9Sstevel@tonic-gate */ 1225*7c478bd9Sstevel@tonic-gate bp->b_error = fjp->fj_ops->fco_rw(fjp, unit, 1226*7c478bd9Sstevel@tonic-gate bp->b_flags & B_READ, cyl, head, sect, addr, tlen); 1227*7c478bd9Sstevel@tonic-gate if (bp->b_error != 0) { 1228*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRT, (CE_WARN, 1229*7c478bd9Sstevel@tonic-gate "fdstart: bad exec of bp: 0x%p, err=%d", 1230*7c478bd9Sstevel@tonic-gate (void *)bp, bp->b_error)); 1231*7c478bd9Sstevel@tonic-gate bp->b_flags |= B_ERROR; 1232*7c478bd9Sstevel@tonic-gate break; 1233*7c478bd9Sstevel@tonic-gate } 1234*7c478bd9Sstevel@tonic-gate blk += tlen >> sctrshft; 1235*7c478bd9Sstevel@tonic-gate len -= tlen; 1236*7c478bd9Sstevel@tonic-gate addr += tlen; 1237*7c478bd9Sstevel@tonic-gate bp->b_resid -= tlen; 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, 1240*7c478bd9Sstevel@tonic-gate (CE_CONT, "fdstart done: b_resid %lu, b_count %lu\n", 1241*7c478bd9Sstevel@tonic-gate bp->b_resid, bp->b_bcount)); 1242*7c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 1243*7c478bd9Sstevel@tonic-gate if (bp->b_flags & B_READ) { 1244*7c478bd9Sstevel@tonic-gate KIOSP->reads++; 1245*7c478bd9Sstevel@tonic-gate KIOSP->nread += (bp->b_bcount - bp->b_resid); 1246*7c478bd9Sstevel@tonic-gate } else { 1247*7c478bd9Sstevel@tonic-gate KIOSP->writes++; 1248*7c478bd9Sstevel@tonic-gate KIOSP->nwritten += (bp->b_bcount - bp->b_resid); 1249*7c478bd9Sstevel@tonic-gate } 1250*7c478bd9Sstevel@tonic-gate kstat_runq_exit(KIOSP); 1251*7c478bd9Sstevel@tonic-gate } 1252*7c478bd9Sstevel@tonic-gate bp_mapout(bp); 1253*7c478bd9Sstevel@tonic-gate biodone(bp); 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 1256*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1257*7c478bd9Sstevel@tonic-gate fdp->d_current = 0; 1258*7c478bd9Sstevel@tonic-gate } 1259*7c478bd9Sstevel@tonic-gate fjp->fj_flags ^= FUNIT_BUSY; 1260*7c478bd9Sstevel@tonic-gate } 1261*7c478bd9Sstevel@tonic-gate 1262*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1263*7c478bd9Sstevel@tonic-gate static int 1264*7c478bd9Sstevel@tonic-gate fd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, 1265*7c478bd9Sstevel@tonic-gate int *rval_p) 1266*7c478bd9Sstevel@tonic-gate { 1267*7c478bd9Sstevel@tonic-gate union { 1268*7c478bd9Sstevel@tonic-gate struct dk_cinfo dki; 1269*7c478bd9Sstevel@tonic-gate struct dk_geom dkg; 1270*7c478bd9Sstevel@tonic-gate struct dk_allmap dka; 1271*7c478bd9Sstevel@tonic-gate struct fd_char fdchar; 1272*7c478bd9Sstevel@tonic-gate struct fd_drive drvchar; 1273*7c478bd9Sstevel@tonic-gate int temp; 1274*7c478bd9Sstevel@tonic-gate } cpy; 1275*7c478bd9Sstevel@tonic-gate struct vtoc vtoc; 1276*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 1277*7c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 1278*7c478bd9Sstevel@tonic-gate struct dk_map *dmp; 1279*7c478bd9Sstevel@tonic-gate struct dk_label *label; 1280*7c478bd9Sstevel@tonic-gate int nblks, part, unit; 1281*7c478bd9Sstevel@tonic-gate int rval = 0; 1282*7c478bd9Sstevel@tonic-gate enum dkio_state state; 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 1285*7c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 1286*7c478bd9Sstevel@tonic-gate return (ENXIO); 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_IOCT, 1289*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_ioctl fd unit %d: cmd %x, arg %lx\n", 1290*7c478bd9Sstevel@tonic-gate unit, cmd, arg)); 1291*7c478bd9Sstevel@tonic-gate 1292*7c478bd9Sstevel@tonic-gate switch (cmd) { 1293*7c478bd9Sstevel@tonic-gate case DKIOCINFO: 1294*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_dkinfo(fjp, &cpy.dki); 1295*7c478bd9Sstevel@tonic-gate cpy.dki.dki_cnum = FDCTLR(fjp->fj_unit); 1296*7c478bd9Sstevel@tonic-gate cpy.dki.dki_unit = FDUNIT(fjp->fj_unit); 1297*7c478bd9Sstevel@tonic-gate cpy.dki.dki_partition = PARTITION(dev); 1298*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dki, (void *)arg, sizeof (cpy.dki), flag)) 1299*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1300*7c478bd9Sstevel@tonic-gate break; 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate case DKIOCG_PHYGEOM: 1303*7c478bd9Sstevel@tonic-gate case DKIOCG_VIRTGEOM: 1304*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = fjp->fj_chars->fdc_secptrack; 1305*7c478bd9Sstevel@tonic-gate goto get_geom; 1306*7c478bd9Sstevel@tonic-gate case DKIOCGGEOM: 1307*7c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_LABELOK) 1308*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = (fjp->fj_chars->fdc_secptrack * 1309*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 1310*7c478bd9Sstevel@tonic-gate else 1311*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = fjp->fj_chars->fdc_secptrack; 1312*7c478bd9Sstevel@tonic-gate get_geom: 1313*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_pcyl = fjp->fj_chars->fdc_ncyl; 1314*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_ncyl = fjp->fj_chars->fdc_ncyl; 1315*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nhead = fjp->fj_chars->fdc_nhead; 1316*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_intrlv = fjp->fj_attr->fda_intrlv; 1317*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_rpm = fjp->fj_attr->fda_rotatespd; 1318*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_read_reinstruct = 1319*7c478bd9Sstevel@tonic-gate (int)(cpy.dkg.dkg_nsect * cpy.dkg.dkg_rpm * 4) / 60000; 1320*7c478bd9Sstevel@tonic-gate cpy.dkg.dkg_write_reinstruct = cpy.dkg.dkg_read_reinstruct; 1321*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dkg, (void *)arg, sizeof (cpy.dkg), flag)) 1322*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1323*7c478bd9Sstevel@tonic-gate break; 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate case DKIOCSGEOM: 1326*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.dkg, 1327*7c478bd9Sstevel@tonic-gate sizeof (struct dk_geom), flag)) { 1328*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1329*7c478bd9Sstevel@tonic-gate break; 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1332*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl = cpy.dkg.dkg_ncyl; 1333*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_nhead = cpy.dkg.dkg_nhead; 1334*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack = cpy.dkg.dkg_nsect; 1335*7c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv = cpy.dkg.dkg_intrlv; 1336*7c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = cpy.dkg.dkg_rpm; 1337*7c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 1338*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1339*7c478bd9Sstevel@tonic-gate break; 1340*7c478bd9Sstevel@tonic-gate 1341*7c478bd9Sstevel@tonic-gate /* 1342*7c478bd9Sstevel@tonic-gate * return the map of all logical partitions 1343*7c478bd9Sstevel@tonic-gate */ 1344*7c478bd9Sstevel@tonic-gate case DKIOCGAPART: 1345*7c478bd9Sstevel@tonic-gate /* 1346*7c478bd9Sstevel@tonic-gate * Note the conversion from starting sector number 1347*7c478bd9Sstevel@tonic-gate * to starting cylinder number. 1348*7c478bd9Sstevel@tonic-gate * Return error if division results in a remainder. 1349*7c478bd9Sstevel@tonic-gate */ 1350*7c478bd9Sstevel@tonic-gate nblks = fjp->fj_chars->fdc_nhead * fjp->fj_chars->fdc_secptrack; 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1353*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 1354*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1355*7c478bd9Sstevel@tonic-gate { 1356*7c478bd9Sstevel@tonic-gate struct dk_allmap32 dka32; 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 1359*7c478bd9Sstevel@tonic-gate if ((fdp->d_part[part].p_start % nblks) != 0) 1360*7c478bd9Sstevel@tonic-gate return (EINVAL); 1361*7c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_cylno = 1362*7c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start / nblks; 1363*7c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_nblk = 1364*7c478bd9Sstevel@tonic-gate fdp->d_part[part].p_size; 1365*7c478bd9Sstevel@tonic-gate } 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&dka32, (void *)arg, 1368*7c478bd9Sstevel@tonic-gate sizeof (struct dk_allmap32), flag)) 1369*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1370*7c478bd9Sstevel@tonic-gate 1371*7c478bd9Sstevel@tonic-gate break; 1372*7c478bd9Sstevel@tonic-gate } 1373*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1374*7c478bd9Sstevel@tonic-gate 1375*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1376*7c478bd9Sstevel@tonic-gate 1377*7c478bd9Sstevel@tonic-gate dmp = (struct dk_map *)&cpy.dka; 1378*7c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 1379*7c478bd9Sstevel@tonic-gate if ((fdp->d_part[part].p_start % nblks) != 0) 1380*7c478bd9Sstevel@tonic-gate return (EINVAL); 1381*7c478bd9Sstevel@tonic-gate dmp->dkl_cylno = 1382*7c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start / nblks; 1383*7c478bd9Sstevel@tonic-gate dmp->dkl_nblk = fdp->d_part[part].p_size; 1384*7c478bd9Sstevel@tonic-gate dmp++; 1385*7c478bd9Sstevel@tonic-gate } 1386*7c478bd9Sstevel@tonic-gate 1387*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dka, (void *)arg, 1388*7c478bd9Sstevel@tonic-gate sizeof (struct dk_allmap), flag)) 1389*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1390*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1391*7c478bd9Sstevel@tonic-gate break; 1392*7c478bd9Sstevel@tonic-gate 1393*7c478bd9Sstevel@tonic-gate } 1394*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate break; 1397*7c478bd9Sstevel@tonic-gate 1398*7c478bd9Sstevel@tonic-gate /* 1399*7c478bd9Sstevel@tonic-gate * Set the map of all logical partitions 1400*7c478bd9Sstevel@tonic-gate */ 1401*7c478bd9Sstevel@tonic-gate case DKIOCSAPART: 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1404*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 1405*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1406*7c478bd9Sstevel@tonic-gate { 1407*7c478bd9Sstevel@tonic-gate struct dk_allmap32 dka32; 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &dka32, 1410*7c478bd9Sstevel@tonic-gate sizeof (dka32), flag)) { 1411*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1412*7c478bd9Sstevel@tonic-gate break; 1413*7c478bd9Sstevel@tonic-gate } 1414*7c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 1415*7c478bd9Sstevel@tonic-gate cpy.dka.dka_map[part].dkl_cylno = 1416*7c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_cylno; 1417*7c478bd9Sstevel@tonic-gate cpy.dka.dka_map[part].dkl_nblk = 1418*7c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_nblk; 1419*7c478bd9Sstevel@tonic-gate } 1420*7c478bd9Sstevel@tonic-gate break; 1421*7c478bd9Sstevel@tonic-gate } 1422*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1425*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.dka, sizeof (cpy.dka), flag)) 1426*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1427*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1428*7c478bd9Sstevel@tonic-gate 1429*7c478bd9Sstevel@tonic-gate break; 1430*7c478bd9Sstevel@tonic-gate } 1431*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1432*7c478bd9Sstevel@tonic-gate 1433*7c478bd9Sstevel@tonic-gate if (rval != 0) 1434*7c478bd9Sstevel@tonic-gate break; 1435*7c478bd9Sstevel@tonic-gate 1436*7c478bd9Sstevel@tonic-gate dmp = (struct dk_map *)&cpy.dka; 1437*7c478bd9Sstevel@tonic-gate nblks = fjp->fj_chars->fdc_nhead * 1438*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack; 1439*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1440*7c478bd9Sstevel@tonic-gate /* 1441*7c478bd9Sstevel@tonic-gate * Note the conversion from starting cylinder number 1442*7c478bd9Sstevel@tonic-gate * to starting sector number. 1443*7c478bd9Sstevel@tonic-gate */ 1444*7c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 1445*7c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start = dmp->dkl_cylno * 1446*7c478bd9Sstevel@tonic-gate nblks; 1447*7c478bd9Sstevel@tonic-gate fdp->d_part[part].p_size = dmp->dkl_nblk; 1448*7c478bd9Sstevel@tonic-gate dmp++; 1449*7c478bd9Sstevel@tonic-gate } 1450*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate break; 1453*7c478bd9Sstevel@tonic-gate 1454*7c478bd9Sstevel@tonic-gate case DKIOCGVTOC: 1455*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1456*7c478bd9Sstevel@tonic-gate 1457*7c478bd9Sstevel@tonic-gate /* 1458*7c478bd9Sstevel@tonic-gate * Exit if the diskette has no label. 1459*7c478bd9Sstevel@tonic-gate * Also, get the label to make sure the correct one is 1460*7c478bd9Sstevel@tonic-gate * being used since the diskette may have changed 1461*7c478bd9Sstevel@tonic-gate */ 1462*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 1463*7c478bd9Sstevel@tonic-gate rval = fdgetlabel(fjp, unit); 1464*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 1465*7c478bd9Sstevel@tonic-gate if (rval) { 1466*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1467*7c478bd9Sstevel@tonic-gate rval = EINVAL; 1468*7c478bd9Sstevel@tonic-gate break; 1469*7c478bd9Sstevel@tonic-gate } 1470*7c478bd9Sstevel@tonic-gate 1471*7c478bd9Sstevel@tonic-gate fd_build_user_vtoc(fjp, fdp, &vtoc); 1472*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1473*7c478bd9Sstevel@tonic-gate 1474*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1475*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 1476*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1477*7c478bd9Sstevel@tonic-gate { 1478*7c478bd9Sstevel@tonic-gate struct vtoc32 vtoc32; 1479*7c478bd9Sstevel@tonic-gate 1480*7c478bd9Sstevel@tonic-gate vtoctovtoc32(vtoc, vtoc32); 1481*7c478bd9Sstevel@tonic-gate 1482*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&vtoc32, (void *)arg, 1483*7c478bd9Sstevel@tonic-gate sizeof (vtoc32), flag)) 1484*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1485*7c478bd9Sstevel@tonic-gate 1486*7c478bd9Sstevel@tonic-gate break; 1487*7c478bd9Sstevel@tonic-gate } 1488*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1489*7c478bd9Sstevel@tonic-gate 1490*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1491*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&vtoc, (void *)arg, 1492*7c478bd9Sstevel@tonic-gate sizeof (vtoc), flag)) 1493*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1494*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1495*7c478bd9Sstevel@tonic-gate break; 1496*7c478bd9Sstevel@tonic-gate } 1497*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1498*7c478bd9Sstevel@tonic-gate 1499*7c478bd9Sstevel@tonic-gate break; 1500*7c478bd9Sstevel@tonic-gate 1501*7c478bd9Sstevel@tonic-gate case DKIOCSVTOC: 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1504*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 1505*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1506*7c478bd9Sstevel@tonic-gate { 1507*7c478bd9Sstevel@tonic-gate struct vtoc32 vtoc32; 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &vtoc32, 1510*7c478bd9Sstevel@tonic-gate sizeof (vtoc32), flag)) { 1511*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1512*7c478bd9Sstevel@tonic-gate break; 1513*7c478bd9Sstevel@tonic-gate } 1514*7c478bd9Sstevel@tonic-gate 1515*7c478bd9Sstevel@tonic-gate vtoc32tovtoc(vtoc32, vtoc); 1516*7c478bd9Sstevel@tonic-gate 1517*7c478bd9Sstevel@tonic-gate break; 1518*7c478bd9Sstevel@tonic-gate } 1519*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1520*7c478bd9Sstevel@tonic-gate 1521*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1522*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &vtoc, sizeof (vtoc), flag)) 1523*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1524*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1525*7c478bd9Sstevel@tonic-gate break; 1526*7c478bd9Sstevel@tonic-gate } 1527*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate if (rval != 0) 1530*7c478bd9Sstevel@tonic-gate break; 1531*7c478bd9Sstevel@tonic-gate 1532*7c478bd9Sstevel@tonic-gate 1533*7c478bd9Sstevel@tonic-gate label = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1536*7c478bd9Sstevel@tonic-gate 1537*7c478bd9Sstevel@tonic-gate if ((rval = fd_build_label_vtoc(fjp, fdp, &vtoc, label)) == 0) { 1538*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 1539*7c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_rw(fjp, unit, FDWRITE, 1540*7c478bd9Sstevel@tonic-gate 0, 0, 1, (caddr_t)label, sizeof (struct dk_label)); 1541*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 1542*7c478bd9Sstevel@tonic-gate } 1543*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1544*7c478bd9Sstevel@tonic-gate kmem_free(label, sizeof (struct dk_label)); 1545*7c478bd9Sstevel@tonic-gate break; 1546*7c478bd9Sstevel@tonic-gate 1547*7c478bd9Sstevel@tonic-gate case DKIOCSTATE: 1548*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_IOCT, 1549*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_ioctl fd unit %d: DKIOCSTATE\n", unit)); 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &state, sizeof (int), flag)) { 1552*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1553*7c478bd9Sstevel@tonic-gate break; 1554*7c478bd9Sstevel@tonic-gate } 1555*7c478bd9Sstevel@tonic-gate 1556*7c478bd9Sstevel@tonic-gate rval = fd_check_media(dev, state); 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&fdp->d_media_state, (void *)arg, 1559*7c478bd9Sstevel@tonic-gate sizeof (int), flag)) 1560*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1561*7c478bd9Sstevel@tonic-gate break; 1562*7c478bd9Sstevel@tonic-gate 1563*7c478bd9Sstevel@tonic-gate case FDIOGCHAR: 1564*7c478bd9Sstevel@tonic-gate if (ddi_copyout(fjp->fj_chars, (void *)arg, 1565*7c478bd9Sstevel@tonic-gate sizeof (struct fd_char), flag)) 1566*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1567*7c478bd9Sstevel@tonic-gate break; 1568*7c478bd9Sstevel@tonic-gate 1569*7c478bd9Sstevel@tonic-gate case FDIOSCHAR: 1570*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.fdchar, 1571*7c478bd9Sstevel@tonic-gate sizeof (struct fd_char), flag)) { 1572*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1573*7c478bd9Sstevel@tonic-gate break; 1574*7c478bd9Sstevel@tonic-gate } 1575*7c478bd9Sstevel@tonic-gate switch (cpy.fdchar.fdc_transfer_rate) { 1576*7c478bd9Sstevel@tonic-gate case 417: 1577*7c478bd9Sstevel@tonic-gate if ((fdp->d_media & (1 << FMT_3M)) == 0) { 1578*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 1579*7c478bd9Sstevel@tonic-gate "fdioschar:Medium density not supported\n"); 1580*7c478bd9Sstevel@tonic-gate rval = EINVAL; 1581*7c478bd9Sstevel@tonic-gate break; 1582*7c478bd9Sstevel@tonic-gate } 1583*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1584*7c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = 360; 1585*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1586*7c478bd9Sstevel@tonic-gate /* cpy.fdchar.fdc_transfer_rate = 500; */ 1587*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1588*7c478bd9Sstevel@tonic-gate case 1000: 1589*7c478bd9Sstevel@tonic-gate case 500: 1590*7c478bd9Sstevel@tonic-gate case 300: 1591*7c478bd9Sstevel@tonic-gate case 250: 1592*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1593*7c478bd9Sstevel@tonic-gate *(fjp->fj_chars) = cpy.fdchar; 1594*7c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 1595*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 1596*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1597*7c478bd9Sstevel@tonic-gate 1598*7c478bd9Sstevel@tonic-gate break; 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate default: 1601*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 1602*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: FDIOSCHAR odd " 1603*7c478bd9Sstevel@tonic-gate "xfer rate %dkbs", 1604*7c478bd9Sstevel@tonic-gate unit, cpy.fdchar.fdc_transfer_rate)); 1605*7c478bd9Sstevel@tonic-gate rval = EINVAL; 1606*7c478bd9Sstevel@tonic-gate break; 1607*7c478bd9Sstevel@tonic-gate } 1608*7c478bd9Sstevel@tonic-gate break; 1609*7c478bd9Sstevel@tonic-gate 1610*7c478bd9Sstevel@tonic-gate /* 1611*7c478bd9Sstevel@tonic-gate * set all characteristics and geometry to the defaults 1612*7c478bd9Sstevel@tonic-gate */ 1613*7c478bd9Sstevel@tonic-gate case FDDEFGEOCHAR: 1614*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1615*7c478bd9Sstevel@tonic-gate fdp->d_curfdtype = fdp->d_deffdtype; 1616*7c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_curfdtype]; 1617*7c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_curfdtype]; 1618*7c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_curfdtype], 1619*7c478bd9Sstevel@tonic-gate fdp->d_part, sizeof (struct partition) * NDKMAP); 1620*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 1621*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1622*7c478bd9Sstevel@tonic-gate break; 1623*7c478bd9Sstevel@tonic-gate 1624*7c478bd9Sstevel@tonic-gate case FDEJECT: /* eject disk */ 1625*7c478bd9Sstevel@tonic-gate case DKIOCEJECT: 1626*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 1627*7c478bd9Sstevel@tonic-gate rval = ENOSYS; 1628*7c478bd9Sstevel@tonic-gate break; 1629*7c478bd9Sstevel@tonic-gate 1630*7c478bd9Sstevel@tonic-gate case FDGETCHANGE: /* disk changed */ 1631*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.temp, sizeof (int), flag)) { 1632*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1633*7c478bd9Sstevel@tonic-gate break; 1634*7c478bd9Sstevel@tonic-gate } 1635*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1636*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 1637*7c478bd9Sstevel@tonic-gate 1638*7c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHANGED) 1639*7c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_HISTORY; 1640*7c478bd9Sstevel@tonic-gate else 1641*7c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_HISTORY; 1642*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHANGED; 1643*7c478bd9Sstevel@tonic-gate 1644*7c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 1645*7c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_DETECTED; 1646*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_resetchng(fjp, unit); 1647*7c478bd9Sstevel@tonic-gate /* 1648*7c478bd9Sstevel@tonic-gate * check diskette again only if it was removed 1649*7c478bd9Sstevel@tonic-gate */ 1650*7c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 1651*7c478bd9Sstevel@tonic-gate /* 1652*7c478bd9Sstevel@tonic-gate * no diskette is present 1653*7c478bd9Sstevel@tonic-gate */ 1654*7c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_CURRENT; 1655*7c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHGDET) 1656*7c478bd9Sstevel@tonic-gate /* 1657*7c478bd9Sstevel@tonic-gate * again no diskette; not a new change 1658*7c478bd9Sstevel@tonic-gate */ 1659*7c478bd9Sstevel@tonic-gate cpy.temp ^= FDGC_DETECTED; 1660*7c478bd9Sstevel@tonic-gate else 1661*7c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_CHGDET; 1662*7c478bd9Sstevel@tonic-gate } else { 1663*7c478bd9Sstevel@tonic-gate /* 1664*7c478bd9Sstevel@tonic-gate * a new diskette is present 1665*7c478bd9Sstevel@tonic-gate */ 1666*7c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_CURRENT; 1667*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 1668*7c478bd9Sstevel@tonic-gate } 1669*7c478bd9Sstevel@tonic-gate } else { 1670*7c478bd9Sstevel@tonic-gate cpy.temp &= ~(FDGC_DETECTED | FDGC_CURRENT); 1671*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 1672*7c478bd9Sstevel@tonic-gate } 1673*7c478bd9Sstevel@tonic-gate /* 1674*7c478bd9Sstevel@tonic-gate * also get state of write protection 1675*7c478bd9Sstevel@tonic-gate */ 1676*7c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_WPROT) { 1677*7c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_CURWPROT; 1678*7c478bd9Sstevel@tonic-gate } else { 1679*7c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_CURWPROT; 1680*7c478bd9Sstevel@tonic-gate } 1681*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 1682*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1683*7c478bd9Sstevel@tonic-gate 1684*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.temp, (void *)arg, sizeof (int), flag)) 1685*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1686*7c478bd9Sstevel@tonic-gate break; 1687*7c478bd9Sstevel@tonic-gate 1688*7c478bd9Sstevel@tonic-gate case FDGETDRIVECHAR: 1689*7c478bd9Sstevel@tonic-gate if (ddi_copyout(fjp->fj_drive, (void *)arg, 1690*7c478bd9Sstevel@tonic-gate sizeof (struct fd_drive), flag)) 1691*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1692*7c478bd9Sstevel@tonic-gate break; 1693*7c478bd9Sstevel@tonic-gate 1694*7c478bd9Sstevel@tonic-gate case FDSETDRIVECHAR: 1695*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.drvchar, 1696*7c478bd9Sstevel@tonic-gate sizeof (struct fd_drive), flag)) { 1697*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1698*7c478bd9Sstevel@tonic-gate break; 1699*7c478bd9Sstevel@tonic-gate } 1700*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 1701*7c478bd9Sstevel@tonic-gate *(fjp->fj_drive) = cpy.drvchar; 1702*7c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 1703*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 1704*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 1705*7c478bd9Sstevel@tonic-gate break; 1706*7c478bd9Sstevel@tonic-gate 1707*7c478bd9Sstevel@tonic-gate case DKIOCREMOVABLE: { 1708*7c478bd9Sstevel@tonic-gate int i = 1; 1709*7c478bd9Sstevel@tonic-gate 1710*7c478bd9Sstevel@tonic-gate /* no brainer: floppies are always removable */ 1711*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&i, (void *)arg, sizeof (int), flag)) { 1712*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1713*7c478bd9Sstevel@tonic-gate } 1714*7c478bd9Sstevel@tonic-gate break; 1715*7c478bd9Sstevel@tonic-gate } 1716*7c478bd9Sstevel@tonic-gate 1717*7c478bd9Sstevel@tonic-gate case DKIOCGMEDIAINFO: 1718*7c478bd9Sstevel@tonic-gate rval = fd_get_media_info(fjp, (caddr_t)arg, flag); 1719*7c478bd9Sstevel@tonic-gate break; 1720*7c478bd9Sstevel@tonic-gate 1721*7c478bd9Sstevel@tonic-gate case FDIOCMD: 1722*7c478bd9Sstevel@tonic-gate { 1723*7c478bd9Sstevel@tonic-gate struct fd_cmd fc; 1724*7c478bd9Sstevel@tonic-gate int cyl, head, spc, spt; 1725*7c478bd9Sstevel@tonic-gate 1726*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1727*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 1728*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 1729*7c478bd9Sstevel@tonic-gate { 1730*7c478bd9Sstevel@tonic-gate struct fd_cmd32 fc32; 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &fc32, 1733*7c478bd9Sstevel@tonic-gate sizeof (fc32), flag)) { 1734*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1735*7c478bd9Sstevel@tonic-gate break; 1736*7c478bd9Sstevel@tonic-gate } 1737*7c478bd9Sstevel@tonic-gate 1738*7c478bd9Sstevel@tonic-gate fc.fdc_cmd = fc32.fdc_cmd; 1739*7c478bd9Sstevel@tonic-gate fc.fdc_flags = fc32.fdc_flags; 1740*7c478bd9Sstevel@tonic-gate fc.fdc_blkno = fc32.fdc_blkno; 1741*7c478bd9Sstevel@tonic-gate fc.fdc_secnt = fc32.fdc_secnt; 1742*7c478bd9Sstevel@tonic-gate fc.fdc_bufaddr = (caddr_t)(uintptr_t)fc32.fdc_bufaddr; 1743*7c478bd9Sstevel@tonic-gate fc.fdc_buflen = fc32.fdc_buflen; 1744*7c478bd9Sstevel@tonic-gate 1745*7c478bd9Sstevel@tonic-gate break; 1746*7c478bd9Sstevel@tonic-gate } 1747*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1750*7c478bd9Sstevel@tonic-gate 1751*7c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &fc, sizeof (fc), flag)) { 1752*7c478bd9Sstevel@tonic-gate rval = EFAULT; 1753*7c478bd9Sstevel@tonic-gate break; 1754*7c478bd9Sstevel@tonic-gate } 1755*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 1756*7c478bd9Sstevel@tonic-gate break; 1757*7c478bd9Sstevel@tonic-gate } 1758*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 1759*7c478bd9Sstevel@tonic-gate 1760*7c478bd9Sstevel@tonic-gate if (rval != 0) 1761*7c478bd9Sstevel@tonic-gate break; 1762*7c478bd9Sstevel@tonic-gate 1763*7c478bd9Sstevel@tonic-gate if (fc.fdc_cmd == FDCMD_READ || fc.fdc_cmd == FDCMD_WRITE) { 1764*7c478bd9Sstevel@tonic-gate auto struct iovec aiov; 1765*7c478bd9Sstevel@tonic-gate auto struct uio auio; 1766*7c478bd9Sstevel@tonic-gate struct uio *uio = &auio; 1767*7c478bd9Sstevel@tonic-gate 1768*7c478bd9Sstevel@tonic-gate spc = (fc.fdc_cmd == FDCMD_READ)? B_READ: B_WRITE; 1769*7c478bd9Sstevel@tonic-gate 1770*7c478bd9Sstevel@tonic-gate bzero(&auio, sizeof (struct uio)); 1771*7c478bd9Sstevel@tonic-gate bzero(&aiov, sizeof (struct iovec)); 1772*7c478bd9Sstevel@tonic-gate aiov.iov_base = fc.fdc_bufaddr; 1773*7c478bd9Sstevel@tonic-gate aiov.iov_len = (uint_t)fc.fdc_secnt * 1774*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size; 1775*7c478bd9Sstevel@tonic-gate uio->uio_iov = &aiov; 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 1; 1778*7c478bd9Sstevel@tonic-gate uio->uio_resid = aiov.iov_len; 1779*7c478bd9Sstevel@tonic-gate uio->uio_segflg = UIO_USERSPACE; 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate rval = physio(fd_strategy, (struct buf *)0, dev, 1782*7c478bd9Sstevel@tonic-gate spc, minphys, uio); 1783*7c478bd9Sstevel@tonic-gate break; 1784*7c478bd9Sstevel@tonic-gate } else if (fc.fdc_cmd == FDCMD_FORMAT_TRACK) { 1785*7c478bd9Sstevel@tonic-gate spt = fjp->fj_chars->fdc_secptrack; /* sec/trk */ 1786*7c478bd9Sstevel@tonic-gate spc = fjp->fj_chars->fdc_nhead * spt; /* sec/cyl */ 1787*7c478bd9Sstevel@tonic-gate cyl = fc.fdc_blkno / spc; 1788*7c478bd9Sstevel@tonic-gate head = (fc.fdc_blkno % spc) / spt; 1789*7c478bd9Sstevel@tonic-gate if ((cyl | head) == 0) 1790*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= 1791*7c478bd9Sstevel@tonic-gate ~(FUNIT_LABELOK | FUNIT_UNLABELED); 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_FORM, 1794*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_format cyl %d, hd %d\n", cyl, head)); 1795*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 1796*7c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_format(fjp, unit, cyl, head, 1797*7c478bd9Sstevel@tonic-gate (int)fc.fdc_flags); 1798*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 1799*7c478bd9Sstevel@tonic-gate 1800*7c478bd9Sstevel@tonic-gate break; 1801*7c478bd9Sstevel@tonic-gate } 1802*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 1803*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: FDIOCSCMD not yet complete", 1804*7c478bd9Sstevel@tonic-gate unit)); 1805*7c478bd9Sstevel@tonic-gate rval = EINVAL; 1806*7c478bd9Sstevel@tonic-gate break; 1807*7c478bd9Sstevel@tonic-gate } 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate case FDRAW: 1810*7c478bd9Sstevel@tonic-gate rval = fd_rawioctl(fjp, unit, (caddr_t)arg, flag); 1811*7c478bd9Sstevel@tonic-gate break; 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate default: 1814*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 1815*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: invalid ioctl 0x%x", 1816*7c478bd9Sstevel@tonic-gate unit, cmd)); 1817*7c478bd9Sstevel@tonic-gate rval = ENOTTY; 1818*7c478bd9Sstevel@tonic-gate break; 1819*7c478bd9Sstevel@tonic-gate } 1820*7c478bd9Sstevel@tonic-gate return (rval); 1821*7c478bd9Sstevel@tonic-gate } 1822*7c478bd9Sstevel@tonic-gate 1823*7c478bd9Sstevel@tonic-gate static void 1824*7c478bd9Sstevel@tonic-gate fd_build_user_vtoc(struct fcu_obj *fjp, struct fdisk *fdp, struct vtoc *vtocp) 1825*7c478bd9Sstevel@tonic-gate { 1826*7c478bd9Sstevel@tonic-gate struct partition *vpart; 1827*7c478bd9Sstevel@tonic-gate int i; 1828*7c478bd9Sstevel@tonic-gate int xblk; 1829*7c478bd9Sstevel@tonic-gate 1830*7c478bd9Sstevel@tonic-gate /* 1831*7c478bd9Sstevel@tonic-gate * Return vtoc structure fields in the provided VTOC area, addressed 1832*7c478bd9Sstevel@tonic-gate * by *vtocp. 1833*7c478bd9Sstevel@tonic-gate * 1834*7c478bd9Sstevel@tonic-gate */ 1835*7c478bd9Sstevel@tonic-gate bzero(vtocp, sizeof (struct vtoc)); 1836*7c478bd9Sstevel@tonic-gate 1837*7c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_bootinfo, 1838*7c478bd9Sstevel@tonic-gate vtocp->v_bootinfo, sizeof (vtocp->v_bootinfo)); 1839*7c478bd9Sstevel@tonic-gate 1840*7c478bd9Sstevel@tonic-gate vtocp->v_sanity = VTOC_SANE; 1841*7c478bd9Sstevel@tonic-gate vtocp->v_version = fdp->d_vtoc_version; 1842*7c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_volume, vtocp->v_volume, LEN_DKL_VVOL); 1843*7c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_LABELOK) { 1844*7c478bd9Sstevel@tonic-gate vtocp->v_sectorsz = DEV_BSIZE; 1845*7c478bd9Sstevel@tonic-gate xblk = 1; 1846*7c478bd9Sstevel@tonic-gate } else { 1847*7c478bd9Sstevel@tonic-gate vtocp->v_sectorsz = fjp->fj_chars->fdc_sec_size; 1848*7c478bd9Sstevel@tonic-gate xblk = vtocp->v_sectorsz / DEV_BSIZE; 1849*7c478bd9Sstevel@tonic-gate } 1850*7c478bd9Sstevel@tonic-gate vtocp->v_nparts = 3; /* <= NDKMAP; */ 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate /* 1853*7c478bd9Sstevel@tonic-gate * Copy partitioning information. 1854*7c478bd9Sstevel@tonic-gate */ 1855*7c478bd9Sstevel@tonic-gate bcopy(fdp->d_part, vtocp->v_part, sizeof (struct partition) * NDKMAP); 1856*7c478bd9Sstevel@tonic-gate for (i = NDKMAP, vpart = vtocp->v_part; i && (xblk > 1); i--, vpart++) { 1857*7c478bd9Sstevel@tonic-gate /* correct partition info if sector size > 512 bytes */ 1858*7c478bd9Sstevel@tonic-gate vpart->p_start /= xblk; 1859*7c478bd9Sstevel@tonic-gate vpart->p_size /= xblk; 1860*7c478bd9Sstevel@tonic-gate } 1861*7c478bd9Sstevel@tonic-gate 1862*7c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_timestamp, 1863*7c478bd9Sstevel@tonic-gate vtocp->timestamp, sizeof (fdp->d_vtoc_timestamp)); 1864*7c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_asciilabel, vtocp->v_asciilabel, LEN_DKL_ASCII); 1865*7c478bd9Sstevel@tonic-gate } 1866*7c478bd9Sstevel@tonic-gate 1867*7c478bd9Sstevel@tonic-gate 1868*7c478bd9Sstevel@tonic-gate static int 1869*7c478bd9Sstevel@tonic-gate fd_build_label_vtoc(struct fcu_obj *fjp, struct fdisk *fdp, struct vtoc *vtocp, 1870*7c478bd9Sstevel@tonic-gate struct dk_label *labelp) 1871*7c478bd9Sstevel@tonic-gate { 1872*7c478bd9Sstevel@tonic-gate struct partition *vpart; 1873*7c478bd9Sstevel@tonic-gate int i; 1874*7c478bd9Sstevel@tonic-gate int nblks; 1875*7c478bd9Sstevel@tonic-gate int ncyl; 1876*7c478bd9Sstevel@tonic-gate ushort_t sum, *sp; 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate 1879*7c478bd9Sstevel@tonic-gate /* 1880*7c478bd9Sstevel@tonic-gate * Sanity-check the vtoc 1881*7c478bd9Sstevel@tonic-gate */ 1882*7c478bd9Sstevel@tonic-gate if (vtocp->v_sanity != VTOC_SANE || 1883*7c478bd9Sstevel@tonic-gate vtocp->v_nparts > NDKMAP || vtocp->v_nparts <= 0) { 1884*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_IOCT, 1885*7c478bd9Sstevel@tonic-gate (CE_WARN, "fd_build_label: sanity check on vtoc failed")); 1886*7c478bd9Sstevel@tonic-gate return (EINVAL); 1887*7c478bd9Sstevel@tonic-gate } 1888*7c478bd9Sstevel@tonic-gate 1889*7c478bd9Sstevel@tonic-gate /* 1890*7c478bd9Sstevel@tonic-gate * before copying the vtoc, the partition information in it should be 1891*7c478bd9Sstevel@tonic-gate * checked against the information the driver already has on the 1892*7c478bd9Sstevel@tonic-gate * diskette. 1893*7c478bd9Sstevel@tonic-gate */ 1894*7c478bd9Sstevel@tonic-gate 1895*7c478bd9Sstevel@tonic-gate nblks = (fjp->fj_chars->fdc_nhead * fjp->fj_chars->fdc_secptrack * 1896*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 1897*7c478bd9Sstevel@tonic-gate if (nblks == 0 || fjp->fj_chars->fdc_ncyl == 0) 1898*7c478bd9Sstevel@tonic-gate return (EFAULT); 1899*7c478bd9Sstevel@tonic-gate vpart = vtocp->v_part; 1900*7c478bd9Sstevel@tonic-gate 1901*7c478bd9Sstevel@tonic-gate /* 1902*7c478bd9Sstevel@tonic-gate * Check the partition information in the vtoc. The starting sectors 1903*7c478bd9Sstevel@tonic-gate * must lie along cylinder boundaries. (NDKMAP entries are checked 1904*7c478bd9Sstevel@tonic-gate * to ensure that the unused entries are set to 0 if vtoc->v_nparts 1905*7c478bd9Sstevel@tonic-gate * is less than NDKMAP) 1906*7c478bd9Sstevel@tonic-gate */ 1907*7c478bd9Sstevel@tonic-gate for (i = NDKMAP; i; i--) { 1908*7c478bd9Sstevel@tonic-gate if ((vpart->p_start % nblks) != 0) { 1909*7c478bd9Sstevel@tonic-gate return (EINVAL); 1910*7c478bd9Sstevel@tonic-gate } 1911*7c478bd9Sstevel@tonic-gate ncyl = vpart->p_start / nblks; 1912*7c478bd9Sstevel@tonic-gate ncyl += vpart->p_size / nblks; 1913*7c478bd9Sstevel@tonic-gate if ((vpart->p_size % nblks) != 0) 1914*7c478bd9Sstevel@tonic-gate ncyl++; 1915*7c478bd9Sstevel@tonic-gate if (ncyl > (long)fjp->fj_chars->fdc_ncyl) { 1916*7c478bd9Sstevel@tonic-gate return (EINVAL); 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate vpart++; 1919*7c478bd9Sstevel@tonic-gate } 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate 1922*7c478bd9Sstevel@tonic-gate bcopy(vtocp->v_bootinfo, fdp->d_vtoc_bootinfo, 1923*7c478bd9Sstevel@tonic-gate sizeof (vtocp->v_bootinfo)); 1924*7c478bd9Sstevel@tonic-gate fdp->d_vtoc_version = vtocp->v_version; 1925*7c478bd9Sstevel@tonic-gate bcopy(vtocp->v_volume, fdp->d_vtoc_volume, LEN_DKL_VVOL); 1926*7c478bd9Sstevel@tonic-gate 1927*7c478bd9Sstevel@tonic-gate /* 1928*7c478bd9Sstevel@tonic-gate * Copy partitioning information. 1929*7c478bd9Sstevel@tonic-gate */ 1930*7c478bd9Sstevel@tonic-gate bcopy(vtocp->v_part, fdp->d_part, sizeof (struct partition) * NDKMAP); 1931*7c478bd9Sstevel@tonic-gate bcopy(vtocp->timestamp, fdp->d_vtoc_timestamp, 1932*7c478bd9Sstevel@tonic-gate sizeof (fdp->d_vtoc_timestamp)); 1933*7c478bd9Sstevel@tonic-gate bcopy(vtocp->v_asciilabel, fdp->d_vtoc_asciilabel, LEN_DKL_ASCII); 1934*7c478bd9Sstevel@tonic-gate 1935*7c478bd9Sstevel@tonic-gate /* 1936*7c478bd9Sstevel@tonic-gate * construct the diskette label in supplied buffer 1937*7c478bd9Sstevel@tonic-gate */ 1938*7c478bd9Sstevel@tonic-gate 1939*7c478bd9Sstevel@tonic-gate /* Put appropriate vtoc structure fields into the disk label */ 1940*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[0] = (uint32_t)vtocp->v_bootinfo[0]; 1941*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[1] = (uint32_t)vtocp->v_bootinfo[1]; 1942*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[2] = (uint32_t)vtocp->v_bootinfo[2]; 1943*7c478bd9Sstevel@tonic-gate 1944*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_sanity = vtocp->v_sanity; 1945*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_version = vtocp->v_version; 1946*7c478bd9Sstevel@tonic-gate 1947*7c478bd9Sstevel@tonic-gate bcopy(vtocp->v_volume, labelp->dkl_vtoc.v_volume, LEN_DKL_VVOL); 1948*7c478bd9Sstevel@tonic-gate 1949*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_nparts = vtocp->v_nparts; 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate bcopy(vtocp->v_reserved, labelp->dkl_vtoc.v_reserved, 1952*7c478bd9Sstevel@tonic-gate sizeof (labelp->dkl_vtoc.v_reserved)); 1953*7c478bd9Sstevel@tonic-gate 1954*7c478bd9Sstevel@tonic-gate for (i = 0; i < (int)vtocp->v_nparts; i++) { 1955*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_tag = vtocp->v_part[i].p_tag; 1956*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_flag = vtocp->v_part[i].p_flag; 1957*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_start = vtocp->v_part[i].p_start; 1958*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_size = vtocp->v_part[i].p_size; 1959*7c478bd9Sstevel@tonic-gate } 1960*7c478bd9Sstevel@tonic-gate 1961*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 1962*7c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_timestamp[i] = vtocp->timestamp[i]; 1963*7c478bd9Sstevel@tonic-gate } 1964*7c478bd9Sstevel@tonic-gate bcopy(vtocp->v_asciilabel, labelp->dkl_asciilabel, LEN_DKL_ASCII); 1965*7c478bd9Sstevel@tonic-gate 1966*7c478bd9Sstevel@tonic-gate 1967*7c478bd9Sstevel@tonic-gate labelp->dkl_pcyl = fjp->fj_chars->fdc_ncyl; 1968*7c478bd9Sstevel@tonic-gate labelp->dkl_ncyl = fjp->fj_chars->fdc_ncyl; 1969*7c478bd9Sstevel@tonic-gate labelp->dkl_nhead = fjp->fj_chars->fdc_nhead; 1970*7c478bd9Sstevel@tonic-gate /* 1971*7c478bd9Sstevel@tonic-gate * The fdc_secptrack field of the fd_char structure is the number 1972*7c478bd9Sstevel@tonic-gate * of sectors per track where the sectors are fdc_sec_size. 1973*7c478bd9Sstevel@tonic-gate * The dkl_nsect field of the dk_label structure is the number of 1974*7c478bd9Sstevel@tonic-gate * DEV_BSIZE (512) byte sectors per track. 1975*7c478bd9Sstevel@tonic-gate */ 1976*7c478bd9Sstevel@tonic-gate labelp->dkl_nsect = (fjp->fj_chars->fdc_secptrack * 1977*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 1978*7c478bd9Sstevel@tonic-gate labelp->dkl_intrlv = fjp->fj_attr->fda_intrlv; 1979*7c478bd9Sstevel@tonic-gate labelp->dkl_rpm = fjp->fj_attr->fda_rotatespd; 1980*7c478bd9Sstevel@tonic-gate labelp->dkl_read_reinstruct = 1981*7c478bd9Sstevel@tonic-gate (int)(labelp->dkl_nsect * labelp->dkl_rpm * 4) / 60000; 1982*7c478bd9Sstevel@tonic-gate labelp->dkl_write_reinstruct = labelp->dkl_read_reinstruct; 1983*7c478bd9Sstevel@tonic-gate 1984*7c478bd9Sstevel@tonic-gate labelp->dkl_magic = DKL_MAGIC; 1985*7c478bd9Sstevel@tonic-gate 1986*7c478bd9Sstevel@tonic-gate sum = 0; 1987*7c478bd9Sstevel@tonic-gate labelp->dkl_cksum = 0; 1988*7c478bd9Sstevel@tonic-gate sp = (ushort_t *)labelp; 1989*7c478bd9Sstevel@tonic-gate while (sp < &(labelp->dkl_cksum)) { 1990*7c478bd9Sstevel@tonic-gate sum ^= *sp++; 1991*7c478bd9Sstevel@tonic-gate } 1992*7c478bd9Sstevel@tonic-gate labelp->dkl_cksum = sum; 1993*7c478bd9Sstevel@tonic-gate 1994*7c478bd9Sstevel@tonic-gate return (0); 1995*7c478bd9Sstevel@tonic-gate } 1996*7c478bd9Sstevel@tonic-gate 1997*7c478bd9Sstevel@tonic-gate static int 1998*7c478bd9Sstevel@tonic-gate fd_rawioctl(struct fcu_obj *fjp, int unit, caddr_t arg, int mode) 1999*7c478bd9Sstevel@tonic-gate { 2000*7c478bd9Sstevel@tonic-gate struct fd_raw fdr; 2001*7c478bd9Sstevel@tonic-gate char *arg_result = NULL; 2002*7c478bd9Sstevel@tonic-gate int flag = B_READ; 2003*7c478bd9Sstevel@tonic-gate int rval = 0; 2004*7c478bd9Sstevel@tonic-gate caddr_t uaddr; 2005*7c478bd9Sstevel@tonic-gate uint_t ucount; 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_RAWI, 2008*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_rawioctl: cmd[0]=0x%x\n", fdr.fdr_cmd[0])); 2009*7c478bd9Sstevel@tonic-gate 2010*7c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_medium != 3 && fjp->fj_chars->fdc_medium != 5) { 2011*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "fd_rawioctl: Medium density not supported\n"); 2012*7c478bd9Sstevel@tonic-gate return (ENXIO); 2013*7c478bd9Sstevel@tonic-gate } 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 2016*7c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 2017*7c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 2018*7c478bd9Sstevel@tonic-gate { 2019*7c478bd9Sstevel@tonic-gate struct fd_raw32 fdr32; 2020*7c478bd9Sstevel@tonic-gate 2021*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, &fdr32, sizeof (fdr32), mode)) 2022*7c478bd9Sstevel@tonic-gate return (EFAULT); 2023*7c478bd9Sstevel@tonic-gate 2024*7c478bd9Sstevel@tonic-gate bcopy(fdr32.fdr_cmd, fdr.fdr_cmd, sizeof (fdr.fdr_cmd)); 2025*7c478bd9Sstevel@tonic-gate fdr.fdr_cnum = fdr32.fdr_cnum; 2026*7c478bd9Sstevel@tonic-gate fdr.fdr_nbytes = fdr32.fdr_nbytes; 2027*7c478bd9Sstevel@tonic-gate fdr.fdr_addr = (caddr_t)(uintptr_t)fdr32.fdr_addr; 2028*7c478bd9Sstevel@tonic-gate arg_result = ((struct fd_raw32 *)arg)->fdr_result; 2029*7c478bd9Sstevel@tonic-gate 2030*7c478bd9Sstevel@tonic-gate break; 2031*7c478bd9Sstevel@tonic-gate } 2032*7c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 2033*7c478bd9Sstevel@tonic-gate #endif /* ! _MULTI_DATAMODEL */ 2034*7c478bd9Sstevel@tonic-gate 2035*7c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, &fdr, sizeof (fdr), mode)) 2036*7c478bd9Sstevel@tonic-gate return (EFAULT); 2037*7c478bd9Sstevel@tonic-gate 2038*7c478bd9Sstevel@tonic-gate arg_result = ((struct fd_raw *)arg)->fdr_result; 2039*7c478bd9Sstevel@tonic-gate 2040*7c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 2041*7c478bd9Sstevel@tonic-gate break; 2042*7c478bd9Sstevel@tonic-gate } 2043*7c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 2044*7c478bd9Sstevel@tonic-gate 2045*7c478bd9Sstevel@tonic-gate 2046*7c478bd9Sstevel@tonic-gate 2047*7c478bd9Sstevel@tonic-gate /* 2048*7c478bd9Sstevel@tonic-gate * copy user address & nbytes from raw_req so that we can 2049*7c478bd9Sstevel@tonic-gate * put kernel address in req structure 2050*7c478bd9Sstevel@tonic-gate */ 2051*7c478bd9Sstevel@tonic-gate uaddr = fdr.fdr_addr; 2052*7c478bd9Sstevel@tonic-gate ucount = (uint_t)fdr.fdr_nbytes; 2053*7c478bd9Sstevel@tonic-gate unit &= 3; 2054*7c478bd9Sstevel@tonic-gate 2055*7c478bd9Sstevel@tonic-gate switch (fdr.fdr_cmd[0] & 0x0f) { 2056*7c478bd9Sstevel@tonic-gate 2057*7c478bd9Sstevel@tonic-gate case FDRAW_FORMAT: 2058*7c478bd9Sstevel@tonic-gate ucount += 16; 2059*7c478bd9Sstevel@tonic-gate fdr.fdr_addr = kmem_zalloc(ucount, KM_SLEEP); 2060*7c478bd9Sstevel@tonic-gate if (ddi_copyin(uaddr, fdr.fdr_addr, 2061*7c478bd9Sstevel@tonic-gate (size_t)fdr.fdr_nbytes, mode)) { 2062*7c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 2063*7c478bd9Sstevel@tonic-gate return (EFAULT); 2064*7c478bd9Sstevel@tonic-gate } 2065*7c478bd9Sstevel@tonic-gate if ((*fdr.fdr_addr | fdr.fdr_addr[1]) == 0) 2066*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 2067*7c478bd9Sstevel@tonic-gate flag = B_WRITE; 2068*7c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 2069*7c478bd9Sstevel@tonic-gate break; 2070*7c478bd9Sstevel@tonic-gate 2071*7c478bd9Sstevel@tonic-gate case FDRAW_WRCMD: 2072*7c478bd9Sstevel@tonic-gate case FDRAW_WRITEDEL: 2073*7c478bd9Sstevel@tonic-gate flag = B_WRITE; 2074*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 2075*7c478bd9Sstevel@tonic-gate case FDRAW_RDCMD: 2076*7c478bd9Sstevel@tonic-gate case FDRAW_READDEL: 2077*7c478bd9Sstevel@tonic-gate case FDRAW_READTRACK: 2078*7c478bd9Sstevel@tonic-gate if (ucount) { 2079*7c478bd9Sstevel@tonic-gate /* 2080*7c478bd9Sstevel@tonic-gate * In SunOS 4.X, we used to as_fault things in. 2081*7c478bd9Sstevel@tonic-gate * We really cannot do this in 5.0/SVr4. Unless 2082*7c478bd9Sstevel@tonic-gate * someone really believes that speed is of the 2083*7c478bd9Sstevel@tonic-gate * essence here, it is just much simpler to do 2084*7c478bd9Sstevel@tonic-gate * this in kernel space and use copyin/copyout. 2085*7c478bd9Sstevel@tonic-gate */ 2086*7c478bd9Sstevel@tonic-gate fdr.fdr_addr = kmem_alloc((size_t)ucount, KM_SLEEP); 2087*7c478bd9Sstevel@tonic-gate if (flag == B_WRITE) { 2088*7c478bd9Sstevel@tonic-gate if (ddi_copyin(uaddr, fdr.fdr_addr, ucount, 2089*7c478bd9Sstevel@tonic-gate mode)) { 2090*7c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 2091*7c478bd9Sstevel@tonic-gate return (EFAULT); 2092*7c478bd9Sstevel@tonic-gate } 2093*7c478bd9Sstevel@tonic-gate } 2094*7c478bd9Sstevel@tonic-gate } else 2095*7c478bd9Sstevel@tonic-gate return (EINVAL); 2096*7c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 2097*7c478bd9Sstevel@tonic-gate break; 2098*7c478bd9Sstevel@tonic-gate 2099*7c478bd9Sstevel@tonic-gate case FDRAW_READID: 2100*7c478bd9Sstevel@tonic-gate case FDRAW_REZERO: 2101*7c478bd9Sstevel@tonic-gate case FDRAW_SEEK: 2102*7c478bd9Sstevel@tonic-gate case FDRAW_SENSE_DRV: 2103*7c478bd9Sstevel@tonic-gate ucount = 0; 2104*7c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 2105*7c478bd9Sstevel@tonic-gate break; 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate case FDRAW_SPECIFY: 2108*7c478bd9Sstevel@tonic-gate fdr.fdr_cmd[2] &= 0xfe; /* keep NoDMA bit clear */ 2109*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 2110*7c478bd9Sstevel@tonic-gate case FDRAW_SENSE_INT: 2111*7c478bd9Sstevel@tonic-gate ucount = 0; 2112*7c478bd9Sstevel@tonic-gate break; 2113*7c478bd9Sstevel@tonic-gate 2114*7c478bd9Sstevel@tonic-gate default: 2115*7c478bd9Sstevel@tonic-gate return (EINVAL); 2116*7c478bd9Sstevel@tonic-gate } 2117*7c478bd9Sstevel@tonic-gate 2118*7c478bd9Sstevel@tonic-gate /* 2119*7c478bd9Sstevel@tonic-gate * Note that we ignore any error returns from controller 2120*7c478bd9Sstevel@tonic-gate * This is the way the driver has been, and it may be 2121*7c478bd9Sstevel@tonic-gate * that the raw ioctl senders simply don't want to 2122*7c478bd9Sstevel@tonic-gate * see any errors returned in this fashion. 2123*7c478bd9Sstevel@tonic-gate */ 2124*7c478bd9Sstevel@tonic-gate 2125*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 2126*7c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_rwioctl(fjp, unit, (caddr_t)&fdr); 2127*7c478bd9Sstevel@tonic-gate 2128*7c478bd9Sstevel@tonic-gate if (ucount && flag == B_READ && rval == 0) { 2129*7c478bd9Sstevel@tonic-gate if (ddi_copyout(fdr.fdr_addr, uaddr, ucount, mode)) { 2130*7c478bd9Sstevel@tonic-gate rval = EFAULT; 2131*7c478bd9Sstevel@tonic-gate } 2132*7c478bd9Sstevel@tonic-gate } 2133*7c478bd9Sstevel@tonic-gate if (ddi_copyout(fdr.fdr_result, arg_result, sizeof (fdr.fdr_cmd), mode)) 2134*7c478bd9Sstevel@tonic-gate rval = EFAULT; 2135*7c478bd9Sstevel@tonic-gate 2136*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 2137*7c478bd9Sstevel@tonic-gate if (ucount) 2138*7c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 2139*7c478bd9Sstevel@tonic-gate 2140*7c478bd9Sstevel@tonic-gate return (rval); 2141*7c478bd9Sstevel@tonic-gate } 2142*7c478bd9Sstevel@tonic-gate 2143*7c478bd9Sstevel@tonic-gate /* 2144*7c478bd9Sstevel@tonic-gate * property operation routine. return the number of blocks for the partition 2145*7c478bd9Sstevel@tonic-gate * in question or forward the request to the property facilities. 2146*7c478bd9Sstevel@tonic-gate */ 2147*7c478bd9Sstevel@tonic-gate static int 2148*7c478bd9Sstevel@tonic-gate fd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 2149*7c478bd9Sstevel@tonic-gate char *name, caddr_t valuep, int *lengthp) 2150*7c478bd9Sstevel@tonic-gate { 2151*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 2152*7c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 2153*7c478bd9Sstevel@tonic-gate uint64_t nblocks64; 2154*7c478bd9Sstevel@tonic-gate 2155*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_PROP, 2156*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_prop_op: dip %p %s\n", (void *)dip, name)); 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate /* 2159*7c478bd9Sstevel@tonic-gate * Our dynamic properties are all device specific and size oriented. 2160*7c478bd9Sstevel@tonic-gate * Requests issued under conditions where size is valid are passed 2161*7c478bd9Sstevel@tonic-gate * to ddi_prop_op_nblocks with the size information, otherwise the 2162*7c478bd9Sstevel@tonic-gate * request is passed to ddi_prop_op. 2163*7c478bd9Sstevel@tonic-gate */ 2164*7c478bd9Sstevel@tonic-gate if (dev == DDI_DEV_T_ANY) { 2165*7c478bd9Sstevel@tonic-gate pass: return (ddi_prop_op(dev, dip, prop_op, mod_flags, 2166*7c478bd9Sstevel@tonic-gate name, valuep, lengthp)); 2167*7c478bd9Sstevel@tonic-gate } else { 2168*7c478bd9Sstevel@tonic-gate /* 2169*7c478bd9Sstevel@tonic-gate * Ignoring return value because success is checked by 2170*7c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 2171*7c478bd9Sstevel@tonic-gate */ 2172*7c478bd9Sstevel@tonic-gate (void) fd_getdrive(dev, &fjp, &fdp); 2173*7c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 2174*7c478bd9Sstevel@tonic-gate goto pass; 2175*7c478bd9Sstevel@tonic-gate 2176*7c478bd9Sstevel@tonic-gate /* get nblocks value */ 2177*7c478bd9Sstevel@tonic-gate nblocks64 = (ulong_t)fdp->d_part[PARTITION(dev)].p_size; 2178*7c478bd9Sstevel@tonic-gate 2179*7c478bd9Sstevel@tonic-gate return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags, 2180*7c478bd9Sstevel@tonic-gate name, valuep, lengthp, nblocks64)); 2181*7c478bd9Sstevel@tonic-gate } 2182*7c478bd9Sstevel@tonic-gate } 2183*7c478bd9Sstevel@tonic-gate 2184*7c478bd9Sstevel@tonic-gate static void 2185*7c478bd9Sstevel@tonic-gate fd_media_watch(void *arg) 2186*7c478bd9Sstevel@tonic-gate { 2187*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 2188*7c478bd9Sstevel@tonic-gate struct fdisk *fdp; 2189*7c478bd9Sstevel@tonic-gate 2190*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2191*7c478bd9Sstevel@tonic-gate int unit; 2192*7c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN unit= 2193*7c478bd9Sstevel@tonic-gate #else 2194*7c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN (void) 2195*7c478bd9Sstevel@tonic-gate #endif 2196*7c478bd9Sstevel@tonic-gate DEBUG_ASSIGN fd_getdrive((dev_t)arg, &fjp, &fdp); 2197*7c478bd9Sstevel@tonic-gate /* 2198*7c478bd9Sstevel@tonic-gate * Ignoring return in non DEBUG mode because device exist. 2199*7c478bd9Sstevel@tonic-gate * Returned unit value is not used. 2200*7c478bd9Sstevel@tonic-gate */ 2201*7c478bd9Sstevel@tonic-gate 2202*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_IOCT, 2203*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_media_watch unit %d\n", unit)); 2204*7c478bd9Sstevel@tonic-gate 2205*7c478bd9Sstevel@tonic-gate /* 2206*7c478bd9Sstevel@tonic-gate * fd_get_media_state() cannot be called from this timeout function 2207*7c478bd9Sstevel@tonic-gate * because the floppy drive has to be selected first, and that could 2208*7c478bd9Sstevel@tonic-gate * force this function to sleep (while waiting for the select 2209*7c478bd9Sstevel@tonic-gate * semaphore). 2210*7c478bd9Sstevel@tonic-gate * Instead, just wakeup up driver. 2211*7c478bd9Sstevel@tonic-gate */ 2212*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 2213*7c478bd9Sstevel@tonic-gate cv_broadcast(&fdp->d_statecv); 2214*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 2215*7c478bd9Sstevel@tonic-gate } 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate enum dkio_state 2218*7c478bd9Sstevel@tonic-gate fd_get_media_state(struct fcu_obj *fjp, int unit) 2219*7c478bd9Sstevel@tonic-gate { 2220*7c478bd9Sstevel@tonic-gate enum dkio_state state; 2221*7c478bd9Sstevel@tonic-gate 2222*7c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 2223*7c478bd9Sstevel@tonic-gate /* recheck disk only if DSKCHG "high" */ 2224*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_resetchng(fjp, unit); 2225*7c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 2226*7c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHGDET) { 2227*7c478bd9Sstevel@tonic-gate /* 2228*7c478bd9Sstevel@tonic-gate * again no diskette; not a new change 2229*7c478bd9Sstevel@tonic-gate */ 2230*7c478bd9Sstevel@tonic-gate state = DKIO_NONE; 2231*7c478bd9Sstevel@tonic-gate } else { 2232*7c478bd9Sstevel@tonic-gate /* 2233*7c478bd9Sstevel@tonic-gate * a new change; diskette was ejected 2234*7c478bd9Sstevel@tonic-gate */ 2235*7c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_CHGDET; 2236*7c478bd9Sstevel@tonic-gate state = DKIO_EJECTED; 2237*7c478bd9Sstevel@tonic-gate } 2238*7c478bd9Sstevel@tonic-gate } else { 2239*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 2240*7c478bd9Sstevel@tonic-gate state = DKIO_INSERTED; 2241*7c478bd9Sstevel@tonic-gate } 2242*7c478bd9Sstevel@tonic-gate } else { 2243*7c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 2244*7c478bd9Sstevel@tonic-gate state = DKIO_INSERTED; 2245*7c478bd9Sstevel@tonic-gate } 2246*7c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_IOCT, 2247*7c478bd9Sstevel@tonic-gate (CE_CONT, "fd_get_media_state unit %d: state %x\n", unit, state)); 2248*7c478bd9Sstevel@tonic-gate return (state); 2249*7c478bd9Sstevel@tonic-gate } 2250*7c478bd9Sstevel@tonic-gate 2251*7c478bd9Sstevel@tonic-gate static int 2252*7c478bd9Sstevel@tonic-gate fd_check_media(dev_t dev, enum dkio_state state) 2253*7c478bd9Sstevel@tonic-gate { 2254*7c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 2255*7c478bd9Sstevel@tonic-gate struct fdisk *fdp; 2256*7c478bd9Sstevel@tonic-gate int unit; 2257*7c478bd9Sstevel@tonic-gate int err; 2258*7c478bd9Sstevel@tonic-gate 2259*7c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 2260*7c478bd9Sstevel@tonic-gate 2261*7c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 2262*7c478bd9Sstevel@tonic-gate 2263*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 2264*7c478bd9Sstevel@tonic-gate fdp->d_media_state = fd_get_media_state(fjp, unit); 2265*7c478bd9Sstevel@tonic-gate fdp->d_media_timeout = drv_usectohz(fd_check_media_time); 2266*7c478bd9Sstevel@tonic-gate 2267*7c478bd9Sstevel@tonic-gate while (fdp->d_media_state == state) { 2268*7c478bd9Sstevel@tonic-gate /* release the controller and drive */ 2269*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 2270*7c478bd9Sstevel@tonic-gate 2271*7c478bd9Sstevel@tonic-gate /* turn on timer */ 2272*7c478bd9Sstevel@tonic-gate fdp->d_media_timeout_id = timeout(fd_media_watch, 2273*7c478bd9Sstevel@tonic-gate (void *)dev, fdp->d_media_timeout); 2274*7c478bd9Sstevel@tonic-gate 2275*7c478bd9Sstevel@tonic-gate if (cv_wait_sig(&fdp->d_statecv, &fjp->fj_lock) == 0) { 2276*7c478bd9Sstevel@tonic-gate fdp->d_media_timeout = 0; 2277*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 2278*7c478bd9Sstevel@tonic-gate return (EINTR); 2279*7c478bd9Sstevel@tonic-gate } 2280*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 2281*7c478bd9Sstevel@tonic-gate fdp->d_media_state = fd_get_media_state(fjp, unit); 2282*7c478bd9Sstevel@tonic-gate } 2283*7c478bd9Sstevel@tonic-gate 2284*7c478bd9Sstevel@tonic-gate if (fdp->d_media_state == DKIO_INSERTED) { 2285*7c478bd9Sstevel@tonic-gate err = fdgetlabel(fjp, unit); 2286*7c478bd9Sstevel@tonic-gate if (err) { 2287*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 2288*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 2289*7c478bd9Sstevel@tonic-gate return (EIO); 2290*7c478bd9Sstevel@tonic-gate } 2291*7c478bd9Sstevel@tonic-gate } 2292*7c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 2293*7c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 2294*7c478bd9Sstevel@tonic-gate return (0); 2295*7c478bd9Sstevel@tonic-gate } 2296*7c478bd9Sstevel@tonic-gate 2297*7c478bd9Sstevel@tonic-gate /* 2298*7c478bd9Sstevel@tonic-gate * fd_get_media_info : 2299*7c478bd9Sstevel@tonic-gate * Collects medium information for 2300*7c478bd9Sstevel@tonic-gate * DKIOCGMEDIAINFO ioctl. 2301*7c478bd9Sstevel@tonic-gate */ 2302*7c478bd9Sstevel@tonic-gate 2303*7c478bd9Sstevel@tonic-gate static int 2304*7c478bd9Sstevel@tonic-gate fd_get_media_info(struct fcu_obj *fjp, caddr_t buf, int flag) 2305*7c478bd9Sstevel@tonic-gate { 2306*7c478bd9Sstevel@tonic-gate struct dk_minfo media_info; 2307*7c478bd9Sstevel@tonic-gate int err = 0; 2308*7c478bd9Sstevel@tonic-gate 2309*7c478bd9Sstevel@tonic-gate media_info.dki_media_type = DK_FLOPPY; 2310*7c478bd9Sstevel@tonic-gate media_info.dki_lbsize = fjp->fj_chars->fdc_sec_size; 2311*7c478bd9Sstevel@tonic-gate media_info.dki_capacity = fjp->fj_chars->fdc_ncyl * 2312*7c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack * fjp->fj_chars->fdc_nhead; 2313*7c478bd9Sstevel@tonic-gate 2314*7c478bd9Sstevel@tonic-gate if (ddi_copyout(&media_info, buf, sizeof (struct dk_minfo), flag)) 2315*7c478bd9Sstevel@tonic-gate err = EFAULT; 2316*7c478bd9Sstevel@tonic-gate return (err); 2317*7c478bd9Sstevel@tonic-gate } 2318