17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*19397407SSherry Moore * Common Development and Distribution License (the "License"). 6*19397407SSherry Moore * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*19397407SSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Floppy Disk driver 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* 327c478bd9Sstevel@tonic-gate * Set CMOS feature: 337c478bd9Sstevel@tonic-gate * CMOS_CONF_MEM: CMOS memory contains configuration info 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate #define CMOS_CONF_MEM 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <sys/types.h> 387c478bd9Sstevel@tonic-gate #include <sys/param.h> 397c478bd9Sstevel@tonic-gate #include <sys/systm.h> 407c478bd9Sstevel@tonic-gate #include <sys/buf.h> 417c478bd9Sstevel@tonic-gate #include <sys/file.h> 427c478bd9Sstevel@tonic-gate #include <sys/open.h> 437c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 447c478bd9Sstevel@tonic-gate #include <sys/uio.h> 457c478bd9Sstevel@tonic-gate #include <sys/conf.h> 467c478bd9Sstevel@tonic-gate #include <sys/stat.h> 477c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 487c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 497c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 507c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 517c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 527c478bd9Sstevel@tonic-gate #include <sys/kstat.h> 537c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 547c478bd9Sstevel@tonic-gate #include <sys/ddidmareq.h> 557c478bd9Sstevel@tonic-gate #include <sys/fdio.h> 567c478bd9Sstevel@tonic-gate #include <sys/fdc.h> 577c478bd9Sstevel@tonic-gate #include <sys/fd_debug.h> 587c478bd9Sstevel@tonic-gate #include <sys/fdmedia.h> 597c478bd9Sstevel@tonic-gate #include <sys/debug.h> 607c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * Local Function Prototypes 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate static int fd_unit_is_open(struct fdisk *); 667c478bd9Sstevel@tonic-gate static int fdgetlabel(struct fcu_obj *, int); 677c478bd9Sstevel@tonic-gate static void fdstart(struct fcu_obj *); 687c478bd9Sstevel@tonic-gate static int fd_build_label_vtoc(struct fcu_obj *, struct fdisk *, 697c478bd9Sstevel@tonic-gate struct vtoc *, struct dk_label *); 707c478bd9Sstevel@tonic-gate static void fd_build_user_vtoc(struct fcu_obj *, struct fdisk *, 717c478bd9Sstevel@tonic-gate struct vtoc *); 727c478bd9Sstevel@tonic-gate static int fd_rawioctl(struct fcu_obj *, int, caddr_t, int); 737c478bd9Sstevel@tonic-gate static void fd_media_watch(void *); 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate static int fd_open(dev_t *, int, int, cred_t *); 767c478bd9Sstevel@tonic-gate static int fd_close(dev_t, int, int, cred_t *); 777c478bd9Sstevel@tonic-gate static int fd_strategy(struct buf *); 787c478bd9Sstevel@tonic-gate static int fd_read(dev_t, struct uio *, cred_t *); 797c478bd9Sstevel@tonic-gate static int fd_write(dev_t, struct uio *, cred_t *); 807c478bd9Sstevel@tonic-gate static int fd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 817c478bd9Sstevel@tonic-gate static int fd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *, 827c478bd9Sstevel@tonic-gate caddr_t, int *); 837c478bd9Sstevel@tonic-gate static int fd_check_media(dev_t dev, enum dkio_state state); 847c478bd9Sstevel@tonic-gate static int fd_get_media_info(struct fcu_obj *fjp, caddr_t buf, int flag); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate static struct cb_ops fd_cb_ops = { 877c478bd9Sstevel@tonic-gate fd_open, /* open */ 887c478bd9Sstevel@tonic-gate fd_close, /* close */ 897c478bd9Sstevel@tonic-gate fd_strategy, /* strategy */ 907c478bd9Sstevel@tonic-gate nodev, /* print */ 917c478bd9Sstevel@tonic-gate nodev, /* dump */ 927c478bd9Sstevel@tonic-gate fd_read, /* read */ 937c478bd9Sstevel@tonic-gate fd_write, /* write */ 947c478bd9Sstevel@tonic-gate fd_ioctl, /* ioctl */ 957c478bd9Sstevel@tonic-gate nodev, /* devmap */ 967c478bd9Sstevel@tonic-gate nodev, /* mmap */ 977c478bd9Sstevel@tonic-gate nodev, /* segmap */ 987c478bd9Sstevel@tonic-gate nochpoll, /* poll */ 997c478bd9Sstevel@tonic-gate fd_prop_op, /* cb_prop_op */ 1007c478bd9Sstevel@tonic-gate 0, /* streamtab */ 1017c478bd9Sstevel@tonic-gate D_NEW | D_MP /* Driver compatibility flag */ 1027c478bd9Sstevel@tonic-gate }; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate static int fd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 1057c478bd9Sstevel@tonic-gate static int fd_probe(dev_info_t *); 1067c478bd9Sstevel@tonic-gate static int fd_attach(dev_info_t *, ddi_attach_cmd_t); 1077c478bd9Sstevel@tonic-gate static int fd_detach(dev_info_t *, ddi_detach_cmd_t); 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate static struct dev_ops fd_ops = { 1107c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 1117c478bd9Sstevel@tonic-gate 0, /* refcnt */ 1127c478bd9Sstevel@tonic-gate fd_getinfo, /* getinfo */ 1137c478bd9Sstevel@tonic-gate nulldev, /* identify */ 1147c478bd9Sstevel@tonic-gate fd_probe, /* probe */ 1157c478bd9Sstevel@tonic-gate fd_attach, /* attach */ 1167c478bd9Sstevel@tonic-gate fd_detach, /* detach */ 1177c478bd9Sstevel@tonic-gate nodev, /* reset */ 1187c478bd9Sstevel@tonic-gate &fd_cb_ops, /* driver operations */ 119*19397407SSherry Moore (struct bus_ops *)0, /* bus operations */ 120*19397407SSherry Moore NULL, /* power */ 121*19397407SSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */ 1227c478bd9Sstevel@tonic-gate }; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * static data 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate static void *fd_state_head; /* opaque handle top of state structs */ 1297c478bd9Sstevel@tonic-gate static int fd_check_media_time = 5000000; /* 5 second state check */ 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * error handling 1337c478bd9Sstevel@tonic-gate * 1347c478bd9Sstevel@tonic-gate * for debugging, 1357c478bd9Sstevel@tonic-gate * set fderrlevel to 1 1367c478bd9Sstevel@tonic-gate * set fderrmask to 224 or 644 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate #ifdef DEBUG 1397c478bd9Sstevel@tonic-gate static uint_t fderrmask = FDEM_ALL; 1407c478bd9Sstevel@tonic-gate #endif 1417c478bd9Sstevel@tonic-gate static int fderrlevel = 5; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate #define KIOSP KSTAT_IO_PTR(fdp->d_iostat) 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate static struct driver_minor_data { 1467c478bd9Sstevel@tonic-gate char *name; 1477c478bd9Sstevel@tonic-gate int minor; 1487c478bd9Sstevel@tonic-gate int type; 1497c478bd9Sstevel@tonic-gate } fd_minor [] = { 1507c478bd9Sstevel@tonic-gate { "a", 0, S_IFBLK}, 1517c478bd9Sstevel@tonic-gate { "b", 1, S_IFBLK}, 1527c478bd9Sstevel@tonic-gate { "c", 2, S_IFBLK}, 1537c478bd9Sstevel@tonic-gate { "a,raw", 0, S_IFCHR}, 1547c478bd9Sstevel@tonic-gate { "b,raw", 1, S_IFCHR}, 1557c478bd9Sstevel@tonic-gate { "c,raw", 2, S_IFCHR}, 1567c478bd9Sstevel@tonic-gate {0} 1577c478bd9Sstevel@tonic-gate }; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 1607c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a driver */ 161*19397407SSherry Moore "Floppy Disk driver", /* Name of the module. */ 1627c478bd9Sstevel@tonic-gate &fd_ops, /* driver ops */ 1637c478bd9Sstevel@tonic-gate }; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 1667c478bd9Sstevel@tonic-gate MODREV_1, (void *)&modldrv, NULL 1677c478bd9Sstevel@tonic-gate }; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate int 1717c478bd9Sstevel@tonic-gate _init(void) 1727c478bd9Sstevel@tonic-gate { 1737c478bd9Sstevel@tonic-gate int retval; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate if ((retval = ddi_soft_state_init(&fd_state_head, 1767c478bd9Sstevel@tonic-gate sizeof (struct fdisk) + sizeof (struct fd_drive) + 1777c478bd9Sstevel@tonic-gate sizeof (struct fd_char) + sizeof (struct fdattr), 0)) != 0) 1787c478bd9Sstevel@tonic-gate return (retval); 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate if ((retval = mod_install(&modlinkage)) != 0) 1817c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&fd_state_head); 1827c478bd9Sstevel@tonic-gate return (retval); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate int 1867c478bd9Sstevel@tonic-gate _fini(void) 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate int retval; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate if ((retval = mod_remove(&modlinkage)) != 0) 1917c478bd9Sstevel@tonic-gate return (retval); 1927c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&fd_state_head); 1937c478bd9Sstevel@tonic-gate return (retval); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate int 1977c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 1987c478bd9Sstevel@tonic-gate { 1997c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate static int 2047c478bd9Sstevel@tonic-gate fd_getdrive(dev_t dev, struct fcu_obj **fjpp, struct fdisk **fdpp) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate if (fdpp) { 2077c478bd9Sstevel@tonic-gate *fdpp = ddi_get_soft_state(fd_state_head, DRIVE(dev)); 2087c478bd9Sstevel@tonic-gate if (*fdpp && fjpp) { 2097c478bd9Sstevel@tonic-gate *fjpp = (*fdpp)->d_obj; 2107c478bd9Sstevel@tonic-gate if (*fjpp) 2117c478bd9Sstevel@tonic-gate return ((*fjpp)->fj_unit); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate return (-1); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2187c478bd9Sstevel@tonic-gate static int 2197c478bd9Sstevel@tonic-gate fd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate dev_t dev = (dev_t)arg; 2227c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 2237c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 2247c478bd9Sstevel@tonic-gate int rval; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate switch (cmd) { 2277c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 2287c478bd9Sstevel@tonic-gate (void) fd_getdrive(dev, &fjp, &fdp); 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * Ignoring return value because success is checked by 2317c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate if (fjp && fdp) { 2347c478bd9Sstevel@tonic-gate *result = fjp->fj_dip; 2357c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 2367c478bd9Sstevel@tonic-gate } else 2377c478bd9Sstevel@tonic-gate rval = DDI_FAILURE; 2387c478bd9Sstevel@tonic-gate break; 2397c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 2407c478bd9Sstevel@tonic-gate *result = (void *)(uintptr_t)DRIVE(dev); 2417c478bd9Sstevel@tonic-gate rval = DDI_SUCCESS; 2427c478bd9Sstevel@tonic-gate break; 2437c478bd9Sstevel@tonic-gate default: 2447c478bd9Sstevel@tonic-gate rval = DDI_FAILURE; 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate return (rval); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 2507c478bd9Sstevel@tonic-gate #define CMOS_ADDR 0x70 2517c478bd9Sstevel@tonic-gate #define CMOS_DATA 0x71 2527c478bd9Sstevel@tonic-gate #define CMOS_FDRV 0x10 2537c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate static int 2567c478bd9Sstevel@tonic-gate fd_probe(dev_info_t *dip) 2577c478bd9Sstevel@tonic-gate { 2587c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 2597c478bd9Sstevel@tonic-gate int cmos; 2607c478bd9Sstevel@tonic-gate int drive_type; 2617c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 2627c478bd9Sstevel@tonic-gate int debug[2]; 2637c478bd9Sstevel@tonic-gate int drive_size; 2647c478bd9Sstevel@tonic-gate int len; 2657c478bd9Sstevel@tonic-gate int unit_num; 2667c478bd9Sstevel@tonic-gate char density[8]; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate len = sizeof (debug); 2697c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 2707c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "debug", (caddr_t)debug, &len) == 2717c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 2727c478bd9Sstevel@tonic-gate fderrlevel = debug[0]; 2737c478bd9Sstevel@tonic-gate #ifdef DEBUG 2747c478bd9Sstevel@tonic-gate fderrmask = (uint_t)debug[1]; 2757c478bd9Sstevel@tonic-gate #endif 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate len = sizeof (unit_num); 2787c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 2797c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "unit", (caddr_t)&unit_num, &len) != 2807c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 2817c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 2827c478bd9Sstevel@tonic-gate (CE_WARN, "fd_probe failed: dip %p", (void *)dip)); 2837c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 2877c478bd9Sstevel@tonic-gate /* get the cmos memory values quick and dirty */ 2887c478bd9Sstevel@tonic-gate outb(CMOS_ADDR, CMOS_FDRV); 2897c478bd9Sstevel@tonic-gate cmos = drive_type = (int)inb(CMOS_DATA); 2907c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate switch (unit_num) { 2937c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 2947c478bd9Sstevel@tonic-gate case 0: 2957c478bd9Sstevel@tonic-gate drive_type = drive_type >> 4; 2967c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 2977c478bd9Sstevel@tonic-gate case 1: 2987c478bd9Sstevel@tonic-gate if (cmos && (drive_type & 0x0F)) { 2997c478bd9Sstevel@tonic-gate break; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * Some enhanced floppy-disk controller adaptor cards 3037c478bd9Sstevel@tonic-gate * require NO drives defined in the CMOS configuration 3047c478bd9Sstevel@tonic-gate * memory. 3057c478bd9Sstevel@tonic-gate * So fall through 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 3087c478bd9Sstevel@tonic-gate default: /* need to check conf file */ 3097c478bd9Sstevel@tonic-gate len = sizeof (density); 3107c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 3117c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "density", (caddr_t)&density, &len) != 3127c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 3137c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 3147c478bd9Sstevel@tonic-gate (CE_WARN, 3157c478bd9Sstevel@tonic-gate "fd_probe failed density: dip %p unit %d", 3167c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 3177c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate len = sizeof (drive_size); 3207c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 3217c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "size", (caddr_t)&drive_size, &len) != 3227c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 3237c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 3247c478bd9Sstevel@tonic-gate (CE_WARN, "fd_probe failed size: dip %p unit %d", 3257c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 3267c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 3307c478bd9Sstevel@tonic-gate (CE_WARN, "fd_probe dip %p unit %d", (void *)dip, unit_num)); 3317c478bd9Sstevel@tonic-gate return (DDI_PROBE_SUCCESS); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* ARGSUSED */ 3367c478bd9Sstevel@tonic-gate static int 3377c478bd9Sstevel@tonic-gate fd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 3387c478bd9Sstevel@tonic-gate { 3397c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 3407c478bd9Sstevel@tonic-gate struct fdisk *fdp; 3417c478bd9Sstevel@tonic-gate struct driver_minor_data *dmdp; 3427c478bd9Sstevel@tonic-gate int mode_3D; 3437c478bd9Sstevel@tonic-gate int drive_num, drive_size, drive_type; 3447c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 3457c478bd9Sstevel@tonic-gate int cmos; 3467c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 3477c478bd9Sstevel@tonic-gate int len, sig_minor; 3487c478bd9Sstevel@tonic-gate int unit_num; 3497c478bd9Sstevel@tonic-gate char density[8]; 3507c478bd9Sstevel@tonic-gate char name[MAXNAMELEN]; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate switch (cmd) { 3537c478bd9Sstevel@tonic-gate case DDI_ATTACH: 3547c478bd9Sstevel@tonic-gate len = sizeof (unit_num); 3557c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 3567c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "unit", (caddr_t)&unit_num, &len) != 3577c478bd9Sstevel@tonic-gate DDI_PROP_SUCCESS) { 3587c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 3597c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach failed: dip %p", (void *)dip)); 3607c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 3647c478bd9Sstevel@tonic-gate outb(CMOS_ADDR, CMOS_FDRV); 3657c478bd9Sstevel@tonic-gate cmos = drive_type = (int)inb(CMOS_DATA); 3667c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate switch (unit_num) { 3697c478bd9Sstevel@tonic-gate #ifdef CMOS_CONF_MEM 3707c478bd9Sstevel@tonic-gate case 0: 3717c478bd9Sstevel@tonic-gate drive_type = drive_type >> 4; 3727c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 3737c478bd9Sstevel@tonic-gate case 1: 3747c478bd9Sstevel@tonic-gate drive_type = drive_type & 0x0F; 3757c478bd9Sstevel@tonic-gate if (cmos) 3767c478bd9Sstevel@tonic-gate break; 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * Some enhanced floppy-disk controller adaptor cards 3797c478bd9Sstevel@tonic-gate * require NO drives defined in the CMOS configuration 3807c478bd9Sstevel@tonic-gate * memory. 3817c478bd9Sstevel@tonic-gate * So fall through 3827c478bd9Sstevel@tonic-gate */ 3837c478bd9Sstevel@tonic-gate #endif /* CMOS_CONF_MEM */ 3847c478bd9Sstevel@tonic-gate default: /* need to check .conf file */ 3857c478bd9Sstevel@tonic-gate drive_type = 0; 3867c478bd9Sstevel@tonic-gate len = sizeof (density); 3877c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, 3887c478bd9Sstevel@tonic-gate PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "density", 3897c478bd9Sstevel@tonic-gate (caddr_t)&density, &len) != DDI_PROP_SUCCESS) 3907c478bd9Sstevel@tonic-gate density[0] = '\0'; 3917c478bd9Sstevel@tonic-gate len = sizeof (drive_size); 3927c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, 3937c478bd9Sstevel@tonic-gate PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "size", 3947c478bd9Sstevel@tonic-gate (caddr_t)&drive_size, &len) != DDI_PROP_SUCCESS) 3957c478bd9Sstevel@tonic-gate drive_size = 0; 3967c478bd9Sstevel@tonic-gate if (strcmp(density, "DSDD") == 0) { 3977c478bd9Sstevel@tonic-gate if (drive_size == 5) 3987c478bd9Sstevel@tonic-gate drive_type = 1; 3997c478bd9Sstevel@tonic-gate else if (drive_size == 3) 4007c478bd9Sstevel@tonic-gate drive_type = 3; 4017c478bd9Sstevel@tonic-gate } else if (strcmp(density, "DSHD") == 0) { 4027c478bd9Sstevel@tonic-gate if (drive_size == 5) 4037c478bd9Sstevel@tonic-gate drive_type = 2; 4047c478bd9Sstevel@tonic-gate else if (drive_size == 3) 4057c478bd9Sstevel@tonic-gate drive_type = 4; 4067c478bd9Sstevel@tonic-gate } else if (strcmp(density, "DSED") == 0 && 4077c478bd9Sstevel@tonic-gate drive_size == 3) { 4087c478bd9Sstevel@tonic-gate drive_type = 6; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate if (drive_type == 0) { 4137c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 4147c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach failed type: dip %p unit %d", 4157c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 4167c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate drive_num = ddi_get_instance(dip); 4207c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(fd_state_head, drive_num) != 0) 4217c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4227c478bd9Sstevel@tonic-gate fdp = ddi_get_soft_state(fd_state_head, drive_num); 4237c478bd9Sstevel@tonic-gate fjp = fdp->d_obj = ddi_get_driver_private(dip); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate mutex_init(&fjp->fj_lock, NULL, MUTEX_DRIVER, *fjp->fj_iblock); 4267c478bd9Sstevel@tonic-gate sema_init(&fdp->d_ocsem, 1, NULL, SEMA_DRIVER, NULL); 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate fjp->fj_drive = (struct fd_drive *)(fdp + 1); 4297c478bd9Sstevel@tonic-gate fjp->fj_chars = (struct fd_char *)(fjp->fj_drive + 1); 4307c478bd9Sstevel@tonic-gate fjp->fj_attr = (struct fdattr *)(fjp->fj_chars + 1); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * set default floppy drive characteristics & geometry 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate switch (drive_type) { /* assume doubled sided */ 4367c478bd9Sstevel@tonic-gate case 2: /* 5.25 high density */ 4377c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_525HD; 4387c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_5H | 1<<FMT_5D9 | 1<<FMT_5D8 | 4397c478bd9Sstevel@tonic-gate 1<<FMT_5D4 | 1<<FMT_5D16; 4407c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_5H; 4417c478bd9Sstevel@tonic-gate break; 4427c478bd9Sstevel@tonic-gate case 4: /* 3.5 high density */ 4437c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_350HD; 4447c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_3H | 1<<FMT_3I | 1<<FMT_3D; 4457c478bd9Sstevel@tonic-gate len = sizeof (mode_3D); 4467c478bd9Sstevel@tonic-gate if (ddi_prop_op(DDI_DEV_T_ANY, dip, 4477c478bd9Sstevel@tonic-gate PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "mode_3D", 4487c478bd9Sstevel@tonic-gate (caddr_t)&mode_3D, &len) != DDI_PROP_SUCCESS) 4497c478bd9Sstevel@tonic-gate mode_3D = 0; 4507c478bd9Sstevel@tonic-gate if (mode_3D && (fjp->fj_fdc->c_flags & FCFLG_3DMODE)) 4517c478bd9Sstevel@tonic-gate /* 4527c478bd9Sstevel@tonic-gate * 3D mode should be enabled only if a dual- 4537c478bd9Sstevel@tonic-gate * speed 3.5" high-density drive and a 4547c478bd9Sstevel@tonic-gate * supported floppy controller are installed. 4557c478bd9Sstevel@tonic-gate */ 4567c478bd9Sstevel@tonic-gate fdp->d_media |= 1 << FMT_3M; 4577c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_3H; 4587c478bd9Sstevel@tonic-gate break; 4597c478bd9Sstevel@tonic-gate case 1: /* 5.25 double density */ 4607c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_525DD; 4617c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_5D9 | 1<<FMT_5D8 | 1<<FMT_5D4 | 4627c478bd9Sstevel@tonic-gate 1<<FMT_5D16; 4637c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_5D9; 4647c478bd9Sstevel@tonic-gate break; 4657c478bd9Sstevel@tonic-gate case 3: /* 3.5 double density */ 4667c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_350HD; 4677c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_3D; 4687c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_3D; 4697c478bd9Sstevel@tonic-gate break; 4707c478bd9Sstevel@tonic-gate case 5: /* 3.5 extended density */ 4717c478bd9Sstevel@tonic-gate case 6: 4727c478bd9Sstevel@tonic-gate case 7: 4737c478bd9Sstevel@tonic-gate *fjp->fj_drive = dfd_350ED; 4747c478bd9Sstevel@tonic-gate fdp->d_media = 1<<FMT_3E | 1<<FMT_3H | 1<<FMT_3I | 4757c478bd9Sstevel@tonic-gate 1<<FMT_3D; 4767c478bd9Sstevel@tonic-gate fdp->d_deffdtype = fdp->d_curfdtype = FMT_3E; 4777c478bd9Sstevel@tonic-gate break; 4787c478bd9Sstevel@tonic-gate case 0: /* no drive defined */ 4797c478bd9Sstevel@tonic-gate default: 4807c478bd9Sstevel@tonic-gate goto no_attach; 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_deffdtype]; 4837c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_deffdtype]; 4847c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_deffdtype], fdp->d_part, 4857c478bd9Sstevel@tonic-gate sizeof (struct partition) * NDKMAP); 4867c478bd9Sstevel@tonic-gate fjp->fj_rotspd = fdtypes[fdp->d_deffdtype].fda_rotatespd; 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate sig_minor = drive_num << 3; 4897c478bd9Sstevel@tonic-gate for (dmdp = fd_minor; dmdp->name != NULL; dmdp++) { 4907c478bd9Sstevel@tonic-gate if (ddi_create_minor_node(dip, dmdp->name, dmdp->type, 4917c478bd9Sstevel@tonic-gate sig_minor | dmdp->minor, DDI_NT_FD, NULL) 4927c478bd9Sstevel@tonic-gate == DDI_FAILURE) { 4937c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 4947c478bd9Sstevel@tonic-gate goto no_attach; 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 4997c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach: dip %p unit %d", 5007c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 5017c478bd9Sstevel@tonic-gate (void) sprintf(name, "fd%d", drive_num); 5027c478bd9Sstevel@tonic-gate fdp->d_iostat = kstat_create("fd", drive_num, name, "disk", 5037c478bd9Sstevel@tonic-gate KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT); 5047c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 5057c478bd9Sstevel@tonic-gate fdp->d_iostat->ks_lock = &fjp->fj_lock; 5067c478bd9Sstevel@tonic-gate kstat_install(fdp->d_iostat); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate fjp->fj_data = (caddr_t)fdp; 5107c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_DRVATCH; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate /* 5137c478bd9Sstevel@tonic-gate * Add a zero-length attribute to tell the world we support 5147c478bd9Sstevel@tonic-gate * kernel ioctls (for layered drivers) 5157c478bd9Sstevel@tonic-gate */ 5167c478bd9Sstevel@tonic-gate (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 5177c478bd9Sstevel@tonic-gate DDI_KERNEL_IOCTL, NULL, 0); 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * Ignoring return value because, for passed arguments, only 5207c478bd9Sstevel@tonic-gate * DDI_SUCCESS is returned. 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 5237c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate #ifdef NOT_YET 5267c478bd9Sstevel@tonic-gate case DDI_RESUME: 5277c478bd9Sstevel@tonic-gate drive_num = ddi_get_instance(dip); 5287c478bd9Sstevel@tonic-gate if (!(fdp = ddi_get_soft_state(fd_state_head, drive_num))) 5297c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5307c478bd9Sstevel@tonic-gate fjp = (struct fcu_obj *)fdp->d_obj; 5317c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 5327c478bd9Sstevel@tonic-gate if (!fjp->fj_suspended) { 5337c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 5347c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate fjp->fj_fdc->c_curpcyl[drive_num & 3] = -1; 5377c478bd9Sstevel@tonic-gate fjp->fj_suspended = 0; 5387c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 5397c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5407c478bd9Sstevel@tonic-gate #endif 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate default: 5437c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate no_attach: 5467c478bd9Sstevel@tonic-gate fjp->fj_drive = NULL; 5477c478bd9Sstevel@tonic-gate fjp->fj_chars = NULL; 5487c478bd9Sstevel@tonic-gate fjp->fj_attr = NULL; 5497c478bd9Sstevel@tonic-gate mutex_destroy(&fjp->fj_lock); 5507c478bd9Sstevel@tonic-gate sema_destroy(&fdp->d_ocsem); 5517c478bd9Sstevel@tonic-gate ddi_soft_state_free(fd_state_head, drive_num); 5527c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 5537c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach failed: dip %p unit %d", 5547c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 5557c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5607c478bd9Sstevel@tonic-gate static int 5617c478bd9Sstevel@tonic-gate fd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 5627c478bd9Sstevel@tonic-gate { 5637c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 5647c478bd9Sstevel@tonic-gate struct fdisk *fdp; 5657c478bd9Sstevel@tonic-gate int drive_num; 5667c478bd9Sstevel@tonic-gate int rval = DDI_SUCCESS; 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, (CE_WARN, "fd_detach dip %p", 5697c478bd9Sstevel@tonic-gate (void *)dip)); 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate drive_num = ddi_get_instance(dip); 5727c478bd9Sstevel@tonic-gate if (!(fdp = ddi_get_soft_state(fd_state_head, drive_num))) 5737c478bd9Sstevel@tonic-gate return (rval); 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate switch (cmd) { 5767c478bd9Sstevel@tonic-gate case DDI_DETACH: 5777c478bd9Sstevel@tonic-gate if (fd_unit_is_open(fdp)) { 5787c478bd9Sstevel@tonic-gate rval = EBUSY; 5797c478bd9Sstevel@tonic-gate break; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate kstat_delete(fdp->d_iostat); 5827c478bd9Sstevel@tonic-gate fdp->d_iostat = NULL; 5837c478bd9Sstevel@tonic-gate fjp = (struct fcu_obj *)fdp->d_obj; 5847c478bd9Sstevel@tonic-gate fjp->fj_data = NULL; 5857c478bd9Sstevel@tonic-gate fjp->fj_drive = NULL; 5867c478bd9Sstevel@tonic-gate fjp->fj_chars = NULL; 5877c478bd9Sstevel@tonic-gate fjp->fj_attr = NULL; 5887c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip); 5897c478bd9Sstevel@tonic-gate mutex_destroy(&fjp->fj_lock); 5907c478bd9Sstevel@tonic-gate sema_destroy(&fdp->d_ocsem); 5917c478bd9Sstevel@tonic-gate ddi_soft_state_free(fd_state_head, drive_num); 5927c478bd9Sstevel@tonic-gate break; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate #ifdef NOT_YET 5957c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 5967c478bd9Sstevel@tonic-gate fjp = (struct fcu_obj *)fdp->d_obj; 5977c478bd9Sstevel@tonic-gate fjp->fj_suspended = 1; /* Must be before mutex */ 5987c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 5997c478bd9Sstevel@tonic-gate while (fjp->fj_flags & FUNIT_BUSY) { 6007c478bd9Sstevel@tonic-gate /* Wait for I/O to finish */ 6017c478bd9Sstevel@tonic-gate cv_wait(&fjp->fj_flags, &fjp->fj_lock); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 6047c478bd9Sstevel@tonic-gate break; 6057c478bd9Sstevel@tonic-gate #endif 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate default: 6087c478bd9Sstevel@tonic-gate rval = EINVAL; 6097c478bd9Sstevel@tonic-gate break; 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate return (rval); 6127c478bd9Sstevel@tonic-gate } 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate static int 6167c478bd9Sstevel@tonic-gate fd_part_is_open(struct fdisk *fdp, int part) 6177c478bd9Sstevel@tonic-gate { 6187c478bd9Sstevel@tonic-gate int i; 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate for (i = 0; i < (OTYPCNT - 1); i++) 6217c478bd9Sstevel@tonic-gate if (fdp->d_regopen[i] & (1 << part)) 6227c478bd9Sstevel@tonic-gate return (1); 6237c478bd9Sstevel@tonic-gate return (0); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate static int 6277c478bd9Sstevel@tonic-gate fd_unit_is_open(struct fdisk *fdp) 6287c478bd9Sstevel@tonic-gate { 6297c478bd9Sstevel@tonic-gate int i; 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) 6327c478bd9Sstevel@tonic-gate if (fdp->d_lyropen[i]) 6337c478bd9Sstevel@tonic-gate return (1); 6347c478bd9Sstevel@tonic-gate for (i = 0; i < (OTYPCNT - 1); i++) 6357c478bd9Sstevel@tonic-gate if (fdp->d_regopen[i]) 6367c478bd9Sstevel@tonic-gate return (1); 6377c478bd9Sstevel@tonic-gate return (0); 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6417c478bd9Sstevel@tonic-gate static int 6427c478bd9Sstevel@tonic-gate fd_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) 6437c478bd9Sstevel@tonic-gate { 6447c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 6457c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 6467c478bd9Sstevel@tonic-gate struct partition *pp; 6477c478bd9Sstevel@tonic-gate dev_t dev; 6487c478bd9Sstevel@tonic-gate int part, unit; 6497c478bd9Sstevel@tonic-gate int part_is_open; 6507c478bd9Sstevel@tonic-gate int rval; 6517c478bd9Sstevel@tonic-gate uint_t pbit; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate dev = *devp; 6547c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 6557c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 6567c478bd9Sstevel@tonic-gate return (ENXIO); 6577c478bd9Sstevel@tonic-gate part = PARTITION(dev); 6587c478bd9Sstevel@tonic-gate pbit = 1 << part; 6597c478bd9Sstevel@tonic-gate pp = &fdp->d_part[part]; 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * Serialize opens/closes 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate sema_p(&fdp->d_ocsem); 6657c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_OPEN, 6667c478bd9Sstevel@tonic-gate (CE_CONT, "fd_open: fd%d part %d flag %x otype %x\n", DRIVE(dev), 6677c478bd9Sstevel@tonic-gate part, flag, otyp)); 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate /* 6707c478bd9Sstevel@tonic-gate * Check for previous exclusive open, or trying to exclusive open 6717c478bd9Sstevel@tonic-gate * An "exclusive open" on any partition is not guaranteed to 6727c478bd9Sstevel@tonic-gate * protect against opens on another partition that overlaps it. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) { 6757c478bd9Sstevel@tonic-gate part_is_open = (fdp->d_lyropen[part] != 0); 6767c478bd9Sstevel@tonic-gate } else { 6777c478bd9Sstevel@tonic-gate part_is_open = fd_part_is_open(fdp, part); 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate if ((fdp->d_exclmask & pbit) || ((flag & FEXCL) && part_is_open)) { 6807c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_OPEN, (CE_CONT, 6817c478bd9Sstevel@tonic-gate "fd_open: exclparts %lx openparts %lx lyrcnt %lx pbit %x\n", 6827c478bd9Sstevel@tonic-gate fdp->d_exclmask, fdp->d_regopen[otyp], fdp->d_lyropen[part], 6837c478bd9Sstevel@tonic-gate pbit)); 6847c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 6857c478bd9Sstevel@tonic-gate return (EBUSY); 6867c478bd9Sstevel@tonic-gate } 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* 6897c478bd9Sstevel@tonic-gate * Ensure that drive is recalibrated on first open of new diskette. 6907c478bd9Sstevel@tonic-gate */ 6917c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 6927c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit) != 0) { 6937c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_rcseek(fjp, unit, -1, 0)) { 6947c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L2, FDEM_OPEN, 6957c478bd9Sstevel@tonic-gate (CE_NOTE, "fd_open fd%d: not ready", DRIVE(dev))); 6967c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 6977c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 6987c478bd9Sstevel@tonic-gate return (ENXIO); 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate if (flag & (FNDELAY | FNONBLOCK)) { 7037c478bd9Sstevel@tonic-gate /* don't attempt access, just return successfully */ 7047c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 7057c478bd9Sstevel@tonic-gate goto out; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate /* 7097c478bd9Sstevel@tonic-gate * auto-sense the density/format of the diskette 7107c478bd9Sstevel@tonic-gate */ 7117c478bd9Sstevel@tonic-gate rval = fdgetlabel(fjp, unit); 7127c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 7137c478bd9Sstevel@tonic-gate if (rval) { 7147c478bd9Sstevel@tonic-gate /* didn't find label (couldn't read anything) */ 7157c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L2, FDEM_OPEN, 7167c478bd9Sstevel@tonic-gate (CE_NOTE, "fd%d: drive not ready", DRIVE(dev))); 7177c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7187c478bd9Sstevel@tonic-gate return (EIO); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate /* check partition */ 7217c478bd9Sstevel@tonic-gate if (pp->p_size == 0) { 7227c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7237c478bd9Sstevel@tonic-gate return (ENXIO); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate /* 7267c478bd9Sstevel@tonic-gate * if opening for writing, check write protect on diskette 7277c478bd9Sstevel@tonic-gate */ 7287c478bd9Sstevel@tonic-gate if ((flag & FWRITE) && (fdp->d_obj->fj_flags & FUNIT_WPROT)) { 7297c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7307c478bd9Sstevel@tonic-gate return (EROFS); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate out: 7347c478bd9Sstevel@tonic-gate /* 7357c478bd9Sstevel@tonic-gate * mark open as having succeeded 7367c478bd9Sstevel@tonic-gate */ 7377c478bd9Sstevel@tonic-gate if (flag & FEXCL) 7387c478bd9Sstevel@tonic-gate fdp->d_exclmask |= pbit; 7397c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) 7407c478bd9Sstevel@tonic-gate fdp->d_lyropen[part]++; 7417c478bd9Sstevel@tonic-gate else 7427c478bd9Sstevel@tonic-gate fdp->d_regopen[otyp] |= 1 << part; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7457c478bd9Sstevel@tonic-gate return (0); 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate /* 7497c478bd9Sstevel@tonic-gate * fdgetlabel - read the SunOS label off the diskette 7507c478bd9Sstevel@tonic-gate * if it can read a valid label it does so, else it will use a 7517c478bd9Sstevel@tonic-gate * default. If it can`t read the diskette - that is an error. 7527c478bd9Sstevel@tonic-gate * 7537c478bd9Sstevel@tonic-gate * RETURNS: 0 for ok - meaning that it could at least read the device, 7547c478bd9Sstevel@tonic-gate * !0 for error XXX TBD NYD error codes 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate static int 7577c478bd9Sstevel@tonic-gate fdgetlabel(struct fcu_obj *fjp, int unit) 7587c478bd9Sstevel@tonic-gate { 7597c478bd9Sstevel@tonic-gate struct dk_label *label; 7607c478bd9Sstevel@tonic-gate struct fdisk *fdp; 7617c478bd9Sstevel@tonic-gate char *newlabel; 7627c478bd9Sstevel@tonic-gate short *sp; 7637c478bd9Sstevel@tonic-gate short count; 7647c478bd9Sstevel@tonic-gate short xsum; 7657c478bd9Sstevel@tonic-gate int tries, try_this; 7667c478bd9Sstevel@tonic-gate uint_t nexttype; 7677c478bd9Sstevel@tonic-gate int rval; 7687c478bd9Sstevel@tonic-gate short oldlvl; 7697c478bd9Sstevel@tonic-gate int i; 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, 7727c478bd9Sstevel@tonic-gate (CE_CONT, "fdgetlabel fd unit %d\n", unit)); 7737c478bd9Sstevel@tonic-gate fdp = (struct fdisk *)fjp->fj_data; 7747c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_UNLABELED); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate /* 7777c478bd9Sstevel@tonic-gate * get some space to play with the label 7787c478bd9Sstevel@tonic-gate */ 7797c478bd9Sstevel@tonic-gate label = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 7807c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, (CE_CONT, 7817c478bd9Sstevel@tonic-gate "fdgetlabel fd unit %d kmem_zalloc: ptr = %p, size = %lx\n", 7827c478bd9Sstevel@tonic-gate unit, (void *)label, (size_t)sizeof (struct dk_label))); 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* 7857c478bd9Sstevel@tonic-gate * read block 0 (0/0/1) to find the label 7867c478bd9Sstevel@tonic-gate * (disk is potentially not present or unformatted) 7877c478bd9Sstevel@tonic-gate */ 7887c478bd9Sstevel@tonic-gate /* noerrprint since this is a private cmd */ 7897c478bd9Sstevel@tonic-gate oldlvl = fderrlevel; 7907c478bd9Sstevel@tonic-gate fderrlevel = FDEP_LMAX; 7917c478bd9Sstevel@tonic-gate /* 7927c478bd9Sstevel@tonic-gate * try different characteristics (ie densities) 7937c478bd9Sstevel@tonic-gate * 7947c478bd9Sstevel@tonic-gate * if fdp->d_curfdtype is -1 then the current characteristics 7957c478bd9Sstevel@tonic-gate * were set by ioctl and need to try it as well as everything 7967c478bd9Sstevel@tonic-gate * in the table 7977c478bd9Sstevel@tonic-gate */ 7987c478bd9Sstevel@tonic-gate nexttype = fdp->d_deffdtype; 7997c478bd9Sstevel@tonic-gate try_this = 1; /* always try the current characteristics */ 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate for (tries = nfdtypes; tries; tries--) { 8027c478bd9Sstevel@tonic-gate if (try_this) { 8037c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 8047c478bd9Sstevel@tonic-gate 8057c478bd9Sstevel@tonic-gate /* try reading last sector of cyl 1, head 0 */ 8067c478bd9Sstevel@tonic-gate if (!(rval = fjp->fj_ops->fco_rw(fjp, unit, 8077c478bd9Sstevel@tonic-gate FDREAD, 1, 0, fjp->fj_chars->fdc_secptrack, 8087c478bd9Sstevel@tonic-gate (caddr_t)label, 8097c478bd9Sstevel@tonic-gate sizeof (struct dk_label))) && 8107c478bd9Sstevel@tonic-gate /* and last sector plus 1 of cylinder 1 */ 8117c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_rw(fjp, unit, FDREAD, 1, 8127c478bd9Sstevel@tonic-gate 0, fjp->fj_chars->fdc_secptrack + 1, 8137c478bd9Sstevel@tonic-gate (caddr_t)label, 8147c478bd9Sstevel@tonic-gate sizeof (struct dk_label)) && 8157c478bd9Sstevel@tonic-gate /* and label sector on cylinder 0 */ 8167c478bd9Sstevel@tonic-gate !(rval = fjp->fj_ops->fco_rw(fjp, unit, 8177c478bd9Sstevel@tonic-gate FDREAD, 0, 0, 1, (caddr_t)label, 8187c478bd9Sstevel@tonic-gate sizeof (struct dk_label)))) 8197c478bd9Sstevel@tonic-gate break; 8207c478bd9Sstevel@tonic-gate if (rval == ENXIO) 8217c478bd9Sstevel@tonic-gate break; 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate /* 8247c478bd9Sstevel@tonic-gate * try the next entry in the characteristics tbl 8257c478bd9Sstevel@tonic-gate */ 8267c478bd9Sstevel@tonic-gate fdp->d_curfdtype = (signed char)nexttype; 8277c478bd9Sstevel@tonic-gate nexttype = (nexttype + 1) % nfdtypes; 8287c478bd9Sstevel@tonic-gate if ((1 << fdp->d_curfdtype) & fdp->d_media) { 8297c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_curfdtype]; 8307c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_curfdtype]; 8317c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_curfdtype], fdp->d_part, 8327c478bd9Sstevel@tonic-gate sizeof (struct partition) * NDKMAP); 8337c478bd9Sstevel@tonic-gate /* 8347c478bd9Sstevel@tonic-gate * check for a double_density diskette 8357c478bd9Sstevel@tonic-gate * in a high_density 5.25" drive 8367c478bd9Sstevel@tonic-gate */ 8377c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_transfer_rate == 250 && 8387c478bd9Sstevel@tonic-gate fjp->fj_rotspd > fjp->fj_attr->fda_rotatespd) { 8397c478bd9Sstevel@tonic-gate /* 8407c478bd9Sstevel@tonic-gate * yes - adjust transfer rate since we don't 8417c478bd9Sstevel@tonic-gate * know if we have a 5.25" dual-speed drive 8427c478bd9Sstevel@tonic-gate */ 8437c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = 360; 8447c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_transfer_rate = 300; 8457c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_medium = 5; 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate if ((2 * fjp->fj_chars->fdc_ncyl) == 8487c478bd9Sstevel@tonic-gate defchar[fdp->d_deffdtype]->fdc_ncyl) { 8497c478bd9Sstevel@tonic-gate /* yes - adjust steps per cylinder */ 8507c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 2; 8517c478bd9Sstevel@tonic-gate } else 8527c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 1; 8537c478bd9Sstevel@tonic-gate try_this = 1; 8547c478bd9Sstevel@tonic-gate } else 8557c478bd9Sstevel@tonic-gate try_this = 0; 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate fderrlevel = oldlvl; /* print errors again */ 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate if (rval) { 8607c478bd9Sstevel@tonic-gate fdp->d_curfdtype = fdp->d_deffdtype; 8617c478bd9Sstevel@tonic-gate goto out; /* couldn't read anything */ 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, 8657c478bd9Sstevel@tonic-gate (CE_CONT, 8667c478bd9Sstevel@tonic-gate "fdgetlabel fd unit=%d ncyl=%d nsct=%d step=%d rpm=%d intlv=%d\n", 8677c478bd9Sstevel@tonic-gate unit, fjp->fj_chars->fdc_ncyl, fjp->fj_chars->fdc_secptrack, 8687c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps, fjp->fj_attr->fda_rotatespd, 8697c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv)); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * _something_ was read - look for unixtype label 8737c478bd9Sstevel@tonic-gate */ 8747c478bd9Sstevel@tonic-gate if (label->dkl_magic != DKL_MAGIC || 8757c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_sanity != VTOC_SANE) { 8767c478bd9Sstevel@tonic-gate /* not a label - no magic number */ 8777c478bd9Sstevel@tonic-gate goto nolabel; /* no errors, but no label */ 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate count = sizeof (struct dk_label) / sizeof (short); 8817c478bd9Sstevel@tonic-gate sp = (short *)label; 8827c478bd9Sstevel@tonic-gate xsum = 0; 8837c478bd9Sstevel@tonic-gate while (count--) 8847c478bd9Sstevel@tonic-gate xsum ^= *sp++; /* should add up to 0 */ 8857c478bd9Sstevel@tonic-gate if (xsum) { 8867c478bd9Sstevel@tonic-gate /* not a label - checksum didn't compute */ 8877c478bd9Sstevel@tonic-gate goto nolabel; /* no errors, but no label */ 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate /* 8917c478bd9Sstevel@tonic-gate * the SunOS label overrides current diskette characteristics 8927c478bd9Sstevel@tonic-gate */ 8937c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl = label->dkl_pcyl; 8947c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_nhead = label->dkl_nhead; 8957c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack = (label->dkl_nsect * DEV_BSIZE) / 8967c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size; 8977c478bd9Sstevel@tonic-gate if (defchar[fdp->d_deffdtype]->fdc_ncyl == 2 * fjp->fj_chars->fdc_ncyl) 8987c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 2; 8997c478bd9Sstevel@tonic-gate else 9007c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 1; 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = label->dkl_rpm; 9037c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv = label->dkl_intrlv; 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate fdp->d_vtoc_version = label->dkl_vtoc.v_version; 9067c478bd9Sstevel@tonic-gate bcopy(label->dkl_vtoc.v_volume, fdp->d_vtoc_volume, LEN_DKL_VVOL); 9077c478bd9Sstevel@tonic-gate bcopy(label->dkl_vtoc.v_asciilabel, 9087c478bd9Sstevel@tonic-gate fdp->d_vtoc_asciilabel, LEN_DKL_ASCII); 9097c478bd9Sstevel@tonic-gate /* 9107c478bd9Sstevel@tonic-gate * logical partitions 9117c478bd9Sstevel@tonic-gate */ 9127c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 9137c478bd9Sstevel@tonic-gate fdp->d_part[i].p_tag = label->dkl_vtoc.v_part[i].p_tag; 9147c478bd9Sstevel@tonic-gate fdp->d_part[i].p_flag = label->dkl_vtoc.v_part[i].p_flag; 9157c478bd9Sstevel@tonic-gate fdp->d_part[i].p_start = label->dkl_vtoc.v_part[i].p_start; 9167c478bd9Sstevel@tonic-gate fdp->d_part[i].p_size = label->dkl_vtoc.v_part[i].p_size; 9177c478bd9Sstevel@tonic-gate 9187c478bd9Sstevel@tonic-gate fdp->d_vtoc_timestamp[i] = label->dkl_vtoc.timestamp[i]; 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_LABELOK; 9227c478bd9Sstevel@tonic-gate goto out; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate nolabel: 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * if not found, fill in label info from default (mark default used) 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate if (fdp->d_media & (1<<FMT_3D)) 9297c478bd9Sstevel@tonic-gate newlabel = deflabel_35; 9307c478bd9Sstevel@tonic-gate else /* if (fdp->d_media & (1<<FMT_5D9)) */ 9317c478bd9Sstevel@tonic-gate newlabel = deflabel_525; 9327c478bd9Sstevel@tonic-gate bzero(fdp->d_vtoc_volume, LEN_DKL_VVOL); 9337c478bd9Sstevel@tonic-gate (void) sprintf(fdp->d_vtoc_asciilabel, newlabel, 9347c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl, fjp->fj_chars->fdc_nhead, 9357c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack); 9367c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_UNLABELED; 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate out: 9397c478bd9Sstevel@tonic-gate kmem_free(label, sizeof (struct dk_label)); 9407c478bd9Sstevel@tonic-gate return (rval); 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 9457c478bd9Sstevel@tonic-gate static int 9467c478bd9Sstevel@tonic-gate fd_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 9477c478bd9Sstevel@tonic-gate { 9487c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 9497c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 9507c478bd9Sstevel@tonic-gate int part, part_is_closed; 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate #ifdef DEBUG 9537c478bd9Sstevel@tonic-gate int unit; 9547c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN unit= 9557c478bd9Sstevel@tonic-gate #else 9567c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN (void) 9577c478bd9Sstevel@tonic-gate #endif 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate DEBUG_ASSIGN fd_getdrive(dev, &fjp, &fdp); 9607c478bd9Sstevel@tonic-gate /* 9617c478bd9Sstevel@tonic-gate * Ignoring return in non DEBUG mode because success is checked by 9627c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 9637c478bd9Sstevel@tonic-gate */ 9647c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 9657c478bd9Sstevel@tonic-gate return (ENXIO); 9667c478bd9Sstevel@tonic-gate part = PARTITION(dev); 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate sema_p(&fdp->d_ocsem); 9697c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_CLOS, 9707c478bd9Sstevel@tonic-gate (CE_CONT, "fd_close: fd unit %d part %d otype %x\n", 9717c478bd9Sstevel@tonic-gate unit, part, otyp)); 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) { 9747c478bd9Sstevel@tonic-gate if (fdp->d_lyropen[part]) 9757c478bd9Sstevel@tonic-gate fdp->d_lyropen[part]--; 9767c478bd9Sstevel@tonic-gate part_is_closed = (fdp->d_lyropen[part] == 0); 9777c478bd9Sstevel@tonic-gate } else { 9787c478bd9Sstevel@tonic-gate fdp->d_regopen[otyp] &= ~(1<<part); 9797c478bd9Sstevel@tonic-gate part_is_closed = 1; 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate if (part_is_closed) { 9827c478bd9Sstevel@tonic-gate if (part == 2 && fdp->d_exclmask&(1<<part)) 9837c478bd9Sstevel@tonic-gate fdp->d_exclmask = 0; 9847c478bd9Sstevel@tonic-gate else 9857c478bd9Sstevel@tonic-gate fdp->d_exclmask &= ~(1<<part); 9867c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_CLOS, 9877c478bd9Sstevel@tonic-gate (CE_CONT, 9887c478bd9Sstevel@tonic-gate "fd_close: exclparts %lx openparts %lx lyrcnt %lx\n", 9897c478bd9Sstevel@tonic-gate fdp->d_exclmask, fdp->d_regopen[otyp], 9907c478bd9Sstevel@tonic-gate fdp->d_lyropen[part])); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate if (fd_unit_is_open(fdp) == 0) 9937c478bd9Sstevel@tonic-gate fdp->d_obj->fj_flags &= ~FUNIT_CHANGED; 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 9967c478bd9Sstevel@tonic-gate return (0); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10007c478bd9Sstevel@tonic-gate static int 10017c478bd9Sstevel@tonic-gate fd_read(dev_t dev, struct uio *uio, cred_t *cred_p) 10027c478bd9Sstevel@tonic-gate { 10037c478bd9Sstevel@tonic-gate return (physio(fd_strategy, NULL, dev, B_READ, minphys, uio)); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10077c478bd9Sstevel@tonic-gate static int 10087c478bd9Sstevel@tonic-gate fd_write(dev_t dev, struct uio *uio, cred_t *cred_p) 10097c478bd9Sstevel@tonic-gate { 10107c478bd9Sstevel@tonic-gate return (physio(fd_strategy, NULL, dev, B_WRITE, minphys, uio)); 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate /* 10147c478bd9Sstevel@tonic-gate * fd_strategy 10157c478bd9Sstevel@tonic-gate * checks operation, hangs buf struct off fdcntlr, calls fdstart 10167c478bd9Sstevel@tonic-gate * if not already busy. Note that if we call start, then the operation 10177c478bd9Sstevel@tonic-gate * will already be done on return (start sleeps). 10187c478bd9Sstevel@tonic-gate */ 10197c478bd9Sstevel@tonic-gate static int 10207c478bd9Sstevel@tonic-gate fd_strategy(struct buf *bp) 10217c478bd9Sstevel@tonic-gate { 10227c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 10237c478bd9Sstevel@tonic-gate struct fdisk *fdp; 10247c478bd9Sstevel@tonic-gate struct partition *pp; 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_STRA, 10277c478bd9Sstevel@tonic-gate (CE_CONT, "fd_strategy: bp = 0x%p, dev = 0x%lx\n", 10287c478bd9Sstevel@tonic-gate (void *)bp, bp->b_edev)); 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate (void) fd_getdrive(bp->b_edev, &fjp, &fdp); 10317c478bd9Sstevel@tonic-gate 10327c478bd9Sstevel@tonic-gate /* 10337c478bd9Sstevel@tonic-gate * Ignoring return because device exist. 10347c478bd9Sstevel@tonic-gate * Returned unit value is not used. 10357c478bd9Sstevel@tonic-gate */ 10367c478bd9Sstevel@tonic-gate pp = &fdp->d_part[PARTITION(bp->b_edev)]; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_sec_size > NBPSCTR && (bp->b_blkno & 1)) { 10397c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 10407c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: block %ld is not start of sector!", 10417c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), (long)bp->b_blkno)); 10427c478bd9Sstevel@tonic-gate bp->b_error = EINVAL; 10437c478bd9Sstevel@tonic-gate goto bad; 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate if ((bp->b_blkno > pp->p_size)) { 10477c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 10487c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: block %ld is past the end! (nblk=%ld)", 10497c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), (long)bp->b_blkno, pp->p_size)); 10507c478bd9Sstevel@tonic-gate bp->b_error = ENOSPC; 10517c478bd9Sstevel@tonic-gate goto bad; 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate /* if at end of file, skip out now */ 10557c478bd9Sstevel@tonic-gate if (bp->b_blkno == pp->p_size) { 10567c478bd9Sstevel@tonic-gate if ((bp->b_flags & B_READ) == 0) { 10577c478bd9Sstevel@tonic-gate /* a write needs to get an error! */ 10587c478bd9Sstevel@tonic-gate bp->b_error = ENOSPC; 10597c478bd9Sstevel@tonic-gate goto bad; 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; 10627c478bd9Sstevel@tonic-gate biodone(bp); 10637c478bd9Sstevel@tonic-gate return (0); 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate /* if operation not a multiple of sector size, is error! */ 10677c478bd9Sstevel@tonic-gate if (bp->b_bcount % fjp->fj_chars->fdc_sec_size) { 10687c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 10697c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: count %ld must be a multiple of %d", 10707c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), bp->b_bcount, 10717c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size)); 10727c478bd9Sstevel@tonic-gate bp->b_error = EINVAL; 10737c478bd9Sstevel@tonic-gate goto bad; 10747c478bd9Sstevel@tonic-gate } 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate /* 10777c478bd9Sstevel@tonic-gate * Put the buf request in the drive's queue, FIFO. 10787c478bd9Sstevel@tonic-gate */ 10797c478bd9Sstevel@tonic-gate bp->av_forw = 0; 10807c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 10817c478bd9Sstevel@tonic-gate if (fdp->d_iostat) 10827c478bd9Sstevel@tonic-gate kstat_waitq_enter(KIOSP); 10837c478bd9Sstevel@tonic-gate if (fdp->d_actf) 10847c478bd9Sstevel@tonic-gate fdp->d_actl->av_forw = bp; 10857c478bd9Sstevel@tonic-gate else 10867c478bd9Sstevel@tonic-gate fdp->d_actf = bp; 10877c478bd9Sstevel@tonic-gate fdp->d_actl = bp; 10887c478bd9Sstevel@tonic-gate if (!(fjp->fj_flags & FUNIT_BUSY)) { 10897c478bd9Sstevel@tonic-gate fdstart(fjp); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 10927c478bd9Sstevel@tonic-gate return (0); 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate bad: 10957c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; 10967c478bd9Sstevel@tonic-gate bp->b_flags |= B_ERROR; 10977c478bd9Sstevel@tonic-gate biodone(bp); 10987c478bd9Sstevel@tonic-gate return (0); 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate /* 11027c478bd9Sstevel@tonic-gate * fdstart 11037c478bd9Sstevel@tonic-gate * called from fd_strategy() or from fdXXXX() to setup and 11047c478bd9Sstevel@tonic-gate * start operations of read or write only (using buf structs). 11057c478bd9Sstevel@tonic-gate * Because the chip doesn't handle crossing cylinder boundaries on 11067c478bd9Sstevel@tonic-gate * the fly, this takes care of those boundary conditions. Note that 11077c478bd9Sstevel@tonic-gate * it sleeps until the operation is done *within fdstart* - so that 11087c478bd9Sstevel@tonic-gate * when fdstart returns, the operation is already done. 11097c478bd9Sstevel@tonic-gate */ 11107c478bd9Sstevel@tonic-gate static void 11117c478bd9Sstevel@tonic-gate fdstart(struct fcu_obj *fjp) 11127c478bd9Sstevel@tonic-gate { 11137c478bd9Sstevel@tonic-gate struct buf *bp; 11147c478bd9Sstevel@tonic-gate struct fdisk *fdp = (struct fdisk *)fjp->fj_data; 11157c478bd9Sstevel@tonic-gate struct fd_char *chp; 11167c478bd9Sstevel@tonic-gate struct partition *pp; 11177c478bd9Sstevel@tonic-gate uint_t ptend; 11187c478bd9Sstevel@tonic-gate uint_t bincyl; /* (the number of the desired) block in cyl. */ 11197c478bd9Sstevel@tonic-gate uint_t blk, len, tlen; 11207c478bd9Sstevel@tonic-gate uint_t secpcyl; /* number of sectors per cylinder */ 11217c478bd9Sstevel@tonic-gate int cyl, head, sect; 11227c478bd9Sstevel@tonic-gate int sctrshft, unit; 11237c478bd9Sstevel@tonic-gate caddr_t addr; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fjp->fj_lock)); 11267c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_BUSY; 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate while ((bp = fdp->d_actf) != NULL) { 11297c478bd9Sstevel@tonic-gate fdp->d_actf = bp->av_forw; 11307c478bd9Sstevel@tonic-gate fdp->d_current = bp; 11317c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 11327c478bd9Sstevel@tonic-gate kstat_waitq_to_runq(KIOSP); 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, 11377c478bd9Sstevel@tonic-gate (CE_CONT, "fdstart: bp=0x%p blkno=0x%lx bcount=0x%lx\n", 11387c478bd9Sstevel@tonic-gate (void *)bp, (long)bp->b_blkno, bp->b_bcount)); 11397c478bd9Sstevel@tonic-gate bp->b_flags &= ~B_ERROR; 11407c478bd9Sstevel@tonic-gate bp->b_error = 0; 11417c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; /* init resid */ 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate ASSERT(DRIVE(bp->b_edev) == ddi_get_instance(fjp->fj_dip)); 11447c478bd9Sstevel@tonic-gate unit = fjp->fj_unit; 11457c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate bp_mapin(bp); /* map in buffers */ 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate pp = &fdp->d_part[PARTITION(bp->b_edev)]; 11507c478bd9Sstevel@tonic-gate /* starting blk adjusted for the partition */ 11517c478bd9Sstevel@tonic-gate blk = bp->b_blkno + pp->p_start; 11527c478bd9Sstevel@tonic-gate ptend = pp->p_start + pp->p_size; /* end of the partition */ 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate chp = fjp->fj_chars; 11557c478bd9Sstevel@tonic-gate secpcyl = chp->fdc_nhead * chp->fdc_secptrack; 11567c478bd9Sstevel@tonic-gate switch (chp->fdc_sec_size) { 11577c478bd9Sstevel@tonic-gate /* convert logical block numbers to sector numbers */ 11587c478bd9Sstevel@tonic-gate case 1024: 11597c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT + 1; 11607c478bd9Sstevel@tonic-gate blk >>= 1; 11617c478bd9Sstevel@tonic-gate ptend >>= 1; 11627c478bd9Sstevel@tonic-gate break; 11637c478bd9Sstevel@tonic-gate default: 11647c478bd9Sstevel@tonic-gate case NBPSCTR: 11657c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT; 11667c478bd9Sstevel@tonic-gate break; 11677c478bd9Sstevel@tonic-gate case 256: 11687c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT - 1; 11697c478bd9Sstevel@tonic-gate blk <<= 1; 11707c478bd9Sstevel@tonic-gate ptend <<= 1; 11717c478bd9Sstevel@tonic-gate break; 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate /* 11757c478bd9Sstevel@tonic-gate * If off the end, limit to actual amount that 11767c478bd9Sstevel@tonic-gate * can be transferred. 11777c478bd9Sstevel@tonic-gate */ 11787c478bd9Sstevel@tonic-gate if ((blk + (bp->b_bcount >> sctrshft)) > ptend) 11797c478bd9Sstevel@tonic-gate /* to end of partition */ 11807c478bd9Sstevel@tonic-gate len = (ptend - blk) << sctrshft; 11817c478bd9Sstevel@tonic-gate else 11827c478bd9Sstevel@tonic-gate len = bp->b_bcount; 11837c478bd9Sstevel@tonic-gate addr = bp->b_un.b_addr; /* data buffer address */ 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate /* 11867c478bd9Sstevel@tonic-gate * now we have the real start blk, addr and len for xfer op 11877c478bd9Sstevel@tonic-gate */ 11887c478bd9Sstevel@tonic-gate while (len != 0) { 11897c478bd9Sstevel@tonic-gate /* start cyl of req */ 11907c478bd9Sstevel@tonic-gate cyl = blk / secpcyl; 11917c478bd9Sstevel@tonic-gate bincyl = blk % secpcyl; 11927c478bd9Sstevel@tonic-gate /* start head of req */ 11937c478bd9Sstevel@tonic-gate head = bincyl / chp->fdc_secptrack; 11947c478bd9Sstevel@tonic-gate /* start sector of req */ 11957c478bd9Sstevel@tonic-gate sect = (bincyl % chp->fdc_secptrack) + 1; 11967c478bd9Sstevel@tonic-gate /* 11977c478bd9Sstevel@tonic-gate * If the desired block and length will go beyond the 11987c478bd9Sstevel@tonic-gate * cylinder end, then limit it to the cylinder end. 11997c478bd9Sstevel@tonic-gate */ 12007c478bd9Sstevel@tonic-gate if (bp->b_flags & B_READ) { 12017c478bd9Sstevel@tonic-gate if (len > ((secpcyl - bincyl) << sctrshft)) 12027c478bd9Sstevel@tonic-gate tlen = (secpcyl - bincyl) << sctrshft; 12037c478bd9Sstevel@tonic-gate else 12047c478bd9Sstevel@tonic-gate tlen = len; 12057c478bd9Sstevel@tonic-gate } else { 12067c478bd9Sstevel@tonic-gate if (len > 12077c478bd9Sstevel@tonic-gate ((chp->fdc_secptrack - sect + 1) << 12087c478bd9Sstevel@tonic-gate sctrshft)) 12097c478bd9Sstevel@tonic-gate tlen = 12107c478bd9Sstevel@tonic-gate (chp->fdc_secptrack - sect + 1) << 12117c478bd9Sstevel@tonic-gate sctrshft; 12127c478bd9Sstevel@tonic-gate else 12137c478bd9Sstevel@tonic-gate tlen = len; 12147c478bd9Sstevel@tonic-gate } 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, (CE_CONT, 12177c478bd9Sstevel@tonic-gate " blk 0x%x addr 0x%p len 0x%x " 12187c478bd9Sstevel@tonic-gate "cyl %d head %d sec %d\n resid 0x%lx, tlen %d\n", 12197c478bd9Sstevel@tonic-gate blk, (void *)addr, len, cyl, head, sect, 12207c478bd9Sstevel@tonic-gate bp->b_resid, tlen)); 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate /* 12237c478bd9Sstevel@tonic-gate * (try to) do the operation - failure returns an errno 12247c478bd9Sstevel@tonic-gate */ 12257c478bd9Sstevel@tonic-gate bp->b_error = fjp->fj_ops->fco_rw(fjp, unit, 12267c478bd9Sstevel@tonic-gate bp->b_flags & B_READ, cyl, head, sect, addr, tlen); 12277c478bd9Sstevel@tonic-gate if (bp->b_error != 0) { 12287c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRT, (CE_WARN, 12297c478bd9Sstevel@tonic-gate "fdstart: bad exec of bp: 0x%p, err=%d", 12307c478bd9Sstevel@tonic-gate (void *)bp, bp->b_error)); 12317c478bd9Sstevel@tonic-gate bp->b_flags |= B_ERROR; 12327c478bd9Sstevel@tonic-gate break; 12337c478bd9Sstevel@tonic-gate } 12347c478bd9Sstevel@tonic-gate blk += tlen >> sctrshft; 12357c478bd9Sstevel@tonic-gate len -= tlen; 12367c478bd9Sstevel@tonic-gate addr += tlen; 12377c478bd9Sstevel@tonic-gate bp->b_resid -= tlen; 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, 12407c478bd9Sstevel@tonic-gate (CE_CONT, "fdstart done: b_resid %lu, b_count %lu\n", 12417c478bd9Sstevel@tonic-gate bp->b_resid, bp->b_bcount)); 12427c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 12437c478bd9Sstevel@tonic-gate if (bp->b_flags & B_READ) { 12447c478bd9Sstevel@tonic-gate KIOSP->reads++; 12457c478bd9Sstevel@tonic-gate KIOSP->nread += (bp->b_bcount - bp->b_resid); 12467c478bd9Sstevel@tonic-gate } else { 12477c478bd9Sstevel@tonic-gate KIOSP->writes++; 12487c478bd9Sstevel@tonic-gate KIOSP->nwritten += (bp->b_bcount - bp->b_resid); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate kstat_runq_exit(KIOSP); 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate bp_mapout(bp); 12537c478bd9Sstevel@tonic-gate biodone(bp); 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 12567c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 12577c478bd9Sstevel@tonic-gate fdp->d_current = 0; 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate fjp->fj_flags ^= FUNIT_BUSY; 12607c478bd9Sstevel@tonic-gate } 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate /* ARGSUSED */ 12637c478bd9Sstevel@tonic-gate static int 12647c478bd9Sstevel@tonic-gate fd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, 12657c478bd9Sstevel@tonic-gate int *rval_p) 12667c478bd9Sstevel@tonic-gate { 12677c478bd9Sstevel@tonic-gate union { 12687c478bd9Sstevel@tonic-gate struct dk_cinfo dki; 12697c478bd9Sstevel@tonic-gate struct dk_geom dkg; 12707c478bd9Sstevel@tonic-gate struct dk_allmap dka; 12717c478bd9Sstevel@tonic-gate struct fd_char fdchar; 12727c478bd9Sstevel@tonic-gate struct fd_drive drvchar; 12737c478bd9Sstevel@tonic-gate int temp; 12747c478bd9Sstevel@tonic-gate } cpy; 12757c478bd9Sstevel@tonic-gate struct vtoc vtoc; 12767c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 12777c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 12787c478bd9Sstevel@tonic-gate struct dk_map *dmp; 12797c478bd9Sstevel@tonic-gate struct dk_label *label; 12807c478bd9Sstevel@tonic-gate int nblks, part, unit; 12817c478bd9Sstevel@tonic-gate int rval = 0; 12827c478bd9Sstevel@tonic-gate enum dkio_state state; 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 12857c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 12867c478bd9Sstevel@tonic-gate return (ENXIO); 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_IOCT, 12897c478bd9Sstevel@tonic-gate (CE_CONT, "fd_ioctl fd unit %d: cmd %x, arg %lx\n", 12907c478bd9Sstevel@tonic-gate unit, cmd, arg)); 12917c478bd9Sstevel@tonic-gate 12927c478bd9Sstevel@tonic-gate switch (cmd) { 12937c478bd9Sstevel@tonic-gate case DKIOCINFO: 12947c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_dkinfo(fjp, &cpy.dki); 12957c478bd9Sstevel@tonic-gate cpy.dki.dki_cnum = FDCTLR(fjp->fj_unit); 12967c478bd9Sstevel@tonic-gate cpy.dki.dki_unit = FDUNIT(fjp->fj_unit); 12977c478bd9Sstevel@tonic-gate cpy.dki.dki_partition = PARTITION(dev); 12987c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dki, (void *)arg, sizeof (cpy.dki), flag)) 12997c478bd9Sstevel@tonic-gate rval = EFAULT; 13007c478bd9Sstevel@tonic-gate break; 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate case DKIOCG_PHYGEOM: 13037c478bd9Sstevel@tonic-gate case DKIOCG_VIRTGEOM: 13047c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = fjp->fj_chars->fdc_secptrack; 13057c478bd9Sstevel@tonic-gate goto get_geom; 13067c478bd9Sstevel@tonic-gate case DKIOCGGEOM: 13077c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_LABELOK) 13087c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = (fjp->fj_chars->fdc_secptrack * 13097c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 13107c478bd9Sstevel@tonic-gate else 13117c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = fjp->fj_chars->fdc_secptrack; 13127c478bd9Sstevel@tonic-gate get_geom: 13137c478bd9Sstevel@tonic-gate cpy.dkg.dkg_pcyl = fjp->fj_chars->fdc_ncyl; 13147c478bd9Sstevel@tonic-gate cpy.dkg.dkg_ncyl = fjp->fj_chars->fdc_ncyl; 13157c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nhead = fjp->fj_chars->fdc_nhead; 13167c478bd9Sstevel@tonic-gate cpy.dkg.dkg_intrlv = fjp->fj_attr->fda_intrlv; 13177c478bd9Sstevel@tonic-gate cpy.dkg.dkg_rpm = fjp->fj_attr->fda_rotatespd; 13187c478bd9Sstevel@tonic-gate cpy.dkg.dkg_read_reinstruct = 13197c478bd9Sstevel@tonic-gate (int)(cpy.dkg.dkg_nsect * cpy.dkg.dkg_rpm * 4) / 60000; 13207c478bd9Sstevel@tonic-gate cpy.dkg.dkg_write_reinstruct = cpy.dkg.dkg_read_reinstruct; 13217c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dkg, (void *)arg, sizeof (cpy.dkg), flag)) 13227c478bd9Sstevel@tonic-gate rval = EFAULT; 13237c478bd9Sstevel@tonic-gate break; 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate case DKIOCSGEOM: 13267c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.dkg, 13277c478bd9Sstevel@tonic-gate sizeof (struct dk_geom), flag)) { 13287c478bd9Sstevel@tonic-gate rval = EFAULT; 13297c478bd9Sstevel@tonic-gate break; 13307c478bd9Sstevel@tonic-gate } 13317c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 13327c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl = cpy.dkg.dkg_ncyl; 13337c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_nhead = cpy.dkg.dkg_nhead; 13347c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack = cpy.dkg.dkg_nsect; 13357c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv = cpy.dkg.dkg_intrlv; 13367c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = cpy.dkg.dkg_rpm; 13377c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 13387c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 13397c478bd9Sstevel@tonic-gate break; 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate /* 13427c478bd9Sstevel@tonic-gate * return the map of all logical partitions 13437c478bd9Sstevel@tonic-gate */ 13447c478bd9Sstevel@tonic-gate case DKIOCGAPART: 13457c478bd9Sstevel@tonic-gate /* 13467c478bd9Sstevel@tonic-gate * Note the conversion from starting sector number 13477c478bd9Sstevel@tonic-gate * to starting cylinder number. 13487c478bd9Sstevel@tonic-gate * Return error if division results in a remainder. 13497c478bd9Sstevel@tonic-gate */ 13507c478bd9Sstevel@tonic-gate nblks = fjp->fj_chars->fdc_nhead * fjp->fj_chars->fdc_secptrack; 13517c478bd9Sstevel@tonic-gate 13527c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 13537c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 13547c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 13557c478bd9Sstevel@tonic-gate { 13567c478bd9Sstevel@tonic-gate struct dk_allmap32 dka32; 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 13597c478bd9Sstevel@tonic-gate if ((fdp->d_part[part].p_start % nblks) != 0) 13607c478bd9Sstevel@tonic-gate return (EINVAL); 13617c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_cylno = 13627c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start / nblks; 13637c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_nblk = 13647c478bd9Sstevel@tonic-gate fdp->d_part[part].p_size; 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate if (ddi_copyout(&dka32, (void *)arg, 13687c478bd9Sstevel@tonic-gate sizeof (struct dk_allmap32), flag)) 13697c478bd9Sstevel@tonic-gate rval = EFAULT; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate break; 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate dmp = (struct dk_map *)&cpy.dka; 13787c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 13797c478bd9Sstevel@tonic-gate if ((fdp->d_part[part].p_start % nblks) != 0) 13807c478bd9Sstevel@tonic-gate return (EINVAL); 13817c478bd9Sstevel@tonic-gate dmp->dkl_cylno = 13827c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start / nblks; 13837c478bd9Sstevel@tonic-gate dmp->dkl_nblk = fdp->d_part[part].p_size; 13847c478bd9Sstevel@tonic-gate dmp++; 13857c478bd9Sstevel@tonic-gate } 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dka, (void *)arg, 13887c478bd9Sstevel@tonic-gate sizeof (struct dk_allmap), flag)) 13897c478bd9Sstevel@tonic-gate rval = EFAULT; 13907c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 13917c478bd9Sstevel@tonic-gate break; 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate break; 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate * Set the map of all logical partitions 14007c478bd9Sstevel@tonic-gate */ 14017c478bd9Sstevel@tonic-gate case DKIOCSAPART: 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 14047c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 14057c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 14067c478bd9Sstevel@tonic-gate { 14077c478bd9Sstevel@tonic-gate struct dk_allmap32 dka32; 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &dka32, 14107c478bd9Sstevel@tonic-gate sizeof (dka32), flag)) { 14117c478bd9Sstevel@tonic-gate rval = EFAULT; 14127c478bd9Sstevel@tonic-gate break; 14137c478bd9Sstevel@tonic-gate } 14147c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 14157c478bd9Sstevel@tonic-gate cpy.dka.dka_map[part].dkl_cylno = 14167c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_cylno; 14177c478bd9Sstevel@tonic-gate cpy.dka.dka_map[part].dkl_nblk = 14187c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_nblk; 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate break; 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14257c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.dka, sizeof (cpy.dka), flag)) 14267c478bd9Sstevel@tonic-gate rval = EFAULT; 14277c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate break; 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate if (rval != 0) 14347c478bd9Sstevel@tonic-gate break; 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate dmp = (struct dk_map *)&cpy.dka; 14377c478bd9Sstevel@tonic-gate nblks = fjp->fj_chars->fdc_nhead * 14387c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack; 14397c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 14407c478bd9Sstevel@tonic-gate /* 14417c478bd9Sstevel@tonic-gate * Note the conversion from starting cylinder number 14427c478bd9Sstevel@tonic-gate * to starting sector number. 14437c478bd9Sstevel@tonic-gate */ 14447c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 14457c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start = dmp->dkl_cylno * 14467c478bd9Sstevel@tonic-gate nblks; 14477c478bd9Sstevel@tonic-gate fdp->d_part[part].p_size = dmp->dkl_nblk; 14487c478bd9Sstevel@tonic-gate dmp++; 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 14517c478bd9Sstevel@tonic-gate 14527c478bd9Sstevel@tonic-gate break; 14537c478bd9Sstevel@tonic-gate 14547c478bd9Sstevel@tonic-gate case DKIOCGVTOC: 14557c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate /* 14587c478bd9Sstevel@tonic-gate * Exit if the diskette has no label. 14597c478bd9Sstevel@tonic-gate * Also, get the label to make sure the correct one is 14607c478bd9Sstevel@tonic-gate * being used since the diskette may have changed 14617c478bd9Sstevel@tonic-gate */ 14627c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 14637c478bd9Sstevel@tonic-gate rval = fdgetlabel(fjp, unit); 14647c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 14657c478bd9Sstevel@tonic-gate if (rval) { 14667c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 14677c478bd9Sstevel@tonic-gate rval = EINVAL; 14687c478bd9Sstevel@tonic-gate break; 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate fd_build_user_vtoc(fjp, fdp, &vtoc); 14727c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 14757c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 14767c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 14777c478bd9Sstevel@tonic-gate { 14787c478bd9Sstevel@tonic-gate struct vtoc32 vtoc32; 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate vtoctovtoc32(vtoc, vtoc32); 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate if (ddi_copyout(&vtoc32, (void *)arg, 14837c478bd9Sstevel@tonic-gate sizeof (vtoc32), flag)) 14847c478bd9Sstevel@tonic-gate rval = EFAULT; 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate break; 14877c478bd9Sstevel@tonic-gate } 14887c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14917c478bd9Sstevel@tonic-gate if (ddi_copyout(&vtoc, (void *)arg, 14927c478bd9Sstevel@tonic-gate sizeof (vtoc), flag)) 14937c478bd9Sstevel@tonic-gate rval = EFAULT; 14947c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 14957c478bd9Sstevel@tonic-gate break; 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate break; 15007c478bd9Sstevel@tonic-gate 15017c478bd9Sstevel@tonic-gate case DKIOCSVTOC: 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 15047c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 15057c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 15067c478bd9Sstevel@tonic-gate { 15077c478bd9Sstevel@tonic-gate struct vtoc32 vtoc32; 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &vtoc32, 15107c478bd9Sstevel@tonic-gate sizeof (vtoc32), flag)) { 15117c478bd9Sstevel@tonic-gate rval = EFAULT; 15127c478bd9Sstevel@tonic-gate break; 15137c478bd9Sstevel@tonic-gate } 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate vtoc32tovtoc(vtoc32, vtoc); 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate break; 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 15227c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &vtoc, sizeof (vtoc), flag)) 15237c478bd9Sstevel@tonic-gate rval = EFAULT; 15247c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 15257c478bd9Sstevel@tonic-gate break; 15267c478bd9Sstevel@tonic-gate } 15277c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate if (rval != 0) 15307c478bd9Sstevel@tonic-gate break; 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate label = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate if ((rval = fd_build_label_vtoc(fjp, fdp, &vtoc, label)) == 0) { 15387c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 15397c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_rw(fjp, unit, FDWRITE, 15407c478bd9Sstevel@tonic-gate 0, 0, 1, (caddr_t)label, sizeof (struct dk_label)); 15417c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 15427c478bd9Sstevel@tonic-gate } 15437c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 15447c478bd9Sstevel@tonic-gate kmem_free(label, sizeof (struct dk_label)); 15457c478bd9Sstevel@tonic-gate break; 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate case DKIOCSTATE: 15487c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_IOCT, 15497c478bd9Sstevel@tonic-gate (CE_CONT, "fd_ioctl fd unit %d: DKIOCSTATE\n", unit)); 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &state, sizeof (int), flag)) { 15527c478bd9Sstevel@tonic-gate rval = EFAULT; 15537c478bd9Sstevel@tonic-gate break; 15547c478bd9Sstevel@tonic-gate } 15557c478bd9Sstevel@tonic-gate 15567c478bd9Sstevel@tonic-gate rval = fd_check_media(dev, state); 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate if (ddi_copyout(&fdp->d_media_state, (void *)arg, 15597c478bd9Sstevel@tonic-gate sizeof (int), flag)) 15607c478bd9Sstevel@tonic-gate rval = EFAULT; 15617c478bd9Sstevel@tonic-gate break; 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate case FDIOGCHAR: 15647c478bd9Sstevel@tonic-gate if (ddi_copyout(fjp->fj_chars, (void *)arg, 15657c478bd9Sstevel@tonic-gate sizeof (struct fd_char), flag)) 15667c478bd9Sstevel@tonic-gate rval = EFAULT; 15677c478bd9Sstevel@tonic-gate break; 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate case FDIOSCHAR: 15707c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.fdchar, 15717c478bd9Sstevel@tonic-gate sizeof (struct fd_char), flag)) { 15727c478bd9Sstevel@tonic-gate rval = EFAULT; 15737c478bd9Sstevel@tonic-gate break; 15747c478bd9Sstevel@tonic-gate } 15757c478bd9Sstevel@tonic-gate switch (cpy.fdchar.fdc_transfer_rate) { 15767c478bd9Sstevel@tonic-gate case 417: 15777c478bd9Sstevel@tonic-gate if ((fdp->d_media & (1 << FMT_3M)) == 0) { 15787c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 15797c478bd9Sstevel@tonic-gate "fdioschar:Medium density not supported\n"); 15807c478bd9Sstevel@tonic-gate rval = EINVAL; 15817c478bd9Sstevel@tonic-gate break; 15827c478bd9Sstevel@tonic-gate } 15837c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 15847c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = 360; 15857c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 15867c478bd9Sstevel@tonic-gate /* cpy.fdchar.fdc_transfer_rate = 500; */ 15877c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15887c478bd9Sstevel@tonic-gate case 1000: 15897c478bd9Sstevel@tonic-gate case 500: 15907c478bd9Sstevel@tonic-gate case 300: 15917c478bd9Sstevel@tonic-gate case 250: 15927c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 15937c478bd9Sstevel@tonic-gate *(fjp->fj_chars) = cpy.fdchar; 15947c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 15957c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 15967c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate break; 15997c478bd9Sstevel@tonic-gate 16007c478bd9Sstevel@tonic-gate default: 16017c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 16027c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: FDIOSCHAR odd " 16037c478bd9Sstevel@tonic-gate "xfer rate %dkbs", 16047c478bd9Sstevel@tonic-gate unit, cpy.fdchar.fdc_transfer_rate)); 16057c478bd9Sstevel@tonic-gate rval = EINVAL; 16067c478bd9Sstevel@tonic-gate break; 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate break; 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate /* 16117c478bd9Sstevel@tonic-gate * set all characteristics and geometry to the defaults 16127c478bd9Sstevel@tonic-gate */ 16137c478bd9Sstevel@tonic-gate case FDDEFGEOCHAR: 16147c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 16157c478bd9Sstevel@tonic-gate fdp->d_curfdtype = fdp->d_deffdtype; 16167c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_curfdtype]; 16177c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_curfdtype]; 16187c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_curfdtype], 16197c478bd9Sstevel@tonic-gate fdp->d_part, sizeof (struct partition) * NDKMAP); 16207c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 16217c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 16227c478bd9Sstevel@tonic-gate break; 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate case FDEJECT: /* eject disk */ 16257c478bd9Sstevel@tonic-gate case DKIOCEJECT: 16267c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 16277c478bd9Sstevel@tonic-gate rval = ENOSYS; 16287c478bd9Sstevel@tonic-gate break; 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate case FDGETCHANGE: /* disk changed */ 16317c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.temp, sizeof (int), flag)) { 16327c478bd9Sstevel@tonic-gate rval = EFAULT; 16337c478bd9Sstevel@tonic-gate break; 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 16367c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHANGED) 16397c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_HISTORY; 16407c478bd9Sstevel@tonic-gate else 16417c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_HISTORY; 16427c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHANGED; 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 16457c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_DETECTED; 16467c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_resetchng(fjp, unit); 16477c478bd9Sstevel@tonic-gate /* 16487c478bd9Sstevel@tonic-gate * check diskette again only if it was removed 16497c478bd9Sstevel@tonic-gate */ 16507c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 16517c478bd9Sstevel@tonic-gate /* 16527c478bd9Sstevel@tonic-gate * no diskette is present 16537c478bd9Sstevel@tonic-gate */ 16547c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_CURRENT; 16557c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHGDET) 16567c478bd9Sstevel@tonic-gate /* 16577c478bd9Sstevel@tonic-gate * again no diskette; not a new change 16587c478bd9Sstevel@tonic-gate */ 16597c478bd9Sstevel@tonic-gate cpy.temp ^= FDGC_DETECTED; 16607c478bd9Sstevel@tonic-gate else 16617c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_CHGDET; 16627c478bd9Sstevel@tonic-gate } else { 16637c478bd9Sstevel@tonic-gate /* 16647c478bd9Sstevel@tonic-gate * a new diskette is present 16657c478bd9Sstevel@tonic-gate */ 16667c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_CURRENT; 16677c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate } else { 16707c478bd9Sstevel@tonic-gate cpy.temp &= ~(FDGC_DETECTED | FDGC_CURRENT); 16717c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate /* 16747c478bd9Sstevel@tonic-gate * also get state of write protection 16757c478bd9Sstevel@tonic-gate */ 16767c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_WPROT) { 16777c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_CURWPROT; 16787c478bd9Sstevel@tonic-gate } else { 16797c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_CURWPROT; 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 16827c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.temp, (void *)arg, sizeof (int), flag)) 16857c478bd9Sstevel@tonic-gate rval = EFAULT; 16867c478bd9Sstevel@tonic-gate break; 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate case FDGETDRIVECHAR: 16897c478bd9Sstevel@tonic-gate if (ddi_copyout(fjp->fj_drive, (void *)arg, 16907c478bd9Sstevel@tonic-gate sizeof (struct fd_drive), flag)) 16917c478bd9Sstevel@tonic-gate rval = EFAULT; 16927c478bd9Sstevel@tonic-gate break; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate case FDSETDRIVECHAR: 16957c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.drvchar, 16967c478bd9Sstevel@tonic-gate sizeof (struct fd_drive), flag)) { 16977c478bd9Sstevel@tonic-gate rval = EFAULT; 16987c478bd9Sstevel@tonic-gate break; 16997c478bd9Sstevel@tonic-gate } 17007c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 17017c478bd9Sstevel@tonic-gate *(fjp->fj_drive) = cpy.drvchar; 17027c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 17037c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 17047c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 17057c478bd9Sstevel@tonic-gate break; 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate case DKIOCREMOVABLE: { 17087c478bd9Sstevel@tonic-gate int i = 1; 17097c478bd9Sstevel@tonic-gate 17107c478bd9Sstevel@tonic-gate /* no brainer: floppies are always removable */ 17117c478bd9Sstevel@tonic-gate if (ddi_copyout(&i, (void *)arg, sizeof (int), flag)) { 17127c478bd9Sstevel@tonic-gate rval = EFAULT; 17137c478bd9Sstevel@tonic-gate } 17147c478bd9Sstevel@tonic-gate break; 17157c478bd9Sstevel@tonic-gate } 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate case DKIOCGMEDIAINFO: 17187c478bd9Sstevel@tonic-gate rval = fd_get_media_info(fjp, (caddr_t)arg, flag); 17197c478bd9Sstevel@tonic-gate break; 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate case FDIOCMD: 17227c478bd9Sstevel@tonic-gate { 17237c478bd9Sstevel@tonic-gate struct fd_cmd fc; 17247c478bd9Sstevel@tonic-gate int cyl, head, spc, spt; 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 17277c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 17287c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 17297c478bd9Sstevel@tonic-gate { 17307c478bd9Sstevel@tonic-gate struct fd_cmd32 fc32; 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &fc32, 17337c478bd9Sstevel@tonic-gate sizeof (fc32), flag)) { 17347c478bd9Sstevel@tonic-gate rval = EFAULT; 17357c478bd9Sstevel@tonic-gate break; 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate fc.fdc_cmd = fc32.fdc_cmd; 17397c478bd9Sstevel@tonic-gate fc.fdc_flags = fc32.fdc_flags; 17407c478bd9Sstevel@tonic-gate fc.fdc_blkno = fc32.fdc_blkno; 17417c478bd9Sstevel@tonic-gate fc.fdc_secnt = fc32.fdc_secnt; 17427c478bd9Sstevel@tonic-gate fc.fdc_bufaddr = (caddr_t)(uintptr_t)fc32.fdc_bufaddr; 17437c478bd9Sstevel@tonic-gate fc.fdc_buflen = fc32.fdc_buflen; 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate break; 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &fc, sizeof (fc), flag)) { 17527c478bd9Sstevel@tonic-gate rval = EFAULT; 17537c478bd9Sstevel@tonic-gate break; 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 17567c478bd9Sstevel@tonic-gate break; 17577c478bd9Sstevel@tonic-gate } 17587c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate if (rval != 0) 17617c478bd9Sstevel@tonic-gate break; 17627c478bd9Sstevel@tonic-gate 17637c478bd9Sstevel@tonic-gate if (fc.fdc_cmd == FDCMD_READ || fc.fdc_cmd == FDCMD_WRITE) { 17647c478bd9Sstevel@tonic-gate auto struct iovec aiov; 17657c478bd9Sstevel@tonic-gate auto struct uio auio; 17667c478bd9Sstevel@tonic-gate struct uio *uio = &auio; 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate spc = (fc.fdc_cmd == FDCMD_READ)? B_READ: B_WRITE; 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate bzero(&auio, sizeof (struct uio)); 17717c478bd9Sstevel@tonic-gate bzero(&aiov, sizeof (struct iovec)); 17727c478bd9Sstevel@tonic-gate aiov.iov_base = fc.fdc_bufaddr; 17737c478bd9Sstevel@tonic-gate aiov.iov_len = (uint_t)fc.fdc_secnt * 17747c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size; 17757c478bd9Sstevel@tonic-gate uio->uio_iov = &aiov; 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 1; 17787c478bd9Sstevel@tonic-gate uio->uio_resid = aiov.iov_len; 17797c478bd9Sstevel@tonic-gate uio->uio_segflg = UIO_USERSPACE; 17807c478bd9Sstevel@tonic-gate 17817c478bd9Sstevel@tonic-gate rval = physio(fd_strategy, (struct buf *)0, dev, 17827c478bd9Sstevel@tonic-gate spc, minphys, uio); 17837c478bd9Sstevel@tonic-gate break; 17847c478bd9Sstevel@tonic-gate } else if (fc.fdc_cmd == FDCMD_FORMAT_TRACK) { 17857c478bd9Sstevel@tonic-gate spt = fjp->fj_chars->fdc_secptrack; /* sec/trk */ 17867c478bd9Sstevel@tonic-gate spc = fjp->fj_chars->fdc_nhead * spt; /* sec/cyl */ 17877c478bd9Sstevel@tonic-gate cyl = fc.fdc_blkno / spc; 17887c478bd9Sstevel@tonic-gate head = (fc.fdc_blkno % spc) / spt; 17897c478bd9Sstevel@tonic-gate if ((cyl | head) == 0) 17907c478bd9Sstevel@tonic-gate fjp->fj_flags &= 17917c478bd9Sstevel@tonic-gate ~(FUNIT_LABELOK | FUNIT_UNLABELED); 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_FORM, 17947c478bd9Sstevel@tonic-gate (CE_CONT, "fd_format cyl %d, hd %d\n", cyl, head)); 17957c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 17967c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_format(fjp, unit, cyl, head, 17977c478bd9Sstevel@tonic-gate (int)fc.fdc_flags); 17987c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate break; 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 18037c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: FDIOCSCMD not yet complete", 18047c478bd9Sstevel@tonic-gate unit)); 18057c478bd9Sstevel@tonic-gate rval = EINVAL; 18067c478bd9Sstevel@tonic-gate break; 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate case FDRAW: 18107c478bd9Sstevel@tonic-gate rval = fd_rawioctl(fjp, unit, (caddr_t)arg, flag); 18117c478bd9Sstevel@tonic-gate break; 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate default: 18147c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 18157c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: invalid ioctl 0x%x", 18167c478bd9Sstevel@tonic-gate unit, cmd)); 18177c478bd9Sstevel@tonic-gate rval = ENOTTY; 18187c478bd9Sstevel@tonic-gate break; 18197c478bd9Sstevel@tonic-gate } 18207c478bd9Sstevel@tonic-gate return (rval); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate static void 18247c478bd9Sstevel@tonic-gate fd_build_user_vtoc(struct fcu_obj *fjp, struct fdisk *fdp, struct vtoc *vtocp) 18257c478bd9Sstevel@tonic-gate { 18267c478bd9Sstevel@tonic-gate struct partition *vpart; 18277c478bd9Sstevel@tonic-gate int i; 18287c478bd9Sstevel@tonic-gate int xblk; 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate /* 18317c478bd9Sstevel@tonic-gate * Return vtoc structure fields in the provided VTOC area, addressed 18327c478bd9Sstevel@tonic-gate * by *vtocp. 18337c478bd9Sstevel@tonic-gate * 18347c478bd9Sstevel@tonic-gate */ 18357c478bd9Sstevel@tonic-gate bzero(vtocp, sizeof (struct vtoc)); 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_bootinfo, 18387c478bd9Sstevel@tonic-gate vtocp->v_bootinfo, sizeof (vtocp->v_bootinfo)); 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate vtocp->v_sanity = VTOC_SANE; 18417c478bd9Sstevel@tonic-gate vtocp->v_version = fdp->d_vtoc_version; 18427c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_volume, vtocp->v_volume, LEN_DKL_VVOL); 18437c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_LABELOK) { 18447c478bd9Sstevel@tonic-gate vtocp->v_sectorsz = DEV_BSIZE; 18457c478bd9Sstevel@tonic-gate xblk = 1; 18467c478bd9Sstevel@tonic-gate } else { 18477c478bd9Sstevel@tonic-gate vtocp->v_sectorsz = fjp->fj_chars->fdc_sec_size; 18487c478bd9Sstevel@tonic-gate xblk = vtocp->v_sectorsz / DEV_BSIZE; 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate vtocp->v_nparts = 3; /* <= NDKMAP; */ 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate /* 18537c478bd9Sstevel@tonic-gate * Copy partitioning information. 18547c478bd9Sstevel@tonic-gate */ 18557c478bd9Sstevel@tonic-gate bcopy(fdp->d_part, vtocp->v_part, sizeof (struct partition) * NDKMAP); 18567c478bd9Sstevel@tonic-gate for (i = NDKMAP, vpart = vtocp->v_part; i && (xblk > 1); i--, vpart++) { 18577c478bd9Sstevel@tonic-gate /* correct partition info if sector size > 512 bytes */ 18587c478bd9Sstevel@tonic-gate vpart->p_start /= xblk; 18597c478bd9Sstevel@tonic-gate vpart->p_size /= xblk; 18607c478bd9Sstevel@tonic-gate } 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_timestamp, 18637c478bd9Sstevel@tonic-gate vtocp->timestamp, sizeof (fdp->d_vtoc_timestamp)); 18647c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_asciilabel, vtocp->v_asciilabel, LEN_DKL_ASCII); 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate 18687c478bd9Sstevel@tonic-gate static int 18697c478bd9Sstevel@tonic-gate fd_build_label_vtoc(struct fcu_obj *fjp, struct fdisk *fdp, struct vtoc *vtocp, 18707c478bd9Sstevel@tonic-gate struct dk_label *labelp) 18717c478bd9Sstevel@tonic-gate { 18727c478bd9Sstevel@tonic-gate struct partition *vpart; 18737c478bd9Sstevel@tonic-gate int i; 18747c478bd9Sstevel@tonic-gate int nblks; 18757c478bd9Sstevel@tonic-gate int ncyl; 18767c478bd9Sstevel@tonic-gate ushort_t sum, *sp; 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate 18797c478bd9Sstevel@tonic-gate /* 18807c478bd9Sstevel@tonic-gate * Sanity-check the vtoc 18817c478bd9Sstevel@tonic-gate */ 18827c478bd9Sstevel@tonic-gate if (vtocp->v_sanity != VTOC_SANE || 18837c478bd9Sstevel@tonic-gate vtocp->v_nparts > NDKMAP || vtocp->v_nparts <= 0) { 18847c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_IOCT, 18857c478bd9Sstevel@tonic-gate (CE_WARN, "fd_build_label: sanity check on vtoc failed")); 18867c478bd9Sstevel@tonic-gate return (EINVAL); 18877c478bd9Sstevel@tonic-gate } 18887c478bd9Sstevel@tonic-gate 18897c478bd9Sstevel@tonic-gate /* 18907c478bd9Sstevel@tonic-gate * before copying the vtoc, the partition information in it should be 18917c478bd9Sstevel@tonic-gate * checked against the information the driver already has on the 18927c478bd9Sstevel@tonic-gate * diskette. 18937c478bd9Sstevel@tonic-gate */ 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate nblks = (fjp->fj_chars->fdc_nhead * fjp->fj_chars->fdc_secptrack * 18967c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 18977c478bd9Sstevel@tonic-gate if (nblks == 0 || fjp->fj_chars->fdc_ncyl == 0) 18987c478bd9Sstevel@tonic-gate return (EFAULT); 18997c478bd9Sstevel@tonic-gate vpart = vtocp->v_part; 19007c478bd9Sstevel@tonic-gate 19017c478bd9Sstevel@tonic-gate /* 19027c478bd9Sstevel@tonic-gate * Check the partition information in the vtoc. The starting sectors 19037c478bd9Sstevel@tonic-gate * must lie along cylinder boundaries. (NDKMAP entries are checked 19047c478bd9Sstevel@tonic-gate * to ensure that the unused entries are set to 0 if vtoc->v_nparts 19057c478bd9Sstevel@tonic-gate * is less than NDKMAP) 19067c478bd9Sstevel@tonic-gate */ 19077c478bd9Sstevel@tonic-gate for (i = NDKMAP; i; i--) { 19087c478bd9Sstevel@tonic-gate if ((vpart->p_start % nblks) != 0) { 19097c478bd9Sstevel@tonic-gate return (EINVAL); 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate ncyl = vpart->p_start / nblks; 19127c478bd9Sstevel@tonic-gate ncyl += vpart->p_size / nblks; 19137c478bd9Sstevel@tonic-gate if ((vpart->p_size % nblks) != 0) 19147c478bd9Sstevel@tonic-gate ncyl++; 19157c478bd9Sstevel@tonic-gate if (ncyl > (long)fjp->fj_chars->fdc_ncyl) { 19167c478bd9Sstevel@tonic-gate return (EINVAL); 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate vpart++; 19197c478bd9Sstevel@tonic-gate } 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate 19227c478bd9Sstevel@tonic-gate bcopy(vtocp->v_bootinfo, fdp->d_vtoc_bootinfo, 19237c478bd9Sstevel@tonic-gate sizeof (vtocp->v_bootinfo)); 19247c478bd9Sstevel@tonic-gate fdp->d_vtoc_version = vtocp->v_version; 19257c478bd9Sstevel@tonic-gate bcopy(vtocp->v_volume, fdp->d_vtoc_volume, LEN_DKL_VVOL); 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate /* 19287c478bd9Sstevel@tonic-gate * Copy partitioning information. 19297c478bd9Sstevel@tonic-gate */ 19307c478bd9Sstevel@tonic-gate bcopy(vtocp->v_part, fdp->d_part, sizeof (struct partition) * NDKMAP); 19317c478bd9Sstevel@tonic-gate bcopy(vtocp->timestamp, fdp->d_vtoc_timestamp, 19327c478bd9Sstevel@tonic-gate sizeof (fdp->d_vtoc_timestamp)); 19337c478bd9Sstevel@tonic-gate bcopy(vtocp->v_asciilabel, fdp->d_vtoc_asciilabel, LEN_DKL_ASCII); 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate /* 19367c478bd9Sstevel@tonic-gate * construct the diskette label in supplied buffer 19377c478bd9Sstevel@tonic-gate */ 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate /* Put appropriate vtoc structure fields into the disk label */ 19407c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[0] = (uint32_t)vtocp->v_bootinfo[0]; 19417c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[1] = (uint32_t)vtocp->v_bootinfo[1]; 19427c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[2] = (uint32_t)vtocp->v_bootinfo[2]; 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_sanity = vtocp->v_sanity; 19457c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_version = vtocp->v_version; 19467c478bd9Sstevel@tonic-gate 19477c478bd9Sstevel@tonic-gate bcopy(vtocp->v_volume, labelp->dkl_vtoc.v_volume, LEN_DKL_VVOL); 19487c478bd9Sstevel@tonic-gate 19497c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_nparts = vtocp->v_nparts; 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate bcopy(vtocp->v_reserved, labelp->dkl_vtoc.v_reserved, 19527c478bd9Sstevel@tonic-gate sizeof (labelp->dkl_vtoc.v_reserved)); 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate for (i = 0; i < (int)vtocp->v_nparts; i++) { 19557c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_tag = vtocp->v_part[i].p_tag; 19567c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_flag = vtocp->v_part[i].p_flag; 19577c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_start = vtocp->v_part[i].p_start; 19587c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_size = vtocp->v_part[i].p_size; 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 19627c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_timestamp[i] = vtocp->timestamp[i]; 19637c478bd9Sstevel@tonic-gate } 19647c478bd9Sstevel@tonic-gate bcopy(vtocp->v_asciilabel, labelp->dkl_asciilabel, LEN_DKL_ASCII); 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate labelp->dkl_pcyl = fjp->fj_chars->fdc_ncyl; 19687c478bd9Sstevel@tonic-gate labelp->dkl_ncyl = fjp->fj_chars->fdc_ncyl; 19697c478bd9Sstevel@tonic-gate labelp->dkl_nhead = fjp->fj_chars->fdc_nhead; 19707c478bd9Sstevel@tonic-gate /* 19717c478bd9Sstevel@tonic-gate * The fdc_secptrack field of the fd_char structure is the number 19727c478bd9Sstevel@tonic-gate * of sectors per track where the sectors are fdc_sec_size. 19737c478bd9Sstevel@tonic-gate * The dkl_nsect field of the dk_label structure is the number of 19747c478bd9Sstevel@tonic-gate * DEV_BSIZE (512) byte sectors per track. 19757c478bd9Sstevel@tonic-gate */ 19767c478bd9Sstevel@tonic-gate labelp->dkl_nsect = (fjp->fj_chars->fdc_secptrack * 19777c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 19787c478bd9Sstevel@tonic-gate labelp->dkl_intrlv = fjp->fj_attr->fda_intrlv; 19797c478bd9Sstevel@tonic-gate labelp->dkl_rpm = fjp->fj_attr->fda_rotatespd; 19807c478bd9Sstevel@tonic-gate labelp->dkl_read_reinstruct = 19817c478bd9Sstevel@tonic-gate (int)(labelp->dkl_nsect * labelp->dkl_rpm * 4) / 60000; 19827c478bd9Sstevel@tonic-gate labelp->dkl_write_reinstruct = labelp->dkl_read_reinstruct; 19837c478bd9Sstevel@tonic-gate 19847c478bd9Sstevel@tonic-gate labelp->dkl_magic = DKL_MAGIC; 19857c478bd9Sstevel@tonic-gate 19867c478bd9Sstevel@tonic-gate sum = 0; 19877c478bd9Sstevel@tonic-gate labelp->dkl_cksum = 0; 19887c478bd9Sstevel@tonic-gate sp = (ushort_t *)labelp; 19897c478bd9Sstevel@tonic-gate while (sp < &(labelp->dkl_cksum)) { 19907c478bd9Sstevel@tonic-gate sum ^= *sp++; 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate labelp->dkl_cksum = sum; 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate return (0); 19957c478bd9Sstevel@tonic-gate } 19967c478bd9Sstevel@tonic-gate 19977c478bd9Sstevel@tonic-gate static int 19987c478bd9Sstevel@tonic-gate fd_rawioctl(struct fcu_obj *fjp, int unit, caddr_t arg, int mode) 19997c478bd9Sstevel@tonic-gate { 20007c478bd9Sstevel@tonic-gate struct fd_raw fdr; 20017c478bd9Sstevel@tonic-gate char *arg_result = NULL; 20027c478bd9Sstevel@tonic-gate int flag = B_READ; 20037c478bd9Sstevel@tonic-gate int rval = 0; 20047c478bd9Sstevel@tonic-gate caddr_t uaddr; 20057c478bd9Sstevel@tonic-gate uint_t ucount; 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_RAWI, 20087c478bd9Sstevel@tonic-gate (CE_CONT, "fd_rawioctl: cmd[0]=0x%x\n", fdr.fdr_cmd[0])); 20097c478bd9Sstevel@tonic-gate 20107c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_medium != 3 && fjp->fj_chars->fdc_medium != 5) { 20117c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "fd_rawioctl: Medium density not supported\n"); 20127c478bd9Sstevel@tonic-gate return (ENXIO); 20137c478bd9Sstevel@tonic-gate } 20147c478bd9Sstevel@tonic-gate 20157c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 20167c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 20177c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 20187c478bd9Sstevel@tonic-gate { 20197c478bd9Sstevel@tonic-gate struct fd_raw32 fdr32; 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, &fdr32, sizeof (fdr32), mode)) 20227c478bd9Sstevel@tonic-gate return (EFAULT); 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate bcopy(fdr32.fdr_cmd, fdr.fdr_cmd, sizeof (fdr.fdr_cmd)); 20257c478bd9Sstevel@tonic-gate fdr.fdr_cnum = fdr32.fdr_cnum; 20267c478bd9Sstevel@tonic-gate fdr.fdr_nbytes = fdr32.fdr_nbytes; 20277c478bd9Sstevel@tonic-gate fdr.fdr_addr = (caddr_t)(uintptr_t)fdr32.fdr_addr; 20287c478bd9Sstevel@tonic-gate arg_result = ((struct fd_raw32 *)arg)->fdr_result; 20297c478bd9Sstevel@tonic-gate 20307c478bd9Sstevel@tonic-gate break; 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 20337c478bd9Sstevel@tonic-gate #endif /* ! _MULTI_DATAMODEL */ 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, &fdr, sizeof (fdr), mode)) 20367c478bd9Sstevel@tonic-gate return (EFAULT); 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate arg_result = ((struct fd_raw *)arg)->fdr_result; 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 20417c478bd9Sstevel@tonic-gate break; 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate /* 20487c478bd9Sstevel@tonic-gate * copy user address & nbytes from raw_req so that we can 20497c478bd9Sstevel@tonic-gate * put kernel address in req structure 20507c478bd9Sstevel@tonic-gate */ 20517c478bd9Sstevel@tonic-gate uaddr = fdr.fdr_addr; 20527c478bd9Sstevel@tonic-gate ucount = (uint_t)fdr.fdr_nbytes; 20537c478bd9Sstevel@tonic-gate unit &= 3; 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate switch (fdr.fdr_cmd[0] & 0x0f) { 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate case FDRAW_FORMAT: 20587c478bd9Sstevel@tonic-gate ucount += 16; 20597c478bd9Sstevel@tonic-gate fdr.fdr_addr = kmem_zalloc(ucount, KM_SLEEP); 20607c478bd9Sstevel@tonic-gate if (ddi_copyin(uaddr, fdr.fdr_addr, 20617c478bd9Sstevel@tonic-gate (size_t)fdr.fdr_nbytes, mode)) { 20627c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 20637c478bd9Sstevel@tonic-gate return (EFAULT); 20647c478bd9Sstevel@tonic-gate } 20657c478bd9Sstevel@tonic-gate if ((*fdr.fdr_addr | fdr.fdr_addr[1]) == 0) 20667c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 20677c478bd9Sstevel@tonic-gate flag = B_WRITE; 20687c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 20697c478bd9Sstevel@tonic-gate break; 20707c478bd9Sstevel@tonic-gate 20717c478bd9Sstevel@tonic-gate case FDRAW_WRCMD: 20727c478bd9Sstevel@tonic-gate case FDRAW_WRITEDEL: 20737c478bd9Sstevel@tonic-gate flag = B_WRITE; 20747c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 20757c478bd9Sstevel@tonic-gate case FDRAW_RDCMD: 20767c478bd9Sstevel@tonic-gate case FDRAW_READDEL: 20777c478bd9Sstevel@tonic-gate case FDRAW_READTRACK: 20787c478bd9Sstevel@tonic-gate if (ucount) { 20797c478bd9Sstevel@tonic-gate /* 20807c478bd9Sstevel@tonic-gate * In SunOS 4.X, we used to as_fault things in. 20817c478bd9Sstevel@tonic-gate * We really cannot do this in 5.0/SVr4. Unless 20827c478bd9Sstevel@tonic-gate * someone really believes that speed is of the 20837c478bd9Sstevel@tonic-gate * essence here, it is just much simpler to do 20847c478bd9Sstevel@tonic-gate * this in kernel space and use copyin/copyout. 20857c478bd9Sstevel@tonic-gate */ 20867c478bd9Sstevel@tonic-gate fdr.fdr_addr = kmem_alloc((size_t)ucount, KM_SLEEP); 20877c478bd9Sstevel@tonic-gate if (flag == B_WRITE) { 20887c478bd9Sstevel@tonic-gate if (ddi_copyin(uaddr, fdr.fdr_addr, ucount, 20897c478bd9Sstevel@tonic-gate mode)) { 20907c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 20917c478bd9Sstevel@tonic-gate return (EFAULT); 20927c478bd9Sstevel@tonic-gate } 20937c478bd9Sstevel@tonic-gate } 20947c478bd9Sstevel@tonic-gate } else 20957c478bd9Sstevel@tonic-gate return (EINVAL); 20967c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 20977c478bd9Sstevel@tonic-gate break; 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate case FDRAW_READID: 21007c478bd9Sstevel@tonic-gate case FDRAW_REZERO: 21017c478bd9Sstevel@tonic-gate case FDRAW_SEEK: 21027c478bd9Sstevel@tonic-gate case FDRAW_SENSE_DRV: 21037c478bd9Sstevel@tonic-gate ucount = 0; 21047c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 21057c478bd9Sstevel@tonic-gate break; 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate case FDRAW_SPECIFY: 21087c478bd9Sstevel@tonic-gate fdr.fdr_cmd[2] &= 0xfe; /* keep NoDMA bit clear */ 21097c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 21107c478bd9Sstevel@tonic-gate case FDRAW_SENSE_INT: 21117c478bd9Sstevel@tonic-gate ucount = 0; 21127c478bd9Sstevel@tonic-gate break; 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate default: 21157c478bd9Sstevel@tonic-gate return (EINVAL); 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate /* 21197c478bd9Sstevel@tonic-gate * Note that we ignore any error returns from controller 21207c478bd9Sstevel@tonic-gate * This is the way the driver has been, and it may be 21217c478bd9Sstevel@tonic-gate * that the raw ioctl senders simply don't want to 21227c478bd9Sstevel@tonic-gate * see any errors returned in this fashion. 21237c478bd9Sstevel@tonic-gate */ 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 21267c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_rwioctl(fjp, unit, (caddr_t)&fdr); 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate if (ucount && flag == B_READ && rval == 0) { 21297c478bd9Sstevel@tonic-gate if (ddi_copyout(fdr.fdr_addr, uaddr, ucount, mode)) { 21307c478bd9Sstevel@tonic-gate rval = EFAULT; 21317c478bd9Sstevel@tonic-gate } 21327c478bd9Sstevel@tonic-gate } 21337c478bd9Sstevel@tonic-gate if (ddi_copyout(fdr.fdr_result, arg_result, sizeof (fdr.fdr_cmd), mode)) 21347c478bd9Sstevel@tonic-gate rval = EFAULT; 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 21377c478bd9Sstevel@tonic-gate if (ucount) 21387c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate return (rval); 21417c478bd9Sstevel@tonic-gate } 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate /* 21447c478bd9Sstevel@tonic-gate * property operation routine. return the number of blocks for the partition 21457c478bd9Sstevel@tonic-gate * in question or forward the request to the property facilities. 21467c478bd9Sstevel@tonic-gate */ 21477c478bd9Sstevel@tonic-gate static int 21487c478bd9Sstevel@tonic-gate fd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 21497c478bd9Sstevel@tonic-gate char *name, caddr_t valuep, int *lengthp) 21507c478bd9Sstevel@tonic-gate { 21517c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 21527c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 21537c478bd9Sstevel@tonic-gate uint64_t nblocks64; 21547c478bd9Sstevel@tonic-gate 21557c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_PROP, 21567c478bd9Sstevel@tonic-gate (CE_CONT, "fd_prop_op: dip %p %s\n", (void *)dip, name)); 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate /* 21597c478bd9Sstevel@tonic-gate * Our dynamic properties are all device specific and size oriented. 21607c478bd9Sstevel@tonic-gate * Requests issued under conditions where size is valid are passed 21617c478bd9Sstevel@tonic-gate * to ddi_prop_op_nblocks with the size information, otherwise the 21627c478bd9Sstevel@tonic-gate * request is passed to ddi_prop_op. 21637c478bd9Sstevel@tonic-gate */ 21647c478bd9Sstevel@tonic-gate if (dev == DDI_DEV_T_ANY) { 21657c478bd9Sstevel@tonic-gate pass: return (ddi_prop_op(dev, dip, prop_op, mod_flags, 21667c478bd9Sstevel@tonic-gate name, valuep, lengthp)); 21677c478bd9Sstevel@tonic-gate } else { 21687c478bd9Sstevel@tonic-gate /* 21697c478bd9Sstevel@tonic-gate * Ignoring return value because success is checked by 21707c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 21717c478bd9Sstevel@tonic-gate */ 21727c478bd9Sstevel@tonic-gate (void) fd_getdrive(dev, &fjp, &fdp); 21737c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 21747c478bd9Sstevel@tonic-gate goto pass; 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate /* get nblocks value */ 21777c478bd9Sstevel@tonic-gate nblocks64 = (ulong_t)fdp->d_part[PARTITION(dev)].p_size; 21787c478bd9Sstevel@tonic-gate 21797c478bd9Sstevel@tonic-gate return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags, 21807c478bd9Sstevel@tonic-gate name, valuep, lengthp, nblocks64)); 21817c478bd9Sstevel@tonic-gate } 21827c478bd9Sstevel@tonic-gate } 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate static void 21857c478bd9Sstevel@tonic-gate fd_media_watch(void *arg) 21867c478bd9Sstevel@tonic-gate { 21877c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 21887c478bd9Sstevel@tonic-gate struct fdisk *fdp; 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate #ifdef DEBUG 21917c478bd9Sstevel@tonic-gate int unit; 21927c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN unit= 21937c478bd9Sstevel@tonic-gate #else 21947c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN (void) 21957c478bd9Sstevel@tonic-gate #endif 21967c478bd9Sstevel@tonic-gate DEBUG_ASSIGN fd_getdrive((dev_t)arg, &fjp, &fdp); 21977c478bd9Sstevel@tonic-gate /* 21987c478bd9Sstevel@tonic-gate * Ignoring return in non DEBUG mode because device exist. 21997c478bd9Sstevel@tonic-gate * Returned unit value is not used. 22007c478bd9Sstevel@tonic-gate */ 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_IOCT, 22037c478bd9Sstevel@tonic-gate (CE_CONT, "fd_media_watch unit %d\n", unit)); 22047c478bd9Sstevel@tonic-gate 22057c478bd9Sstevel@tonic-gate /* 22067c478bd9Sstevel@tonic-gate * fd_get_media_state() cannot be called from this timeout function 22077c478bd9Sstevel@tonic-gate * because the floppy drive has to be selected first, and that could 22087c478bd9Sstevel@tonic-gate * force this function to sleep (while waiting for the select 22097c478bd9Sstevel@tonic-gate * semaphore). 22107c478bd9Sstevel@tonic-gate * Instead, just wakeup up driver. 22117c478bd9Sstevel@tonic-gate */ 22127c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 22137c478bd9Sstevel@tonic-gate cv_broadcast(&fdp->d_statecv); 22147c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 22157c478bd9Sstevel@tonic-gate } 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate enum dkio_state 22187c478bd9Sstevel@tonic-gate fd_get_media_state(struct fcu_obj *fjp, int unit) 22197c478bd9Sstevel@tonic-gate { 22207c478bd9Sstevel@tonic-gate enum dkio_state state; 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 22237c478bd9Sstevel@tonic-gate /* recheck disk only if DSKCHG "high" */ 22247c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_resetchng(fjp, unit); 22257c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 22267c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHGDET) { 22277c478bd9Sstevel@tonic-gate /* 22287c478bd9Sstevel@tonic-gate * again no diskette; not a new change 22297c478bd9Sstevel@tonic-gate */ 22307c478bd9Sstevel@tonic-gate state = DKIO_NONE; 22317c478bd9Sstevel@tonic-gate } else { 22327c478bd9Sstevel@tonic-gate /* 22337c478bd9Sstevel@tonic-gate * a new change; diskette was ejected 22347c478bd9Sstevel@tonic-gate */ 22357c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_CHGDET; 22367c478bd9Sstevel@tonic-gate state = DKIO_EJECTED; 22377c478bd9Sstevel@tonic-gate } 22387c478bd9Sstevel@tonic-gate } else { 22397c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 22407c478bd9Sstevel@tonic-gate state = DKIO_INSERTED; 22417c478bd9Sstevel@tonic-gate } 22427c478bd9Sstevel@tonic-gate } else { 22437c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 22447c478bd9Sstevel@tonic-gate state = DKIO_INSERTED; 22457c478bd9Sstevel@tonic-gate } 22467c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_IOCT, 22477c478bd9Sstevel@tonic-gate (CE_CONT, "fd_get_media_state unit %d: state %x\n", unit, state)); 22487c478bd9Sstevel@tonic-gate return (state); 22497c478bd9Sstevel@tonic-gate } 22507c478bd9Sstevel@tonic-gate 22517c478bd9Sstevel@tonic-gate static int 22527c478bd9Sstevel@tonic-gate fd_check_media(dev_t dev, enum dkio_state state) 22537c478bd9Sstevel@tonic-gate { 22547c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 22557c478bd9Sstevel@tonic-gate struct fdisk *fdp; 22567c478bd9Sstevel@tonic-gate int unit; 22577c478bd9Sstevel@tonic-gate int err; 22587c478bd9Sstevel@tonic-gate 22597c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 22627c478bd9Sstevel@tonic-gate 22637c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 22647c478bd9Sstevel@tonic-gate fdp->d_media_state = fd_get_media_state(fjp, unit); 22657c478bd9Sstevel@tonic-gate fdp->d_media_timeout = drv_usectohz(fd_check_media_time); 22667c478bd9Sstevel@tonic-gate 22677c478bd9Sstevel@tonic-gate while (fdp->d_media_state == state) { 22687c478bd9Sstevel@tonic-gate /* release the controller and drive */ 22697c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 22707c478bd9Sstevel@tonic-gate 22717c478bd9Sstevel@tonic-gate /* turn on timer */ 22727c478bd9Sstevel@tonic-gate fdp->d_media_timeout_id = timeout(fd_media_watch, 22737c478bd9Sstevel@tonic-gate (void *)dev, fdp->d_media_timeout); 22747c478bd9Sstevel@tonic-gate 22757c478bd9Sstevel@tonic-gate if (cv_wait_sig(&fdp->d_statecv, &fjp->fj_lock) == 0) { 22767c478bd9Sstevel@tonic-gate fdp->d_media_timeout = 0; 22777c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 22787c478bd9Sstevel@tonic-gate return (EINTR); 22797c478bd9Sstevel@tonic-gate } 22807c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 22817c478bd9Sstevel@tonic-gate fdp->d_media_state = fd_get_media_state(fjp, unit); 22827c478bd9Sstevel@tonic-gate } 22837c478bd9Sstevel@tonic-gate 22847c478bd9Sstevel@tonic-gate if (fdp->d_media_state == DKIO_INSERTED) { 22857c478bd9Sstevel@tonic-gate err = fdgetlabel(fjp, unit); 22867c478bd9Sstevel@tonic-gate if (err) { 22877c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 22887c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 22897c478bd9Sstevel@tonic-gate return (EIO); 22907c478bd9Sstevel@tonic-gate } 22917c478bd9Sstevel@tonic-gate } 22927c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 22937c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 22947c478bd9Sstevel@tonic-gate return (0); 22957c478bd9Sstevel@tonic-gate } 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate /* 22987c478bd9Sstevel@tonic-gate * fd_get_media_info : 22997c478bd9Sstevel@tonic-gate * Collects medium information for 23007c478bd9Sstevel@tonic-gate * DKIOCGMEDIAINFO ioctl. 23017c478bd9Sstevel@tonic-gate */ 23027c478bd9Sstevel@tonic-gate 23037c478bd9Sstevel@tonic-gate static int 23047c478bd9Sstevel@tonic-gate fd_get_media_info(struct fcu_obj *fjp, caddr_t buf, int flag) 23057c478bd9Sstevel@tonic-gate { 23067c478bd9Sstevel@tonic-gate struct dk_minfo media_info; 23077c478bd9Sstevel@tonic-gate int err = 0; 23087c478bd9Sstevel@tonic-gate 23097c478bd9Sstevel@tonic-gate media_info.dki_media_type = DK_FLOPPY; 23107c478bd9Sstevel@tonic-gate media_info.dki_lbsize = fjp->fj_chars->fdc_sec_size; 23117c478bd9Sstevel@tonic-gate media_info.dki_capacity = fjp->fj_chars->fdc_ncyl * 23127c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack * fjp->fj_chars->fdc_nhead; 23137c478bd9Sstevel@tonic-gate 23147c478bd9Sstevel@tonic-gate if (ddi_copyout(&media_info, buf, sizeof (struct dk_minfo), flag)) 23157c478bd9Sstevel@tonic-gate err = EFAULT; 23167c478bd9Sstevel@tonic-gate return (err); 23177c478bd9Sstevel@tonic-gate } 2318