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 519397407SSherry Moore * Common Development and Distribution License (the "License"). 619397407SSherry 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 /* 2219397407SSherry 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 */ 11919397407SSherry Moore (struct bus_ops *)0, /* bus operations */ 12019397407SSherry Moore NULL, /* power */ 12119397407SSherry 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 */ 16119397407SSherry 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); 518*ca925f54SGarrett D'Amore 519*ca925f54SGarrett D'Amore /* 520*ca925f54SGarrett D'Amore * We want to get suspend/resume events, so that we can 521*ca925f54SGarrett D'Amore * refuse to suspend when pcfs is mounted. 522*ca925f54SGarrett D'Amore */ 523*ca925f54SGarrett D'Amore (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, 524*ca925f54SGarrett D'Amore "pm-hardware-state", "needs-suspend-resume"); 525*ca925f54SGarrett D'Amore 5267c478bd9Sstevel@tonic-gate /* 5277c478bd9Sstevel@tonic-gate * Ignoring return value because, for passed arguments, only 5287c478bd9Sstevel@tonic-gate * DDI_SUCCESS is returned. 5297c478bd9Sstevel@tonic-gate */ 5307c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 5317c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate case DDI_RESUME: 534*ca925f54SGarrett D'Amore /* nothing for us to do */ 5357c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate default: 5387c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate no_attach: 5417c478bd9Sstevel@tonic-gate fjp->fj_drive = NULL; 5427c478bd9Sstevel@tonic-gate fjp->fj_chars = NULL; 5437c478bd9Sstevel@tonic-gate fjp->fj_attr = NULL; 5447c478bd9Sstevel@tonic-gate mutex_destroy(&fjp->fj_lock); 5457c478bd9Sstevel@tonic-gate sema_destroy(&fdp->d_ocsem); 5467c478bd9Sstevel@tonic-gate ddi_soft_state_free(fd_state_head, drive_num); 5477c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, 5487c478bd9Sstevel@tonic-gate (CE_WARN, "fd_attach failed: dip %p unit %d", 5497c478bd9Sstevel@tonic-gate (void *)dip, unit_num)); 5507c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5517c478bd9Sstevel@tonic-gate } 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5557c478bd9Sstevel@tonic-gate static int 5567c478bd9Sstevel@tonic-gate fd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 5597c478bd9Sstevel@tonic-gate struct fdisk *fdp; 5607c478bd9Sstevel@tonic-gate int drive_num; 5617c478bd9Sstevel@tonic-gate int rval = DDI_SUCCESS; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_ATTA, (CE_WARN, "fd_detach dip %p", 5647c478bd9Sstevel@tonic-gate (void *)dip)); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate drive_num = ddi_get_instance(dip); 5677c478bd9Sstevel@tonic-gate if (!(fdp = ddi_get_soft_state(fd_state_head, drive_num))) 5687c478bd9Sstevel@tonic-gate return (rval); 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate switch (cmd) { 5717c478bd9Sstevel@tonic-gate case DDI_DETACH: 5727c478bd9Sstevel@tonic-gate if (fd_unit_is_open(fdp)) { 573*ca925f54SGarrett D'Amore rval = DDI_FAILURE; 5747c478bd9Sstevel@tonic-gate break; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate kstat_delete(fdp->d_iostat); 5777c478bd9Sstevel@tonic-gate fdp->d_iostat = NULL; 5787c478bd9Sstevel@tonic-gate fjp = (struct fcu_obj *)fdp->d_obj; 579*ca925f54SGarrett D'Amore fjp->fj_flags &= ~FUNIT_DRVATCH; 5807c478bd9Sstevel@tonic-gate fjp->fj_data = NULL; 5817c478bd9Sstevel@tonic-gate fjp->fj_drive = NULL; 5827c478bd9Sstevel@tonic-gate fjp->fj_chars = NULL; 5837c478bd9Sstevel@tonic-gate fjp->fj_attr = NULL; 5847c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip); 5857c478bd9Sstevel@tonic-gate mutex_destroy(&fjp->fj_lock); 5867c478bd9Sstevel@tonic-gate sema_destroy(&fdp->d_ocsem); 5877c478bd9Sstevel@tonic-gate ddi_soft_state_free(fd_state_head, drive_num); 5887c478bd9Sstevel@tonic-gate break; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate case DDI_SUSPEND: 591*ca925f54SGarrett D'Amore /* 592*ca925f54SGarrett D'Amore * Bad, bad, bad things will happen if someone 593*ca925f54SGarrett D'Amore * *changes* the disk in the drive while it is mounted 594*ca925f54SGarrett D'Amore * and the system is suspended. We have no way to 595*ca925f54SGarrett D'Amore * detect that. (Undetected filesystem corruption. 596*ca925f54SGarrett D'Amore * Its akin to changing the boot disk while the system 597*ca925f54SGarrett D'Amore * is suspended. Don't do it!) 598*ca925f54SGarrett D'Amore * 599*ca925f54SGarrett D'Amore * So we refuse to suspend if there is a mounted filesystem. 600*ca925f54SGarrett D'Amore * (We guess this by looking for a block open. Character 601*ca925f54SGarrett D'Amore * opens are fine.) This limits some of the usability of 602*ca925f54SGarrett D'Amore * suspend/resume, but it certainly avoids this 603*ca925f54SGarrett D'Amore * potential filesytem corruption from pilot error. 604*ca925f54SGarrett D'Amore * Given the decreasing popularity of floppy media, we 605*ca925f54SGarrett D'Amore * don't see this as much of a limitation. 606*ca925f54SGarrett D'Amore */ 607*ca925f54SGarrett D'Amore if (fdp->d_regopen[OTYP_BLK]) { 608*ca925f54SGarrett D'Amore cmn_err(CE_NOTE, 609*ca925f54SGarrett D'Amore "Unable to suspend while floppy is in use."); 610*ca925f54SGarrett D'Amore rval = DDI_FAILURE; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate break; 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate default: 615*ca925f54SGarrett D'Amore rval = DDI_FAILURE; 6167c478bd9Sstevel@tonic-gate break; 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate return (rval); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate static int 6237c478bd9Sstevel@tonic-gate fd_part_is_open(struct fdisk *fdp, int part) 6247c478bd9Sstevel@tonic-gate { 6257c478bd9Sstevel@tonic-gate int i; 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate for (i = 0; i < (OTYPCNT - 1); i++) 6287c478bd9Sstevel@tonic-gate if (fdp->d_regopen[i] & (1 << part)) 6297c478bd9Sstevel@tonic-gate return (1); 6307c478bd9Sstevel@tonic-gate return (0); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate static int 6347c478bd9Sstevel@tonic-gate fd_unit_is_open(struct fdisk *fdp) 6357c478bd9Sstevel@tonic-gate { 6367c478bd9Sstevel@tonic-gate int i; 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) 6397c478bd9Sstevel@tonic-gate if (fdp->d_lyropen[i]) 6407c478bd9Sstevel@tonic-gate return (1); 6417c478bd9Sstevel@tonic-gate for (i = 0; i < (OTYPCNT - 1); i++) 6427c478bd9Sstevel@tonic-gate if (fdp->d_regopen[i]) 6437c478bd9Sstevel@tonic-gate return (1); 6447c478bd9Sstevel@tonic-gate return (0); 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6487c478bd9Sstevel@tonic-gate static int 6497c478bd9Sstevel@tonic-gate fd_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) 6507c478bd9Sstevel@tonic-gate { 6517c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 6527c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 6537c478bd9Sstevel@tonic-gate struct partition *pp; 6547c478bd9Sstevel@tonic-gate dev_t dev; 6557c478bd9Sstevel@tonic-gate int part, unit; 6567c478bd9Sstevel@tonic-gate int part_is_open; 6577c478bd9Sstevel@tonic-gate int rval; 6587c478bd9Sstevel@tonic-gate uint_t pbit; 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate dev = *devp; 6617c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 6627c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 6637c478bd9Sstevel@tonic-gate return (ENXIO); 6647c478bd9Sstevel@tonic-gate part = PARTITION(dev); 6657c478bd9Sstevel@tonic-gate pbit = 1 << part; 6667c478bd9Sstevel@tonic-gate pp = &fdp->d_part[part]; 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate /* 6697c478bd9Sstevel@tonic-gate * Serialize opens/closes 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate sema_p(&fdp->d_ocsem); 6727c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_OPEN, 6737c478bd9Sstevel@tonic-gate (CE_CONT, "fd_open: fd%d part %d flag %x otype %x\n", DRIVE(dev), 6747c478bd9Sstevel@tonic-gate part, flag, otyp)); 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate /* 6777c478bd9Sstevel@tonic-gate * Check for previous exclusive open, or trying to exclusive open 6787c478bd9Sstevel@tonic-gate * An "exclusive open" on any partition is not guaranteed to 6797c478bd9Sstevel@tonic-gate * protect against opens on another partition that overlaps it. 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) { 6827c478bd9Sstevel@tonic-gate part_is_open = (fdp->d_lyropen[part] != 0); 6837c478bd9Sstevel@tonic-gate } else { 6847c478bd9Sstevel@tonic-gate part_is_open = fd_part_is_open(fdp, part); 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate if ((fdp->d_exclmask & pbit) || ((flag & FEXCL) && part_is_open)) { 6877c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_OPEN, (CE_CONT, 6887c478bd9Sstevel@tonic-gate "fd_open: exclparts %lx openparts %lx lyrcnt %lx pbit %x\n", 6897c478bd9Sstevel@tonic-gate fdp->d_exclmask, fdp->d_regopen[otyp], fdp->d_lyropen[part], 6907c478bd9Sstevel@tonic-gate pbit)); 6917c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 6927c478bd9Sstevel@tonic-gate return (EBUSY); 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate /* 6967c478bd9Sstevel@tonic-gate * Ensure that drive is recalibrated on first open of new diskette. 6977c478bd9Sstevel@tonic-gate */ 6987c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 6997c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit) != 0) { 7007c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_rcseek(fjp, unit, -1, 0)) { 7017c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L2, FDEM_OPEN, 7027c478bd9Sstevel@tonic-gate (CE_NOTE, "fd_open fd%d: not ready", DRIVE(dev))); 7037c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 7047c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7057c478bd9Sstevel@tonic-gate return (ENXIO); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 7087c478bd9Sstevel@tonic-gate } 7097c478bd9Sstevel@tonic-gate if (flag & (FNDELAY | FNONBLOCK)) { 7107c478bd9Sstevel@tonic-gate /* don't attempt access, just return successfully */ 7117c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 7127c478bd9Sstevel@tonic-gate goto out; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /* 7167c478bd9Sstevel@tonic-gate * auto-sense the density/format of the diskette 7177c478bd9Sstevel@tonic-gate */ 7187c478bd9Sstevel@tonic-gate rval = fdgetlabel(fjp, unit); 7197c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 7207c478bd9Sstevel@tonic-gate if (rval) { 7217c478bd9Sstevel@tonic-gate /* didn't find label (couldn't read anything) */ 7227c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L2, FDEM_OPEN, 7237c478bd9Sstevel@tonic-gate (CE_NOTE, "fd%d: drive not ready", DRIVE(dev))); 7247c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7257c478bd9Sstevel@tonic-gate return (EIO); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate /* check partition */ 7287c478bd9Sstevel@tonic-gate if (pp->p_size == 0) { 7297c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7307c478bd9Sstevel@tonic-gate return (ENXIO); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate /* 7337c478bd9Sstevel@tonic-gate * if opening for writing, check write protect on diskette 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate if ((flag & FWRITE) && (fdp->d_obj->fj_flags & FUNIT_WPROT)) { 7367c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7377c478bd9Sstevel@tonic-gate return (EROFS); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate out: 7417c478bd9Sstevel@tonic-gate /* 7427c478bd9Sstevel@tonic-gate * mark open as having succeeded 7437c478bd9Sstevel@tonic-gate */ 7447c478bd9Sstevel@tonic-gate if (flag & FEXCL) 7457c478bd9Sstevel@tonic-gate fdp->d_exclmask |= pbit; 7467c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) 7477c478bd9Sstevel@tonic-gate fdp->d_lyropen[part]++; 7487c478bd9Sstevel@tonic-gate else 7497c478bd9Sstevel@tonic-gate fdp->d_regopen[otyp] |= 1 << part; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 7527c478bd9Sstevel@tonic-gate return (0); 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* 7567c478bd9Sstevel@tonic-gate * fdgetlabel - read the SunOS label off the diskette 7577c478bd9Sstevel@tonic-gate * if it can read a valid label it does so, else it will use a 7587c478bd9Sstevel@tonic-gate * default. If it can`t read the diskette - that is an error. 7597c478bd9Sstevel@tonic-gate * 7607c478bd9Sstevel@tonic-gate * RETURNS: 0 for ok - meaning that it could at least read the device, 7617c478bd9Sstevel@tonic-gate * !0 for error XXX TBD NYD error codes 7627c478bd9Sstevel@tonic-gate */ 7637c478bd9Sstevel@tonic-gate static int 7647c478bd9Sstevel@tonic-gate fdgetlabel(struct fcu_obj *fjp, int unit) 7657c478bd9Sstevel@tonic-gate { 7667c478bd9Sstevel@tonic-gate struct dk_label *label; 7677c478bd9Sstevel@tonic-gate struct fdisk *fdp; 7687c478bd9Sstevel@tonic-gate char *newlabel; 7697c478bd9Sstevel@tonic-gate short *sp; 7707c478bd9Sstevel@tonic-gate short count; 7717c478bd9Sstevel@tonic-gate short xsum; 7727c478bd9Sstevel@tonic-gate int tries, try_this; 7737c478bd9Sstevel@tonic-gate uint_t nexttype; 7747c478bd9Sstevel@tonic-gate int rval; 7757c478bd9Sstevel@tonic-gate short oldlvl; 7767c478bd9Sstevel@tonic-gate int i; 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, 7797c478bd9Sstevel@tonic-gate (CE_CONT, "fdgetlabel fd unit %d\n", unit)); 7807c478bd9Sstevel@tonic-gate fdp = (struct fdisk *)fjp->fj_data; 7817c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_UNLABELED); 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate /* 7847c478bd9Sstevel@tonic-gate * get some space to play with the label 7857c478bd9Sstevel@tonic-gate */ 7867c478bd9Sstevel@tonic-gate label = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 7877c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, (CE_CONT, 7887c478bd9Sstevel@tonic-gate "fdgetlabel fd unit %d kmem_zalloc: ptr = %p, size = %lx\n", 7897c478bd9Sstevel@tonic-gate unit, (void *)label, (size_t)sizeof (struct dk_label))); 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate /* 7927c478bd9Sstevel@tonic-gate * read block 0 (0/0/1) to find the label 7937c478bd9Sstevel@tonic-gate * (disk is potentially not present or unformatted) 7947c478bd9Sstevel@tonic-gate */ 7957c478bd9Sstevel@tonic-gate /* noerrprint since this is a private cmd */ 7967c478bd9Sstevel@tonic-gate oldlvl = fderrlevel; 7977c478bd9Sstevel@tonic-gate fderrlevel = FDEP_LMAX; 7987c478bd9Sstevel@tonic-gate /* 7997c478bd9Sstevel@tonic-gate * try different characteristics (ie densities) 8007c478bd9Sstevel@tonic-gate * 8017c478bd9Sstevel@tonic-gate * if fdp->d_curfdtype is -1 then the current characteristics 8027c478bd9Sstevel@tonic-gate * were set by ioctl and need to try it as well as everything 8037c478bd9Sstevel@tonic-gate * in the table 8047c478bd9Sstevel@tonic-gate */ 8057c478bd9Sstevel@tonic-gate nexttype = fdp->d_deffdtype; 8067c478bd9Sstevel@tonic-gate try_this = 1; /* always try the current characteristics */ 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate for (tries = nfdtypes; tries; tries--) { 8097c478bd9Sstevel@tonic-gate if (try_this) { 8107c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate /* try reading last sector of cyl 1, head 0 */ 8137c478bd9Sstevel@tonic-gate if (!(rval = fjp->fj_ops->fco_rw(fjp, unit, 8147c478bd9Sstevel@tonic-gate FDREAD, 1, 0, fjp->fj_chars->fdc_secptrack, 8157c478bd9Sstevel@tonic-gate (caddr_t)label, 8167c478bd9Sstevel@tonic-gate sizeof (struct dk_label))) && 8177c478bd9Sstevel@tonic-gate /* and last sector plus 1 of cylinder 1 */ 8187c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_rw(fjp, unit, FDREAD, 1, 8197c478bd9Sstevel@tonic-gate 0, fjp->fj_chars->fdc_secptrack + 1, 8207c478bd9Sstevel@tonic-gate (caddr_t)label, 8217c478bd9Sstevel@tonic-gate sizeof (struct dk_label)) && 8227c478bd9Sstevel@tonic-gate /* and label sector on cylinder 0 */ 8237c478bd9Sstevel@tonic-gate !(rval = fjp->fj_ops->fco_rw(fjp, unit, 8247c478bd9Sstevel@tonic-gate FDREAD, 0, 0, 1, (caddr_t)label, 8257c478bd9Sstevel@tonic-gate sizeof (struct dk_label)))) 8267c478bd9Sstevel@tonic-gate break; 8277c478bd9Sstevel@tonic-gate if (rval == ENXIO) 8287c478bd9Sstevel@tonic-gate break; 8297c478bd9Sstevel@tonic-gate } 8307c478bd9Sstevel@tonic-gate /* 8317c478bd9Sstevel@tonic-gate * try the next entry in the characteristics tbl 8327c478bd9Sstevel@tonic-gate */ 8337c478bd9Sstevel@tonic-gate fdp->d_curfdtype = (signed char)nexttype; 8347c478bd9Sstevel@tonic-gate nexttype = (nexttype + 1) % nfdtypes; 8357c478bd9Sstevel@tonic-gate if ((1 << fdp->d_curfdtype) & fdp->d_media) { 8367c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_curfdtype]; 8377c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_curfdtype]; 8387c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_curfdtype], fdp->d_part, 8397c478bd9Sstevel@tonic-gate sizeof (struct partition) * NDKMAP); 8407c478bd9Sstevel@tonic-gate /* 8417c478bd9Sstevel@tonic-gate * check for a double_density diskette 8427c478bd9Sstevel@tonic-gate * in a high_density 5.25" drive 8437c478bd9Sstevel@tonic-gate */ 8447c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_transfer_rate == 250 && 8457c478bd9Sstevel@tonic-gate fjp->fj_rotspd > fjp->fj_attr->fda_rotatespd) { 8467c478bd9Sstevel@tonic-gate /* 8477c478bd9Sstevel@tonic-gate * yes - adjust transfer rate since we don't 8487c478bd9Sstevel@tonic-gate * know if we have a 5.25" dual-speed drive 8497c478bd9Sstevel@tonic-gate */ 8507c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = 360; 8517c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_transfer_rate = 300; 8527c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_medium = 5; 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate if ((2 * fjp->fj_chars->fdc_ncyl) == 8557c478bd9Sstevel@tonic-gate defchar[fdp->d_deffdtype]->fdc_ncyl) { 8567c478bd9Sstevel@tonic-gate /* yes - adjust steps per cylinder */ 8577c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 2; 8587c478bd9Sstevel@tonic-gate } else 8597c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 1; 8607c478bd9Sstevel@tonic-gate try_this = 1; 8617c478bd9Sstevel@tonic-gate } else 8627c478bd9Sstevel@tonic-gate try_this = 0; 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate fderrlevel = oldlvl; /* print errors again */ 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate if (rval) { 8677c478bd9Sstevel@tonic-gate fdp->d_curfdtype = fdp->d_deffdtype; 8687c478bd9Sstevel@tonic-gate goto out; /* couldn't read anything */ 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_GETL, 8727c478bd9Sstevel@tonic-gate (CE_CONT, 8737c478bd9Sstevel@tonic-gate "fdgetlabel fd unit=%d ncyl=%d nsct=%d step=%d rpm=%d intlv=%d\n", 8747c478bd9Sstevel@tonic-gate unit, fjp->fj_chars->fdc_ncyl, fjp->fj_chars->fdc_secptrack, 8757c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps, fjp->fj_attr->fda_rotatespd, 8767c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv)); 8777c478bd9Sstevel@tonic-gate 8787c478bd9Sstevel@tonic-gate /* 8797c478bd9Sstevel@tonic-gate * _something_ was read - look for unixtype label 8807c478bd9Sstevel@tonic-gate */ 8817c478bd9Sstevel@tonic-gate if (label->dkl_magic != DKL_MAGIC || 8827c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_sanity != VTOC_SANE) { 8837c478bd9Sstevel@tonic-gate /* not a label - no magic number */ 8847c478bd9Sstevel@tonic-gate goto nolabel; /* no errors, but no label */ 8857c478bd9Sstevel@tonic-gate } 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate count = sizeof (struct dk_label) / sizeof (short); 8887c478bd9Sstevel@tonic-gate sp = (short *)label; 8897c478bd9Sstevel@tonic-gate xsum = 0; 8907c478bd9Sstevel@tonic-gate while (count--) 8917c478bd9Sstevel@tonic-gate xsum ^= *sp++; /* should add up to 0 */ 8927c478bd9Sstevel@tonic-gate if (xsum) { 8937c478bd9Sstevel@tonic-gate /* not a label - checksum didn't compute */ 8947c478bd9Sstevel@tonic-gate goto nolabel; /* no errors, but no label */ 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate /* 8987c478bd9Sstevel@tonic-gate * the SunOS label overrides current diskette characteristics 8997c478bd9Sstevel@tonic-gate */ 9007c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl = label->dkl_pcyl; 9017c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_nhead = label->dkl_nhead; 9027c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack = (label->dkl_nsect * DEV_BSIZE) / 9037c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size; 9047c478bd9Sstevel@tonic-gate if (defchar[fdp->d_deffdtype]->fdc_ncyl == 2 * fjp->fj_chars->fdc_ncyl) 9057c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 2; 9067c478bd9Sstevel@tonic-gate else 9077c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_steps = 1; 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = label->dkl_rpm; 9107c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv = label->dkl_intrlv; 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate fdp->d_vtoc_version = label->dkl_vtoc.v_version; 9137c478bd9Sstevel@tonic-gate bcopy(label->dkl_vtoc.v_volume, fdp->d_vtoc_volume, LEN_DKL_VVOL); 9147c478bd9Sstevel@tonic-gate bcopy(label->dkl_vtoc.v_asciilabel, 9157c478bd9Sstevel@tonic-gate fdp->d_vtoc_asciilabel, LEN_DKL_ASCII); 9167c478bd9Sstevel@tonic-gate /* 9177c478bd9Sstevel@tonic-gate * logical partitions 9187c478bd9Sstevel@tonic-gate */ 9197c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 9207c478bd9Sstevel@tonic-gate fdp->d_part[i].p_tag = label->dkl_vtoc.v_part[i].p_tag; 9217c478bd9Sstevel@tonic-gate fdp->d_part[i].p_flag = label->dkl_vtoc.v_part[i].p_flag; 9227c478bd9Sstevel@tonic-gate fdp->d_part[i].p_start = label->dkl_vtoc.v_part[i].p_start; 9237c478bd9Sstevel@tonic-gate fdp->d_part[i].p_size = label->dkl_vtoc.v_part[i].p_size; 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate fdp->d_vtoc_timestamp[i] = label->dkl_vtoc.timestamp[i]; 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_LABELOK; 9297c478bd9Sstevel@tonic-gate goto out; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate nolabel: 9327c478bd9Sstevel@tonic-gate /* 9337c478bd9Sstevel@tonic-gate * if not found, fill in label info from default (mark default used) 9347c478bd9Sstevel@tonic-gate */ 9357c478bd9Sstevel@tonic-gate if (fdp->d_media & (1<<FMT_3D)) 9367c478bd9Sstevel@tonic-gate newlabel = deflabel_35; 9377c478bd9Sstevel@tonic-gate else /* if (fdp->d_media & (1<<FMT_5D9)) */ 9387c478bd9Sstevel@tonic-gate newlabel = deflabel_525; 9397c478bd9Sstevel@tonic-gate bzero(fdp->d_vtoc_volume, LEN_DKL_VVOL); 9407c478bd9Sstevel@tonic-gate (void) sprintf(fdp->d_vtoc_asciilabel, newlabel, 9417c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl, fjp->fj_chars->fdc_nhead, 9427c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack); 9437c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_UNLABELED; 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate out: 9467c478bd9Sstevel@tonic-gate kmem_free(label, sizeof (struct dk_label)); 9477c478bd9Sstevel@tonic-gate return (rval); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 9527c478bd9Sstevel@tonic-gate static int 9537c478bd9Sstevel@tonic-gate fd_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 9547c478bd9Sstevel@tonic-gate { 9557c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 9567c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 9577c478bd9Sstevel@tonic-gate int part, part_is_closed; 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate #ifdef DEBUG 9607c478bd9Sstevel@tonic-gate int unit; 9617c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN unit= 9627c478bd9Sstevel@tonic-gate #else 9637c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN (void) 9647c478bd9Sstevel@tonic-gate #endif 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate DEBUG_ASSIGN fd_getdrive(dev, &fjp, &fdp); 9677c478bd9Sstevel@tonic-gate /* 9687c478bd9Sstevel@tonic-gate * Ignoring return in non DEBUG mode because success is checked by 9697c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 9707c478bd9Sstevel@tonic-gate */ 9717c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 9727c478bd9Sstevel@tonic-gate return (ENXIO); 9737c478bd9Sstevel@tonic-gate part = PARTITION(dev); 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate sema_p(&fdp->d_ocsem); 9767c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_CLOS, 9777c478bd9Sstevel@tonic-gate (CE_CONT, "fd_close: fd unit %d part %d otype %x\n", 9787c478bd9Sstevel@tonic-gate unit, part, otyp)); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR) { 9817c478bd9Sstevel@tonic-gate if (fdp->d_lyropen[part]) 9827c478bd9Sstevel@tonic-gate fdp->d_lyropen[part]--; 9837c478bd9Sstevel@tonic-gate part_is_closed = (fdp->d_lyropen[part] == 0); 9847c478bd9Sstevel@tonic-gate } else { 9857c478bd9Sstevel@tonic-gate fdp->d_regopen[otyp] &= ~(1<<part); 9867c478bd9Sstevel@tonic-gate part_is_closed = 1; 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate if (part_is_closed) { 9897c478bd9Sstevel@tonic-gate if (part == 2 && fdp->d_exclmask&(1<<part)) 9907c478bd9Sstevel@tonic-gate fdp->d_exclmask = 0; 9917c478bd9Sstevel@tonic-gate else 9927c478bd9Sstevel@tonic-gate fdp->d_exclmask &= ~(1<<part); 9937c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_CLOS, 9947c478bd9Sstevel@tonic-gate (CE_CONT, 9957c478bd9Sstevel@tonic-gate "fd_close: exclparts %lx openparts %lx lyrcnt %lx\n", 9967c478bd9Sstevel@tonic-gate fdp->d_exclmask, fdp->d_regopen[otyp], 9977c478bd9Sstevel@tonic-gate fdp->d_lyropen[part])); 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate if (fd_unit_is_open(fdp) == 0) 10007c478bd9Sstevel@tonic-gate fdp->d_obj->fj_flags &= ~FUNIT_CHANGED; 10017c478bd9Sstevel@tonic-gate } 10027c478bd9Sstevel@tonic-gate sema_v(&fdp->d_ocsem); 10037c478bd9Sstevel@tonic-gate return (0); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10077c478bd9Sstevel@tonic-gate static int 10087c478bd9Sstevel@tonic-gate fd_read(dev_t dev, struct uio *uio, cred_t *cred_p) 10097c478bd9Sstevel@tonic-gate { 10107c478bd9Sstevel@tonic-gate return (physio(fd_strategy, NULL, dev, B_READ, minphys, uio)); 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate /* ARGSUSED */ 10147c478bd9Sstevel@tonic-gate static int 10157c478bd9Sstevel@tonic-gate fd_write(dev_t dev, struct uio *uio, cred_t *cred_p) 10167c478bd9Sstevel@tonic-gate { 10177c478bd9Sstevel@tonic-gate return (physio(fd_strategy, NULL, dev, B_WRITE, minphys, uio)); 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* 10217c478bd9Sstevel@tonic-gate * fd_strategy 10227c478bd9Sstevel@tonic-gate * checks operation, hangs buf struct off fdcntlr, calls fdstart 10237c478bd9Sstevel@tonic-gate * if not already busy. Note that if we call start, then the operation 10247c478bd9Sstevel@tonic-gate * will already be done on return (start sleeps). 10257c478bd9Sstevel@tonic-gate */ 10267c478bd9Sstevel@tonic-gate static int 10277c478bd9Sstevel@tonic-gate fd_strategy(struct buf *bp) 10287c478bd9Sstevel@tonic-gate { 10297c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 10307c478bd9Sstevel@tonic-gate struct fdisk *fdp; 10317c478bd9Sstevel@tonic-gate struct partition *pp; 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_STRA, 10347c478bd9Sstevel@tonic-gate (CE_CONT, "fd_strategy: bp = 0x%p, dev = 0x%lx\n", 10357c478bd9Sstevel@tonic-gate (void *)bp, bp->b_edev)); 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate (void) fd_getdrive(bp->b_edev, &fjp, &fdp); 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate /* 10407c478bd9Sstevel@tonic-gate * Ignoring return because device exist. 10417c478bd9Sstevel@tonic-gate * Returned unit value is not used. 10427c478bd9Sstevel@tonic-gate */ 10437c478bd9Sstevel@tonic-gate pp = &fdp->d_part[PARTITION(bp->b_edev)]; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_sec_size > NBPSCTR && (bp->b_blkno & 1)) { 10467c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 10477c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: block %ld is not start of sector!", 10487c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), (long)bp->b_blkno)); 10497c478bd9Sstevel@tonic-gate bp->b_error = EINVAL; 10507c478bd9Sstevel@tonic-gate goto bad; 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate if ((bp->b_blkno > pp->p_size)) { 10547c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 10557c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: block %ld is past the end! (nblk=%ld)", 10567c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), (long)bp->b_blkno, pp->p_size)); 10577c478bd9Sstevel@tonic-gate bp->b_error = ENOSPC; 10587c478bd9Sstevel@tonic-gate goto bad; 10597c478bd9Sstevel@tonic-gate } 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate /* if at end of file, skip out now */ 10627c478bd9Sstevel@tonic-gate if (bp->b_blkno == pp->p_size) { 10637c478bd9Sstevel@tonic-gate if ((bp->b_flags & B_READ) == 0) { 10647c478bd9Sstevel@tonic-gate /* a write needs to get an error! */ 10657c478bd9Sstevel@tonic-gate bp->b_error = ENOSPC; 10667c478bd9Sstevel@tonic-gate goto bad; 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; 10697c478bd9Sstevel@tonic-gate biodone(bp); 10707c478bd9Sstevel@tonic-gate return (0); 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate /* if operation not a multiple of sector size, is error! */ 10747c478bd9Sstevel@tonic-gate if (bp->b_bcount % fjp->fj_chars->fdc_sec_size) { 10757c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRA, 10767c478bd9Sstevel@tonic-gate (CE_WARN, "fd%d: count %ld must be a multiple of %d", 10777c478bd9Sstevel@tonic-gate DRIVE(bp->b_edev), bp->b_bcount, 10787c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size)); 10797c478bd9Sstevel@tonic-gate bp->b_error = EINVAL; 10807c478bd9Sstevel@tonic-gate goto bad; 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate /* 10847c478bd9Sstevel@tonic-gate * Put the buf request in the drive's queue, FIFO. 10857c478bd9Sstevel@tonic-gate */ 10867c478bd9Sstevel@tonic-gate bp->av_forw = 0; 10877c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 10887c478bd9Sstevel@tonic-gate if (fdp->d_iostat) 10897c478bd9Sstevel@tonic-gate kstat_waitq_enter(KIOSP); 10907c478bd9Sstevel@tonic-gate if (fdp->d_actf) 10917c478bd9Sstevel@tonic-gate fdp->d_actl->av_forw = bp; 10927c478bd9Sstevel@tonic-gate else 10937c478bd9Sstevel@tonic-gate fdp->d_actf = bp; 10947c478bd9Sstevel@tonic-gate fdp->d_actl = bp; 10957c478bd9Sstevel@tonic-gate if (!(fjp->fj_flags & FUNIT_BUSY)) { 10967c478bd9Sstevel@tonic-gate fdstart(fjp); 10977c478bd9Sstevel@tonic-gate } 10987c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 10997c478bd9Sstevel@tonic-gate return (0); 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate bad: 11027c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; 11037c478bd9Sstevel@tonic-gate bp->b_flags |= B_ERROR; 11047c478bd9Sstevel@tonic-gate biodone(bp); 11057c478bd9Sstevel@tonic-gate return (0); 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate /* 11097c478bd9Sstevel@tonic-gate * fdstart 11107c478bd9Sstevel@tonic-gate * called from fd_strategy() or from fdXXXX() to setup and 11117c478bd9Sstevel@tonic-gate * start operations of read or write only (using buf structs). 11127c478bd9Sstevel@tonic-gate * Because the chip doesn't handle crossing cylinder boundaries on 11137c478bd9Sstevel@tonic-gate * the fly, this takes care of those boundary conditions. Note that 11147c478bd9Sstevel@tonic-gate * it sleeps until the operation is done *within fdstart* - so that 11157c478bd9Sstevel@tonic-gate * when fdstart returns, the operation is already done. 11167c478bd9Sstevel@tonic-gate */ 11177c478bd9Sstevel@tonic-gate static void 11187c478bd9Sstevel@tonic-gate fdstart(struct fcu_obj *fjp) 11197c478bd9Sstevel@tonic-gate { 11207c478bd9Sstevel@tonic-gate struct buf *bp; 11217c478bd9Sstevel@tonic-gate struct fdisk *fdp = (struct fdisk *)fjp->fj_data; 11227c478bd9Sstevel@tonic-gate struct fd_char *chp; 11237c478bd9Sstevel@tonic-gate struct partition *pp; 11247c478bd9Sstevel@tonic-gate uint_t ptend; 11257c478bd9Sstevel@tonic-gate uint_t bincyl; /* (the number of the desired) block in cyl. */ 11267c478bd9Sstevel@tonic-gate uint_t blk, len, tlen; 11277c478bd9Sstevel@tonic-gate uint_t secpcyl; /* number of sectors per cylinder */ 11287c478bd9Sstevel@tonic-gate int cyl, head, sect; 11297c478bd9Sstevel@tonic-gate int sctrshft, unit; 11307c478bd9Sstevel@tonic-gate caddr_t addr; 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&fjp->fj_lock)); 11337c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_BUSY; 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate while ((bp = fdp->d_actf) != NULL) { 11367c478bd9Sstevel@tonic-gate fdp->d_actf = bp->av_forw; 11377c478bd9Sstevel@tonic-gate fdp->d_current = bp; 11387c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 11397c478bd9Sstevel@tonic-gate kstat_waitq_to_runq(KIOSP); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, 11447c478bd9Sstevel@tonic-gate (CE_CONT, "fdstart: bp=0x%p blkno=0x%lx bcount=0x%lx\n", 11457c478bd9Sstevel@tonic-gate (void *)bp, (long)bp->b_blkno, bp->b_bcount)); 11467c478bd9Sstevel@tonic-gate bp->b_flags &= ~B_ERROR; 11477c478bd9Sstevel@tonic-gate bp->b_error = 0; 11487c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount; /* init resid */ 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate ASSERT(DRIVE(bp->b_edev) == ddi_get_instance(fjp->fj_dip)); 11517c478bd9Sstevel@tonic-gate unit = fjp->fj_unit; 11527c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate bp_mapin(bp); /* map in buffers */ 11557c478bd9Sstevel@tonic-gate 11567c478bd9Sstevel@tonic-gate pp = &fdp->d_part[PARTITION(bp->b_edev)]; 11577c478bd9Sstevel@tonic-gate /* starting blk adjusted for the partition */ 11587c478bd9Sstevel@tonic-gate blk = bp->b_blkno + pp->p_start; 11597c478bd9Sstevel@tonic-gate ptend = pp->p_start + pp->p_size; /* end of the partition */ 11607c478bd9Sstevel@tonic-gate 11617c478bd9Sstevel@tonic-gate chp = fjp->fj_chars; 11627c478bd9Sstevel@tonic-gate secpcyl = chp->fdc_nhead * chp->fdc_secptrack; 11637c478bd9Sstevel@tonic-gate switch (chp->fdc_sec_size) { 11647c478bd9Sstevel@tonic-gate /* convert logical block numbers to sector numbers */ 11657c478bd9Sstevel@tonic-gate case 1024: 11667c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT + 1; 11677c478bd9Sstevel@tonic-gate blk >>= 1; 11687c478bd9Sstevel@tonic-gate ptend >>= 1; 11697c478bd9Sstevel@tonic-gate break; 11707c478bd9Sstevel@tonic-gate default: 11717c478bd9Sstevel@tonic-gate case NBPSCTR: 11727c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT; 11737c478bd9Sstevel@tonic-gate break; 11747c478bd9Sstevel@tonic-gate case 256: 11757c478bd9Sstevel@tonic-gate sctrshft = SCTRSHFT - 1; 11767c478bd9Sstevel@tonic-gate blk <<= 1; 11777c478bd9Sstevel@tonic-gate ptend <<= 1; 11787c478bd9Sstevel@tonic-gate break; 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate /* 11827c478bd9Sstevel@tonic-gate * If off the end, limit to actual amount that 11837c478bd9Sstevel@tonic-gate * can be transferred. 11847c478bd9Sstevel@tonic-gate */ 11857c478bd9Sstevel@tonic-gate if ((blk + (bp->b_bcount >> sctrshft)) > ptend) 11867c478bd9Sstevel@tonic-gate /* to end of partition */ 11877c478bd9Sstevel@tonic-gate len = (ptend - blk) << sctrshft; 11887c478bd9Sstevel@tonic-gate else 11897c478bd9Sstevel@tonic-gate len = bp->b_bcount; 11907c478bd9Sstevel@tonic-gate addr = bp->b_un.b_addr; /* data buffer address */ 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate /* 11937c478bd9Sstevel@tonic-gate * now we have the real start blk, addr and len for xfer op 11947c478bd9Sstevel@tonic-gate */ 11957c478bd9Sstevel@tonic-gate while (len != 0) { 11967c478bd9Sstevel@tonic-gate /* start cyl of req */ 11977c478bd9Sstevel@tonic-gate cyl = blk / secpcyl; 11987c478bd9Sstevel@tonic-gate bincyl = blk % secpcyl; 11997c478bd9Sstevel@tonic-gate /* start head of req */ 12007c478bd9Sstevel@tonic-gate head = bincyl / chp->fdc_secptrack; 12017c478bd9Sstevel@tonic-gate /* start sector of req */ 12027c478bd9Sstevel@tonic-gate sect = (bincyl % chp->fdc_secptrack) + 1; 12037c478bd9Sstevel@tonic-gate /* 12047c478bd9Sstevel@tonic-gate * If the desired block and length will go beyond the 12057c478bd9Sstevel@tonic-gate * cylinder end, then limit it to the cylinder end. 12067c478bd9Sstevel@tonic-gate */ 12077c478bd9Sstevel@tonic-gate if (bp->b_flags & B_READ) { 12087c478bd9Sstevel@tonic-gate if (len > ((secpcyl - bincyl) << sctrshft)) 12097c478bd9Sstevel@tonic-gate tlen = (secpcyl - bincyl) << sctrshft; 12107c478bd9Sstevel@tonic-gate else 12117c478bd9Sstevel@tonic-gate tlen = len; 12127c478bd9Sstevel@tonic-gate } else { 12137c478bd9Sstevel@tonic-gate if (len > 12147c478bd9Sstevel@tonic-gate ((chp->fdc_secptrack - sect + 1) << 12157c478bd9Sstevel@tonic-gate sctrshft)) 12167c478bd9Sstevel@tonic-gate tlen = 12177c478bd9Sstevel@tonic-gate (chp->fdc_secptrack - sect + 1) << 12187c478bd9Sstevel@tonic-gate sctrshft; 12197c478bd9Sstevel@tonic-gate else 12207c478bd9Sstevel@tonic-gate tlen = len; 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, (CE_CONT, 12247c478bd9Sstevel@tonic-gate " blk 0x%x addr 0x%p len 0x%x " 12257c478bd9Sstevel@tonic-gate "cyl %d head %d sec %d\n resid 0x%lx, tlen %d\n", 12267c478bd9Sstevel@tonic-gate blk, (void *)addr, len, cyl, head, sect, 12277c478bd9Sstevel@tonic-gate bp->b_resid, tlen)); 12287c478bd9Sstevel@tonic-gate 12297c478bd9Sstevel@tonic-gate /* 12307c478bd9Sstevel@tonic-gate * (try to) do the operation - failure returns an errno 12317c478bd9Sstevel@tonic-gate */ 12327c478bd9Sstevel@tonic-gate bp->b_error = fjp->fj_ops->fco_rw(fjp, unit, 12337c478bd9Sstevel@tonic-gate bp->b_flags & B_READ, cyl, head, sect, addr, tlen); 12347c478bd9Sstevel@tonic-gate if (bp->b_error != 0) { 12357c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_STRT, (CE_WARN, 12367c478bd9Sstevel@tonic-gate "fdstart: bad exec of bp: 0x%p, err=%d", 12377c478bd9Sstevel@tonic-gate (void *)bp, bp->b_error)); 12387c478bd9Sstevel@tonic-gate bp->b_flags |= B_ERROR; 12397c478bd9Sstevel@tonic-gate break; 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate blk += tlen >> sctrshft; 12427c478bd9Sstevel@tonic-gate len -= tlen; 12437c478bd9Sstevel@tonic-gate addr += tlen; 12447c478bd9Sstevel@tonic-gate bp->b_resid -= tlen; 12457c478bd9Sstevel@tonic-gate } 12467c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_STRT, 12477c478bd9Sstevel@tonic-gate (CE_CONT, "fdstart done: b_resid %lu, b_count %lu\n", 12487c478bd9Sstevel@tonic-gate bp->b_resid, bp->b_bcount)); 12497c478bd9Sstevel@tonic-gate if (fdp->d_iostat) { 12507c478bd9Sstevel@tonic-gate if (bp->b_flags & B_READ) { 12517c478bd9Sstevel@tonic-gate KIOSP->reads++; 12527c478bd9Sstevel@tonic-gate KIOSP->nread += (bp->b_bcount - bp->b_resid); 12537c478bd9Sstevel@tonic-gate } else { 12547c478bd9Sstevel@tonic-gate KIOSP->writes++; 12557c478bd9Sstevel@tonic-gate KIOSP->nwritten += (bp->b_bcount - bp->b_resid); 12567c478bd9Sstevel@tonic-gate } 12577c478bd9Sstevel@tonic-gate kstat_runq_exit(KIOSP); 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate bp_mapout(bp); 12607c478bd9Sstevel@tonic-gate biodone(bp); 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 12637c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 12647c478bd9Sstevel@tonic-gate fdp->d_current = 0; 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate fjp->fj_flags ^= FUNIT_BUSY; 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate /* ARGSUSED */ 12707c478bd9Sstevel@tonic-gate static int 12717c478bd9Sstevel@tonic-gate fd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, 12727c478bd9Sstevel@tonic-gate int *rval_p) 12737c478bd9Sstevel@tonic-gate { 12747c478bd9Sstevel@tonic-gate union { 12757c478bd9Sstevel@tonic-gate struct dk_cinfo dki; 12767c478bd9Sstevel@tonic-gate struct dk_geom dkg; 12777c478bd9Sstevel@tonic-gate struct dk_allmap dka; 12787c478bd9Sstevel@tonic-gate struct fd_char fdchar; 12797c478bd9Sstevel@tonic-gate struct fd_drive drvchar; 12807c478bd9Sstevel@tonic-gate int temp; 12817c478bd9Sstevel@tonic-gate } cpy; 12827c478bd9Sstevel@tonic-gate struct vtoc vtoc; 12837c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 12847c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 12857c478bd9Sstevel@tonic-gate struct dk_map *dmp; 12867c478bd9Sstevel@tonic-gate struct dk_label *label; 12877c478bd9Sstevel@tonic-gate int nblks, part, unit; 12887c478bd9Sstevel@tonic-gate int rval = 0; 12897c478bd9Sstevel@tonic-gate enum dkio_state state; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 12927c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 12937c478bd9Sstevel@tonic-gate return (ENXIO); 12947c478bd9Sstevel@tonic-gate 12957c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_IOCT, 12967c478bd9Sstevel@tonic-gate (CE_CONT, "fd_ioctl fd unit %d: cmd %x, arg %lx\n", 12977c478bd9Sstevel@tonic-gate unit, cmd, arg)); 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate switch (cmd) { 13007c478bd9Sstevel@tonic-gate case DKIOCINFO: 13017c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_dkinfo(fjp, &cpy.dki); 13027c478bd9Sstevel@tonic-gate cpy.dki.dki_cnum = FDCTLR(fjp->fj_unit); 13037c478bd9Sstevel@tonic-gate cpy.dki.dki_unit = FDUNIT(fjp->fj_unit); 13047c478bd9Sstevel@tonic-gate cpy.dki.dki_partition = PARTITION(dev); 13057c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dki, (void *)arg, sizeof (cpy.dki), flag)) 13067c478bd9Sstevel@tonic-gate rval = EFAULT; 13077c478bd9Sstevel@tonic-gate break; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate case DKIOCG_PHYGEOM: 13107c478bd9Sstevel@tonic-gate case DKIOCG_VIRTGEOM: 13117c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = fjp->fj_chars->fdc_secptrack; 13127c478bd9Sstevel@tonic-gate goto get_geom; 13137c478bd9Sstevel@tonic-gate case DKIOCGGEOM: 13147c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_LABELOK) 13157c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = (fjp->fj_chars->fdc_secptrack * 13167c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 13177c478bd9Sstevel@tonic-gate else 13187c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nsect = fjp->fj_chars->fdc_secptrack; 13197c478bd9Sstevel@tonic-gate get_geom: 13207c478bd9Sstevel@tonic-gate cpy.dkg.dkg_pcyl = fjp->fj_chars->fdc_ncyl; 13217c478bd9Sstevel@tonic-gate cpy.dkg.dkg_ncyl = fjp->fj_chars->fdc_ncyl; 13227c478bd9Sstevel@tonic-gate cpy.dkg.dkg_nhead = fjp->fj_chars->fdc_nhead; 13237c478bd9Sstevel@tonic-gate cpy.dkg.dkg_intrlv = fjp->fj_attr->fda_intrlv; 13247c478bd9Sstevel@tonic-gate cpy.dkg.dkg_rpm = fjp->fj_attr->fda_rotatespd; 13257c478bd9Sstevel@tonic-gate cpy.dkg.dkg_read_reinstruct = 13267c478bd9Sstevel@tonic-gate (int)(cpy.dkg.dkg_nsect * cpy.dkg.dkg_rpm * 4) / 60000; 13277c478bd9Sstevel@tonic-gate cpy.dkg.dkg_write_reinstruct = cpy.dkg.dkg_read_reinstruct; 13287c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dkg, (void *)arg, sizeof (cpy.dkg), flag)) 13297c478bd9Sstevel@tonic-gate rval = EFAULT; 13307c478bd9Sstevel@tonic-gate break; 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate case DKIOCSGEOM: 13337c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.dkg, 13347c478bd9Sstevel@tonic-gate sizeof (struct dk_geom), flag)) { 13357c478bd9Sstevel@tonic-gate rval = EFAULT; 13367c478bd9Sstevel@tonic-gate break; 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 13397c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_ncyl = cpy.dkg.dkg_ncyl; 13407c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_nhead = cpy.dkg.dkg_nhead; 13417c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack = cpy.dkg.dkg_nsect; 13427c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_intrlv = cpy.dkg.dkg_intrlv; 13437c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = cpy.dkg.dkg_rpm; 13447c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 13457c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 13467c478bd9Sstevel@tonic-gate break; 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate /* 13497c478bd9Sstevel@tonic-gate * return the map of all logical partitions 13507c478bd9Sstevel@tonic-gate */ 13517c478bd9Sstevel@tonic-gate case DKIOCGAPART: 13527c478bd9Sstevel@tonic-gate /* 13537c478bd9Sstevel@tonic-gate * Note the conversion from starting sector number 13547c478bd9Sstevel@tonic-gate * to starting cylinder number. 13557c478bd9Sstevel@tonic-gate * Return error if division results in a remainder. 13567c478bd9Sstevel@tonic-gate */ 13577c478bd9Sstevel@tonic-gate nblks = fjp->fj_chars->fdc_nhead * fjp->fj_chars->fdc_secptrack; 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 13607c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 13617c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 13627c478bd9Sstevel@tonic-gate { 13637c478bd9Sstevel@tonic-gate struct dk_allmap32 dka32; 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 13667c478bd9Sstevel@tonic-gate if ((fdp->d_part[part].p_start % nblks) != 0) 13677c478bd9Sstevel@tonic-gate return (EINVAL); 13687c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_cylno = 13697c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start / nblks; 13707c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_nblk = 13717c478bd9Sstevel@tonic-gate fdp->d_part[part].p_size; 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate if (ddi_copyout(&dka32, (void *)arg, 13757c478bd9Sstevel@tonic-gate sizeof (struct dk_allmap32), flag)) 13767c478bd9Sstevel@tonic-gate rval = EFAULT; 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate break; 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 13817c478bd9Sstevel@tonic-gate 13827c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate dmp = (struct dk_map *)&cpy.dka; 13857c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 13867c478bd9Sstevel@tonic-gate if ((fdp->d_part[part].p_start % nblks) != 0) 13877c478bd9Sstevel@tonic-gate return (EINVAL); 13887c478bd9Sstevel@tonic-gate dmp->dkl_cylno = 13897c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start / nblks; 13907c478bd9Sstevel@tonic-gate dmp->dkl_nblk = fdp->d_part[part].p_size; 13917c478bd9Sstevel@tonic-gate dmp++; 13927c478bd9Sstevel@tonic-gate } 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.dka, (void *)arg, 13957c478bd9Sstevel@tonic-gate sizeof (struct dk_allmap), flag)) 13967c478bd9Sstevel@tonic-gate rval = EFAULT; 13977c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 13987c478bd9Sstevel@tonic-gate break; 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate } 14017c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate break; 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate /* 14067c478bd9Sstevel@tonic-gate * Set the map of all logical partitions 14077c478bd9Sstevel@tonic-gate */ 14087c478bd9Sstevel@tonic-gate case DKIOCSAPART: 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 14117c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 14127c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 14137c478bd9Sstevel@tonic-gate { 14147c478bd9Sstevel@tonic-gate struct dk_allmap32 dka32; 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &dka32, 14177c478bd9Sstevel@tonic-gate sizeof (dka32), flag)) { 14187c478bd9Sstevel@tonic-gate rval = EFAULT; 14197c478bd9Sstevel@tonic-gate break; 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 14227c478bd9Sstevel@tonic-gate cpy.dka.dka_map[part].dkl_cylno = 14237c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_cylno; 14247c478bd9Sstevel@tonic-gate cpy.dka.dka_map[part].dkl_nblk = 14257c478bd9Sstevel@tonic-gate dka32.dka_map[part].dkl_nblk; 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate break; 14287c478bd9Sstevel@tonic-gate } 14297c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14327c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.dka, sizeof (cpy.dka), flag)) 14337c478bd9Sstevel@tonic-gate rval = EFAULT; 14347c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate break; 14377c478bd9Sstevel@tonic-gate } 14387c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14397c478bd9Sstevel@tonic-gate 14407c478bd9Sstevel@tonic-gate if (rval != 0) 14417c478bd9Sstevel@tonic-gate break; 14427c478bd9Sstevel@tonic-gate 14437c478bd9Sstevel@tonic-gate dmp = (struct dk_map *)&cpy.dka; 14447c478bd9Sstevel@tonic-gate nblks = fjp->fj_chars->fdc_nhead * 14457c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack; 14467c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 14477c478bd9Sstevel@tonic-gate /* 14487c478bd9Sstevel@tonic-gate * Note the conversion from starting cylinder number 14497c478bd9Sstevel@tonic-gate * to starting sector number. 14507c478bd9Sstevel@tonic-gate */ 14517c478bd9Sstevel@tonic-gate for (part = 0; part < NDKMAP; part++) { 14527c478bd9Sstevel@tonic-gate fdp->d_part[part].p_start = dmp->dkl_cylno * 14537c478bd9Sstevel@tonic-gate nblks; 14547c478bd9Sstevel@tonic-gate fdp->d_part[part].p_size = dmp->dkl_nblk; 14557c478bd9Sstevel@tonic-gate dmp++; 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 14587c478bd9Sstevel@tonic-gate 14597c478bd9Sstevel@tonic-gate break; 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate case DKIOCGVTOC: 14627c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate /* 14657c478bd9Sstevel@tonic-gate * Exit if the diskette has no label. 14667c478bd9Sstevel@tonic-gate * Also, get the label to make sure the correct one is 14677c478bd9Sstevel@tonic-gate * being used since the diskette may have changed 14687c478bd9Sstevel@tonic-gate */ 14697c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 14707c478bd9Sstevel@tonic-gate rval = fdgetlabel(fjp, unit); 14717c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 14727c478bd9Sstevel@tonic-gate if (rval) { 14737c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 14747c478bd9Sstevel@tonic-gate rval = EINVAL; 14757c478bd9Sstevel@tonic-gate break; 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate fd_build_user_vtoc(fjp, fdp, &vtoc); 14797c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 14827c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 14837c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 14847c478bd9Sstevel@tonic-gate { 14857c478bd9Sstevel@tonic-gate struct vtoc32 vtoc32; 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate vtoctovtoc32(vtoc, vtoc32); 14887c478bd9Sstevel@tonic-gate 14897c478bd9Sstevel@tonic-gate if (ddi_copyout(&vtoc32, (void *)arg, 14907c478bd9Sstevel@tonic-gate sizeof (vtoc32), flag)) 14917c478bd9Sstevel@tonic-gate rval = EFAULT; 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate break; 14947c478bd9Sstevel@tonic-gate } 14957c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 14987c478bd9Sstevel@tonic-gate if (ddi_copyout(&vtoc, (void *)arg, 14997c478bd9Sstevel@tonic-gate sizeof (vtoc), flag)) 15007c478bd9Sstevel@tonic-gate rval = EFAULT; 15017c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 15027c478bd9Sstevel@tonic-gate break; 15037c478bd9Sstevel@tonic-gate } 15047c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate break; 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate case DKIOCSVTOC: 15097c478bd9Sstevel@tonic-gate 15107c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 15117c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 15127c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 15137c478bd9Sstevel@tonic-gate { 15147c478bd9Sstevel@tonic-gate struct vtoc32 vtoc32; 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &vtoc32, 15177c478bd9Sstevel@tonic-gate sizeof (vtoc32), flag)) { 15187c478bd9Sstevel@tonic-gate rval = EFAULT; 15197c478bd9Sstevel@tonic-gate break; 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate 15227c478bd9Sstevel@tonic-gate vtoc32tovtoc(vtoc32, vtoc); 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate break; 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 15297c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &vtoc, sizeof (vtoc), flag)) 15307c478bd9Sstevel@tonic-gate rval = EFAULT; 15317c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 15327c478bd9Sstevel@tonic-gate break; 15337c478bd9Sstevel@tonic-gate } 15347c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 15357c478bd9Sstevel@tonic-gate 15367c478bd9Sstevel@tonic-gate if (rval != 0) 15377c478bd9Sstevel@tonic-gate break; 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate label = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate if ((rval = fd_build_label_vtoc(fjp, fdp, &vtoc, label)) == 0) { 15457c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 15467c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_rw(fjp, unit, FDWRITE, 15477c478bd9Sstevel@tonic-gate 0, 0, 1, (caddr_t)label, sizeof (struct dk_label)); 15487c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 15517c478bd9Sstevel@tonic-gate kmem_free(label, sizeof (struct dk_label)); 15527c478bd9Sstevel@tonic-gate break; 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate case DKIOCSTATE: 15557c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_IOCT, 15567c478bd9Sstevel@tonic-gate (CE_CONT, "fd_ioctl fd unit %d: DKIOCSTATE\n", unit)); 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &state, sizeof (int), flag)) { 15597c478bd9Sstevel@tonic-gate rval = EFAULT; 15607c478bd9Sstevel@tonic-gate break; 15617c478bd9Sstevel@tonic-gate } 15627c478bd9Sstevel@tonic-gate 15637c478bd9Sstevel@tonic-gate rval = fd_check_media(dev, state); 15647c478bd9Sstevel@tonic-gate 15657c478bd9Sstevel@tonic-gate if (ddi_copyout(&fdp->d_media_state, (void *)arg, 15667c478bd9Sstevel@tonic-gate sizeof (int), flag)) 15677c478bd9Sstevel@tonic-gate rval = EFAULT; 15687c478bd9Sstevel@tonic-gate break; 15697c478bd9Sstevel@tonic-gate 15707c478bd9Sstevel@tonic-gate case FDIOGCHAR: 15717c478bd9Sstevel@tonic-gate if (ddi_copyout(fjp->fj_chars, (void *)arg, 15727c478bd9Sstevel@tonic-gate sizeof (struct fd_char), flag)) 15737c478bd9Sstevel@tonic-gate rval = EFAULT; 15747c478bd9Sstevel@tonic-gate break; 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate case FDIOSCHAR: 15777c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.fdchar, 15787c478bd9Sstevel@tonic-gate sizeof (struct fd_char), flag)) { 15797c478bd9Sstevel@tonic-gate rval = EFAULT; 15807c478bd9Sstevel@tonic-gate break; 15817c478bd9Sstevel@tonic-gate } 15827c478bd9Sstevel@tonic-gate switch (cpy.fdchar.fdc_transfer_rate) { 15837c478bd9Sstevel@tonic-gate case 417: 15847c478bd9Sstevel@tonic-gate if ((fdp->d_media & (1 << FMT_3M)) == 0) { 15857c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 15867c478bd9Sstevel@tonic-gate "fdioschar:Medium density not supported\n"); 15877c478bd9Sstevel@tonic-gate rval = EINVAL; 15887c478bd9Sstevel@tonic-gate break; 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 15917c478bd9Sstevel@tonic-gate fjp->fj_attr->fda_rotatespd = 360; 15927c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 15937c478bd9Sstevel@tonic-gate /* cpy.fdchar.fdc_transfer_rate = 500; */ 15947c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15957c478bd9Sstevel@tonic-gate case 1000: 15967c478bd9Sstevel@tonic-gate case 500: 15977c478bd9Sstevel@tonic-gate case 300: 15987c478bd9Sstevel@tonic-gate case 250: 15997c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 16007c478bd9Sstevel@tonic-gate *(fjp->fj_chars) = cpy.fdchar; 16017c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 16027c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 16037c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate break; 16067c478bd9Sstevel@tonic-gate 16077c478bd9Sstevel@tonic-gate default: 16087c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 16097c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: FDIOSCHAR odd " 16107c478bd9Sstevel@tonic-gate "xfer rate %dkbs", 16117c478bd9Sstevel@tonic-gate unit, cpy.fdchar.fdc_transfer_rate)); 16127c478bd9Sstevel@tonic-gate rval = EINVAL; 16137c478bd9Sstevel@tonic-gate break; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate break; 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate /* 16187c478bd9Sstevel@tonic-gate * set all characteristics and geometry to the defaults 16197c478bd9Sstevel@tonic-gate */ 16207c478bd9Sstevel@tonic-gate case FDDEFGEOCHAR: 16217c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 16227c478bd9Sstevel@tonic-gate fdp->d_curfdtype = fdp->d_deffdtype; 16237c478bd9Sstevel@tonic-gate *fjp->fj_chars = *defchar[fdp->d_curfdtype]; 16247c478bd9Sstevel@tonic-gate *fjp->fj_attr = fdtypes[fdp->d_curfdtype]; 16257c478bd9Sstevel@tonic-gate bcopy(fdparts[fdp->d_curfdtype], 16267c478bd9Sstevel@tonic-gate fdp->d_part, sizeof (struct partition) * NDKMAP); 16277c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 16287c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 16297c478bd9Sstevel@tonic-gate break; 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate case FDEJECT: /* eject disk */ 16327c478bd9Sstevel@tonic-gate case DKIOCEJECT: 16337c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 16347c478bd9Sstevel@tonic-gate rval = ENOSYS; 16357c478bd9Sstevel@tonic-gate break; 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate case FDGETCHANGE: /* disk changed */ 16387c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.temp, sizeof (int), flag)) { 16397c478bd9Sstevel@tonic-gate rval = EFAULT; 16407c478bd9Sstevel@tonic-gate break; 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 16437c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 16447c478bd9Sstevel@tonic-gate 16457c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHANGED) 16467c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_HISTORY; 16477c478bd9Sstevel@tonic-gate else 16487c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_HISTORY; 16497c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHANGED; 16507c478bd9Sstevel@tonic-gate 16517c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 16527c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_DETECTED; 16537c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_resetchng(fjp, unit); 16547c478bd9Sstevel@tonic-gate /* 16557c478bd9Sstevel@tonic-gate * check diskette again only if it was removed 16567c478bd9Sstevel@tonic-gate */ 16577c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 16587c478bd9Sstevel@tonic-gate /* 16597c478bd9Sstevel@tonic-gate * no diskette is present 16607c478bd9Sstevel@tonic-gate */ 16617c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_CURRENT; 16627c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHGDET) 16637c478bd9Sstevel@tonic-gate /* 16647c478bd9Sstevel@tonic-gate * again no diskette; not a new change 16657c478bd9Sstevel@tonic-gate */ 16667c478bd9Sstevel@tonic-gate cpy.temp ^= FDGC_DETECTED; 16677c478bd9Sstevel@tonic-gate else 16687c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_CHGDET; 16697c478bd9Sstevel@tonic-gate } else { 16707c478bd9Sstevel@tonic-gate /* 16717c478bd9Sstevel@tonic-gate * a new diskette is present 16727c478bd9Sstevel@tonic-gate */ 16737c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_CURRENT; 16747c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 16757c478bd9Sstevel@tonic-gate } 16767c478bd9Sstevel@tonic-gate } else { 16777c478bd9Sstevel@tonic-gate cpy.temp &= ~(FDGC_DETECTED | FDGC_CURRENT); 16787c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 16797c478bd9Sstevel@tonic-gate } 16807c478bd9Sstevel@tonic-gate /* 16817c478bd9Sstevel@tonic-gate * also get state of write protection 16827c478bd9Sstevel@tonic-gate */ 16837c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_WPROT) { 16847c478bd9Sstevel@tonic-gate cpy.temp |= FDGC_CURWPROT; 16857c478bd9Sstevel@tonic-gate } else { 16867c478bd9Sstevel@tonic-gate cpy.temp &= ~FDGC_CURWPROT; 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 16897c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate if (ddi_copyout(&cpy.temp, (void *)arg, sizeof (int), flag)) 16927c478bd9Sstevel@tonic-gate rval = EFAULT; 16937c478bd9Sstevel@tonic-gate break; 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate case FDGETDRIVECHAR: 16967c478bd9Sstevel@tonic-gate if (ddi_copyout(fjp->fj_drive, (void *)arg, 16977c478bd9Sstevel@tonic-gate sizeof (struct fd_drive), flag)) 16987c478bd9Sstevel@tonic-gate rval = EFAULT; 16997c478bd9Sstevel@tonic-gate break; 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate case FDSETDRIVECHAR: 17027c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &cpy.drvchar, 17037c478bd9Sstevel@tonic-gate sizeof (struct fd_drive), flag)) { 17047c478bd9Sstevel@tonic-gate rval = EFAULT; 17057c478bd9Sstevel@tonic-gate break; 17067c478bd9Sstevel@tonic-gate } 17077c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 17087c478bd9Sstevel@tonic-gate *(fjp->fj_drive) = cpy.drvchar; 17097c478bd9Sstevel@tonic-gate fdp->d_curfdtype = -1; 17107c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHAROK; 17117c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 17127c478bd9Sstevel@tonic-gate break; 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate case DKIOCREMOVABLE: { 17157c478bd9Sstevel@tonic-gate int i = 1; 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate /* no brainer: floppies are always removable */ 17187c478bd9Sstevel@tonic-gate if (ddi_copyout(&i, (void *)arg, sizeof (int), flag)) { 17197c478bd9Sstevel@tonic-gate rval = EFAULT; 17207c478bd9Sstevel@tonic-gate } 17217c478bd9Sstevel@tonic-gate break; 17227c478bd9Sstevel@tonic-gate } 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate case DKIOCGMEDIAINFO: 17257c478bd9Sstevel@tonic-gate rval = fd_get_media_info(fjp, (caddr_t)arg, flag); 17267c478bd9Sstevel@tonic-gate break; 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate case FDIOCMD: 17297c478bd9Sstevel@tonic-gate { 17307c478bd9Sstevel@tonic-gate struct fd_cmd fc; 17317c478bd9Sstevel@tonic-gate int cyl, head, spc, spt; 17327c478bd9Sstevel@tonic-gate 17337c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 17347c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(flag & FMODELS)) { 17357c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 17367c478bd9Sstevel@tonic-gate { 17377c478bd9Sstevel@tonic-gate struct fd_cmd32 fc32; 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &fc32, 17407c478bd9Sstevel@tonic-gate sizeof (fc32), flag)) { 17417c478bd9Sstevel@tonic-gate rval = EFAULT; 17427c478bd9Sstevel@tonic-gate break; 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate 17457c478bd9Sstevel@tonic-gate fc.fdc_cmd = fc32.fdc_cmd; 17467c478bd9Sstevel@tonic-gate fc.fdc_flags = fc32.fdc_flags; 17477c478bd9Sstevel@tonic-gate fc.fdc_blkno = fc32.fdc_blkno; 17487c478bd9Sstevel@tonic-gate fc.fdc_secnt = fc32.fdc_secnt; 17497c478bd9Sstevel@tonic-gate fc.fdc_bufaddr = (caddr_t)(uintptr_t)fc32.fdc_bufaddr; 17507c478bd9Sstevel@tonic-gate fc.fdc_buflen = fc32.fdc_buflen; 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate break; 17537c478bd9Sstevel@tonic-gate } 17547c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &fc, sizeof (fc), flag)) { 17597c478bd9Sstevel@tonic-gate rval = EFAULT; 17607c478bd9Sstevel@tonic-gate break; 17617c478bd9Sstevel@tonic-gate } 17627c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 17637c478bd9Sstevel@tonic-gate break; 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate if (rval != 0) 17687c478bd9Sstevel@tonic-gate break; 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate if (fc.fdc_cmd == FDCMD_READ || fc.fdc_cmd == FDCMD_WRITE) { 17717c478bd9Sstevel@tonic-gate auto struct iovec aiov; 17727c478bd9Sstevel@tonic-gate auto struct uio auio; 17737c478bd9Sstevel@tonic-gate struct uio *uio = &auio; 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate spc = (fc.fdc_cmd == FDCMD_READ)? B_READ: B_WRITE; 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate bzero(&auio, sizeof (struct uio)); 17787c478bd9Sstevel@tonic-gate bzero(&aiov, sizeof (struct iovec)); 17797c478bd9Sstevel@tonic-gate aiov.iov_base = fc.fdc_bufaddr; 17807c478bd9Sstevel@tonic-gate aiov.iov_len = (uint_t)fc.fdc_secnt * 17817c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size; 17827c478bd9Sstevel@tonic-gate uio->uio_iov = &aiov; 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate uio->uio_iovcnt = 1; 17857c478bd9Sstevel@tonic-gate uio->uio_resid = aiov.iov_len; 17867c478bd9Sstevel@tonic-gate uio->uio_segflg = UIO_USERSPACE; 17877c478bd9Sstevel@tonic-gate 17887c478bd9Sstevel@tonic-gate rval = physio(fd_strategy, (struct buf *)0, dev, 17897c478bd9Sstevel@tonic-gate spc, minphys, uio); 17907c478bd9Sstevel@tonic-gate break; 17917c478bd9Sstevel@tonic-gate } else if (fc.fdc_cmd == FDCMD_FORMAT_TRACK) { 17927c478bd9Sstevel@tonic-gate spt = fjp->fj_chars->fdc_secptrack; /* sec/trk */ 17937c478bd9Sstevel@tonic-gate spc = fjp->fj_chars->fdc_nhead * spt; /* sec/cyl */ 17947c478bd9Sstevel@tonic-gate cyl = fc.fdc_blkno / spc; 17957c478bd9Sstevel@tonic-gate head = (fc.fdc_blkno % spc) / spt; 17967c478bd9Sstevel@tonic-gate if ((cyl | head) == 0) 17977c478bd9Sstevel@tonic-gate fjp->fj_flags &= 17987c478bd9Sstevel@tonic-gate ~(FUNIT_LABELOK | FUNIT_UNLABELED); 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_FORM, 18017c478bd9Sstevel@tonic-gate (CE_CONT, "fd_format cyl %d, hd %d\n", cyl, head)); 18027c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 18037c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_format(fjp, unit, cyl, head, 18047c478bd9Sstevel@tonic-gate (int)fc.fdc_flags); 18057c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 18067c478bd9Sstevel@tonic-gate 18077c478bd9Sstevel@tonic-gate break; 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 18107c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: FDIOCSCMD not yet complete", 18117c478bd9Sstevel@tonic-gate unit)); 18127c478bd9Sstevel@tonic-gate rval = EINVAL; 18137c478bd9Sstevel@tonic-gate break; 18147c478bd9Sstevel@tonic-gate } 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate case FDRAW: 18177c478bd9Sstevel@tonic-gate rval = fd_rawioctl(fjp, unit, (caddr_t)arg, flag); 18187c478bd9Sstevel@tonic-gate break; 18197c478bd9Sstevel@tonic-gate 18207c478bd9Sstevel@tonic-gate default: 18217c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L4, FDEM_IOCT, 18227c478bd9Sstevel@tonic-gate (CE_WARN, "fd_ioctl fd unit %d: invalid ioctl 0x%x", 18237c478bd9Sstevel@tonic-gate unit, cmd)); 18247c478bd9Sstevel@tonic-gate rval = ENOTTY; 18257c478bd9Sstevel@tonic-gate break; 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate return (rval); 18287c478bd9Sstevel@tonic-gate } 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate static void 18317c478bd9Sstevel@tonic-gate fd_build_user_vtoc(struct fcu_obj *fjp, struct fdisk *fdp, struct vtoc *vtocp) 18327c478bd9Sstevel@tonic-gate { 18337c478bd9Sstevel@tonic-gate struct partition *vpart; 18347c478bd9Sstevel@tonic-gate int i; 18357c478bd9Sstevel@tonic-gate int xblk; 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate /* 18387c478bd9Sstevel@tonic-gate * Return vtoc structure fields in the provided VTOC area, addressed 18397c478bd9Sstevel@tonic-gate * by *vtocp. 18407c478bd9Sstevel@tonic-gate * 18417c478bd9Sstevel@tonic-gate */ 18427c478bd9Sstevel@tonic-gate bzero(vtocp, sizeof (struct vtoc)); 18437c478bd9Sstevel@tonic-gate 18447c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_bootinfo, 18457c478bd9Sstevel@tonic-gate vtocp->v_bootinfo, sizeof (vtocp->v_bootinfo)); 18467c478bd9Sstevel@tonic-gate 18477c478bd9Sstevel@tonic-gate vtocp->v_sanity = VTOC_SANE; 18487c478bd9Sstevel@tonic-gate vtocp->v_version = fdp->d_vtoc_version; 18497c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_volume, vtocp->v_volume, LEN_DKL_VVOL); 18507c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_LABELOK) { 18517c478bd9Sstevel@tonic-gate vtocp->v_sectorsz = DEV_BSIZE; 18527c478bd9Sstevel@tonic-gate xblk = 1; 18537c478bd9Sstevel@tonic-gate } else { 18547c478bd9Sstevel@tonic-gate vtocp->v_sectorsz = fjp->fj_chars->fdc_sec_size; 18557c478bd9Sstevel@tonic-gate xblk = vtocp->v_sectorsz / DEV_BSIZE; 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate vtocp->v_nparts = 3; /* <= NDKMAP; */ 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate /* 18607c478bd9Sstevel@tonic-gate * Copy partitioning information. 18617c478bd9Sstevel@tonic-gate */ 18627c478bd9Sstevel@tonic-gate bcopy(fdp->d_part, vtocp->v_part, sizeof (struct partition) * NDKMAP); 18637c478bd9Sstevel@tonic-gate for (i = NDKMAP, vpart = vtocp->v_part; i && (xblk > 1); i--, vpart++) { 18647c478bd9Sstevel@tonic-gate /* correct partition info if sector size > 512 bytes */ 18657c478bd9Sstevel@tonic-gate vpart->p_start /= xblk; 18667c478bd9Sstevel@tonic-gate vpart->p_size /= xblk; 18677c478bd9Sstevel@tonic-gate } 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_timestamp, 18707c478bd9Sstevel@tonic-gate vtocp->timestamp, sizeof (fdp->d_vtoc_timestamp)); 18717c478bd9Sstevel@tonic-gate bcopy(fdp->d_vtoc_asciilabel, vtocp->v_asciilabel, LEN_DKL_ASCII); 18727c478bd9Sstevel@tonic-gate } 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate static int 18767c478bd9Sstevel@tonic-gate fd_build_label_vtoc(struct fcu_obj *fjp, struct fdisk *fdp, struct vtoc *vtocp, 18777c478bd9Sstevel@tonic-gate struct dk_label *labelp) 18787c478bd9Sstevel@tonic-gate { 18797c478bd9Sstevel@tonic-gate struct partition *vpart; 18807c478bd9Sstevel@tonic-gate int i; 18817c478bd9Sstevel@tonic-gate int nblks; 18827c478bd9Sstevel@tonic-gate int ncyl; 18837c478bd9Sstevel@tonic-gate ushort_t sum, *sp; 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate /* 18877c478bd9Sstevel@tonic-gate * Sanity-check the vtoc 18887c478bd9Sstevel@tonic-gate */ 18897c478bd9Sstevel@tonic-gate if (vtocp->v_sanity != VTOC_SANE || 18907c478bd9Sstevel@tonic-gate vtocp->v_nparts > NDKMAP || vtocp->v_nparts <= 0) { 18917c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L3, FDEM_IOCT, 18927c478bd9Sstevel@tonic-gate (CE_WARN, "fd_build_label: sanity check on vtoc failed")); 18937c478bd9Sstevel@tonic-gate return (EINVAL); 18947c478bd9Sstevel@tonic-gate } 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate /* 18977c478bd9Sstevel@tonic-gate * before copying the vtoc, the partition information in it should be 18987c478bd9Sstevel@tonic-gate * checked against the information the driver already has on the 18997c478bd9Sstevel@tonic-gate * diskette. 19007c478bd9Sstevel@tonic-gate */ 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate nblks = (fjp->fj_chars->fdc_nhead * fjp->fj_chars->fdc_secptrack * 19037c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 19047c478bd9Sstevel@tonic-gate if (nblks == 0 || fjp->fj_chars->fdc_ncyl == 0) 19057c478bd9Sstevel@tonic-gate return (EFAULT); 19067c478bd9Sstevel@tonic-gate vpart = vtocp->v_part; 19077c478bd9Sstevel@tonic-gate 19087c478bd9Sstevel@tonic-gate /* 19097c478bd9Sstevel@tonic-gate * Check the partition information in the vtoc. The starting sectors 19107c478bd9Sstevel@tonic-gate * must lie along cylinder boundaries. (NDKMAP entries are checked 19117c478bd9Sstevel@tonic-gate * to ensure that the unused entries are set to 0 if vtoc->v_nparts 19127c478bd9Sstevel@tonic-gate * is less than NDKMAP) 19137c478bd9Sstevel@tonic-gate */ 19147c478bd9Sstevel@tonic-gate for (i = NDKMAP; i; i--) { 19157c478bd9Sstevel@tonic-gate if ((vpart->p_start % nblks) != 0) { 19167c478bd9Sstevel@tonic-gate return (EINVAL); 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate ncyl = vpart->p_start / nblks; 19197c478bd9Sstevel@tonic-gate ncyl += vpart->p_size / nblks; 19207c478bd9Sstevel@tonic-gate if ((vpart->p_size % nblks) != 0) 19217c478bd9Sstevel@tonic-gate ncyl++; 19227c478bd9Sstevel@tonic-gate if (ncyl > (long)fjp->fj_chars->fdc_ncyl) { 19237c478bd9Sstevel@tonic-gate return (EINVAL); 19247c478bd9Sstevel@tonic-gate } 19257c478bd9Sstevel@tonic-gate vpart++; 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate bcopy(vtocp->v_bootinfo, fdp->d_vtoc_bootinfo, 19307c478bd9Sstevel@tonic-gate sizeof (vtocp->v_bootinfo)); 19317c478bd9Sstevel@tonic-gate fdp->d_vtoc_version = vtocp->v_version; 19327c478bd9Sstevel@tonic-gate bcopy(vtocp->v_volume, fdp->d_vtoc_volume, LEN_DKL_VVOL); 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate /* 19357c478bd9Sstevel@tonic-gate * Copy partitioning information. 19367c478bd9Sstevel@tonic-gate */ 19377c478bd9Sstevel@tonic-gate bcopy(vtocp->v_part, fdp->d_part, sizeof (struct partition) * NDKMAP); 19387c478bd9Sstevel@tonic-gate bcopy(vtocp->timestamp, fdp->d_vtoc_timestamp, 19397c478bd9Sstevel@tonic-gate sizeof (fdp->d_vtoc_timestamp)); 19407c478bd9Sstevel@tonic-gate bcopy(vtocp->v_asciilabel, fdp->d_vtoc_asciilabel, LEN_DKL_ASCII); 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* 19437c478bd9Sstevel@tonic-gate * construct the diskette label in supplied buffer 19447c478bd9Sstevel@tonic-gate */ 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate /* Put appropriate vtoc structure fields into the disk label */ 19477c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[0] = (uint32_t)vtocp->v_bootinfo[0]; 19487c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[1] = (uint32_t)vtocp->v_bootinfo[1]; 19497c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_bootinfo[2] = (uint32_t)vtocp->v_bootinfo[2]; 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_sanity = vtocp->v_sanity; 19527c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_version = vtocp->v_version; 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate bcopy(vtocp->v_volume, labelp->dkl_vtoc.v_volume, LEN_DKL_VVOL); 19557c478bd9Sstevel@tonic-gate 19567c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_nparts = vtocp->v_nparts; 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate bcopy(vtocp->v_reserved, labelp->dkl_vtoc.v_reserved, 19597c478bd9Sstevel@tonic-gate sizeof (labelp->dkl_vtoc.v_reserved)); 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate for (i = 0; i < (int)vtocp->v_nparts; i++) { 19627c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_tag = vtocp->v_part[i].p_tag; 19637c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_flag = vtocp->v_part[i].p_flag; 19647c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_start = vtocp->v_part[i].p_start; 19657c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_part[i].p_size = vtocp->v_part[i].p_size; 19667c478bd9Sstevel@tonic-gate } 19677c478bd9Sstevel@tonic-gate 19687c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 19697c478bd9Sstevel@tonic-gate labelp->dkl_vtoc.v_timestamp[i] = vtocp->timestamp[i]; 19707c478bd9Sstevel@tonic-gate } 19717c478bd9Sstevel@tonic-gate bcopy(vtocp->v_asciilabel, labelp->dkl_asciilabel, LEN_DKL_ASCII); 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate 19747c478bd9Sstevel@tonic-gate labelp->dkl_pcyl = fjp->fj_chars->fdc_ncyl; 19757c478bd9Sstevel@tonic-gate labelp->dkl_ncyl = fjp->fj_chars->fdc_ncyl; 19767c478bd9Sstevel@tonic-gate labelp->dkl_nhead = fjp->fj_chars->fdc_nhead; 19777c478bd9Sstevel@tonic-gate /* 19787c478bd9Sstevel@tonic-gate * The fdc_secptrack field of the fd_char structure is the number 19797c478bd9Sstevel@tonic-gate * of sectors per track where the sectors are fdc_sec_size. 19807c478bd9Sstevel@tonic-gate * The dkl_nsect field of the dk_label structure is the number of 19817c478bd9Sstevel@tonic-gate * DEV_BSIZE (512) byte sectors per track. 19827c478bd9Sstevel@tonic-gate */ 19837c478bd9Sstevel@tonic-gate labelp->dkl_nsect = (fjp->fj_chars->fdc_secptrack * 19847c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_sec_size) / DEV_BSIZE; 19857c478bd9Sstevel@tonic-gate labelp->dkl_intrlv = fjp->fj_attr->fda_intrlv; 19867c478bd9Sstevel@tonic-gate labelp->dkl_rpm = fjp->fj_attr->fda_rotatespd; 19877c478bd9Sstevel@tonic-gate labelp->dkl_read_reinstruct = 19887c478bd9Sstevel@tonic-gate (int)(labelp->dkl_nsect * labelp->dkl_rpm * 4) / 60000; 19897c478bd9Sstevel@tonic-gate labelp->dkl_write_reinstruct = labelp->dkl_read_reinstruct; 19907c478bd9Sstevel@tonic-gate 19917c478bd9Sstevel@tonic-gate labelp->dkl_magic = DKL_MAGIC; 19927c478bd9Sstevel@tonic-gate 19937c478bd9Sstevel@tonic-gate sum = 0; 19947c478bd9Sstevel@tonic-gate labelp->dkl_cksum = 0; 19957c478bd9Sstevel@tonic-gate sp = (ushort_t *)labelp; 19967c478bd9Sstevel@tonic-gate while (sp < &(labelp->dkl_cksum)) { 19977c478bd9Sstevel@tonic-gate sum ^= *sp++; 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate labelp->dkl_cksum = sum; 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate return (0); 20027c478bd9Sstevel@tonic-gate } 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate static int 20057c478bd9Sstevel@tonic-gate fd_rawioctl(struct fcu_obj *fjp, int unit, caddr_t arg, int mode) 20067c478bd9Sstevel@tonic-gate { 20077c478bd9Sstevel@tonic-gate struct fd_raw fdr; 20087c478bd9Sstevel@tonic-gate char *arg_result = NULL; 20097c478bd9Sstevel@tonic-gate int flag = B_READ; 20107c478bd9Sstevel@tonic-gate int rval = 0; 20117c478bd9Sstevel@tonic-gate caddr_t uaddr; 20127c478bd9Sstevel@tonic-gate uint_t ucount; 20137c478bd9Sstevel@tonic-gate 20147c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_RAWI, 20157c478bd9Sstevel@tonic-gate (CE_CONT, "fd_rawioctl: cmd[0]=0x%x\n", fdr.fdr_cmd[0])); 20167c478bd9Sstevel@tonic-gate 20177c478bd9Sstevel@tonic-gate if (fjp->fj_chars->fdc_medium != 3 && fjp->fj_chars->fdc_medium != 5) { 20187c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "fd_rawioctl: Medium density not supported\n"); 20197c478bd9Sstevel@tonic-gate return (ENXIO); 20207c478bd9Sstevel@tonic-gate } 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 20237c478bd9Sstevel@tonic-gate switch (ddi_model_convert_from(mode & FMODELS)) { 20247c478bd9Sstevel@tonic-gate case DDI_MODEL_ILP32: 20257c478bd9Sstevel@tonic-gate { 20267c478bd9Sstevel@tonic-gate struct fd_raw32 fdr32; 20277c478bd9Sstevel@tonic-gate 20287c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, &fdr32, sizeof (fdr32), mode)) 20297c478bd9Sstevel@tonic-gate return (EFAULT); 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate bcopy(fdr32.fdr_cmd, fdr.fdr_cmd, sizeof (fdr.fdr_cmd)); 20327c478bd9Sstevel@tonic-gate fdr.fdr_cnum = fdr32.fdr_cnum; 20337c478bd9Sstevel@tonic-gate fdr.fdr_nbytes = fdr32.fdr_nbytes; 20347c478bd9Sstevel@tonic-gate fdr.fdr_addr = (caddr_t)(uintptr_t)fdr32.fdr_addr; 20357c478bd9Sstevel@tonic-gate arg_result = ((struct fd_raw32 *)arg)->fdr_result; 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate break; 20387c478bd9Sstevel@tonic-gate } 20397c478bd9Sstevel@tonic-gate case DDI_MODEL_NONE: 20407c478bd9Sstevel@tonic-gate #endif /* ! _MULTI_DATAMODEL */ 20417c478bd9Sstevel@tonic-gate 20427c478bd9Sstevel@tonic-gate if (ddi_copyin(arg, &fdr, sizeof (fdr), mode)) 20437c478bd9Sstevel@tonic-gate return (EFAULT); 20447c478bd9Sstevel@tonic-gate 20457c478bd9Sstevel@tonic-gate arg_result = ((struct fd_raw *)arg)->fdr_result; 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate #ifdef _MULTI_DATAMODEL 20487c478bd9Sstevel@tonic-gate break; 20497c478bd9Sstevel@tonic-gate } 20507c478bd9Sstevel@tonic-gate #endif /* _MULTI_DATAMODEL */ 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate /* 20557c478bd9Sstevel@tonic-gate * copy user address & nbytes from raw_req so that we can 20567c478bd9Sstevel@tonic-gate * put kernel address in req structure 20577c478bd9Sstevel@tonic-gate */ 20587c478bd9Sstevel@tonic-gate uaddr = fdr.fdr_addr; 20597c478bd9Sstevel@tonic-gate ucount = (uint_t)fdr.fdr_nbytes; 20607c478bd9Sstevel@tonic-gate unit &= 3; 20617c478bd9Sstevel@tonic-gate 20627c478bd9Sstevel@tonic-gate switch (fdr.fdr_cmd[0] & 0x0f) { 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate case FDRAW_FORMAT: 20657c478bd9Sstevel@tonic-gate ucount += 16; 20667c478bd9Sstevel@tonic-gate fdr.fdr_addr = kmem_zalloc(ucount, KM_SLEEP); 20677c478bd9Sstevel@tonic-gate if (ddi_copyin(uaddr, fdr.fdr_addr, 20687c478bd9Sstevel@tonic-gate (size_t)fdr.fdr_nbytes, mode)) { 20697c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 20707c478bd9Sstevel@tonic-gate return (EFAULT); 20717c478bd9Sstevel@tonic-gate } 20727c478bd9Sstevel@tonic-gate if ((*fdr.fdr_addr | fdr.fdr_addr[1]) == 0) 20737c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~(FUNIT_LABELOK | FUNIT_UNLABELED); 20747c478bd9Sstevel@tonic-gate flag = B_WRITE; 20757c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 20767c478bd9Sstevel@tonic-gate break; 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate case FDRAW_WRCMD: 20797c478bd9Sstevel@tonic-gate case FDRAW_WRITEDEL: 20807c478bd9Sstevel@tonic-gate flag = B_WRITE; 20817c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 20827c478bd9Sstevel@tonic-gate case FDRAW_RDCMD: 20837c478bd9Sstevel@tonic-gate case FDRAW_READDEL: 20847c478bd9Sstevel@tonic-gate case FDRAW_READTRACK: 20857c478bd9Sstevel@tonic-gate if (ucount) { 20867c478bd9Sstevel@tonic-gate /* 20877c478bd9Sstevel@tonic-gate * In SunOS 4.X, we used to as_fault things in. 20887c478bd9Sstevel@tonic-gate * We really cannot do this in 5.0/SVr4. Unless 20897c478bd9Sstevel@tonic-gate * someone really believes that speed is of the 20907c478bd9Sstevel@tonic-gate * essence here, it is just much simpler to do 20917c478bd9Sstevel@tonic-gate * this in kernel space and use copyin/copyout. 20927c478bd9Sstevel@tonic-gate */ 20937c478bd9Sstevel@tonic-gate fdr.fdr_addr = kmem_alloc((size_t)ucount, KM_SLEEP); 20947c478bd9Sstevel@tonic-gate if (flag == B_WRITE) { 20957c478bd9Sstevel@tonic-gate if (ddi_copyin(uaddr, fdr.fdr_addr, ucount, 20967c478bd9Sstevel@tonic-gate mode)) { 20977c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 20987c478bd9Sstevel@tonic-gate return (EFAULT); 20997c478bd9Sstevel@tonic-gate } 21007c478bd9Sstevel@tonic-gate } 21017c478bd9Sstevel@tonic-gate } else 21027c478bd9Sstevel@tonic-gate return (EINVAL); 21037c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 21047c478bd9Sstevel@tonic-gate break; 21057c478bd9Sstevel@tonic-gate 21067c478bd9Sstevel@tonic-gate case FDRAW_READID: 21077c478bd9Sstevel@tonic-gate case FDRAW_REZERO: 21087c478bd9Sstevel@tonic-gate case FDRAW_SEEK: 21097c478bd9Sstevel@tonic-gate case FDRAW_SENSE_DRV: 21107c478bd9Sstevel@tonic-gate ucount = 0; 21117c478bd9Sstevel@tonic-gate fdr.fdr_cmd[1] = (fdr.fdr_cmd[1] & ~3) | unit; 21127c478bd9Sstevel@tonic-gate break; 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate case FDRAW_SPECIFY: 21157c478bd9Sstevel@tonic-gate fdr.fdr_cmd[2] &= 0xfe; /* keep NoDMA bit clear */ 21167c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 21177c478bd9Sstevel@tonic-gate case FDRAW_SENSE_INT: 21187c478bd9Sstevel@tonic-gate ucount = 0; 21197c478bd9Sstevel@tonic-gate break; 21207c478bd9Sstevel@tonic-gate 21217c478bd9Sstevel@tonic-gate default: 21227c478bd9Sstevel@tonic-gate return (EINVAL); 21237c478bd9Sstevel@tonic-gate } 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate /* 21267c478bd9Sstevel@tonic-gate * Note that we ignore any error returns from controller 21277c478bd9Sstevel@tonic-gate * This is the way the driver has been, and it may be 21287c478bd9Sstevel@tonic-gate * that the raw ioctl senders simply don't want to 21297c478bd9Sstevel@tonic-gate * see any errors returned in this fashion. 21307c478bd9Sstevel@tonic-gate */ 21317c478bd9Sstevel@tonic-gate 21327c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 21337c478bd9Sstevel@tonic-gate rval = fjp->fj_ops->fco_rwioctl(fjp, unit, (caddr_t)&fdr); 21347c478bd9Sstevel@tonic-gate 21357c478bd9Sstevel@tonic-gate if (ucount && flag == B_READ && rval == 0) { 21367c478bd9Sstevel@tonic-gate if (ddi_copyout(fdr.fdr_addr, uaddr, ucount, mode)) { 21377c478bd9Sstevel@tonic-gate rval = EFAULT; 21387c478bd9Sstevel@tonic-gate } 21397c478bd9Sstevel@tonic-gate } 21407c478bd9Sstevel@tonic-gate if (ddi_copyout(fdr.fdr_result, arg_result, sizeof (fdr.fdr_cmd), mode)) 21417c478bd9Sstevel@tonic-gate rval = EFAULT; 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 21447c478bd9Sstevel@tonic-gate if (ucount) 21457c478bd9Sstevel@tonic-gate kmem_free(fdr.fdr_addr, ucount); 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate return (rval); 21487c478bd9Sstevel@tonic-gate } 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate /* 21517c478bd9Sstevel@tonic-gate * property operation routine. return the number of blocks for the partition 21527c478bd9Sstevel@tonic-gate * in question or forward the request to the property facilities. 21537c478bd9Sstevel@tonic-gate */ 21547c478bd9Sstevel@tonic-gate static int 21557c478bd9Sstevel@tonic-gate fd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 21567c478bd9Sstevel@tonic-gate char *name, caddr_t valuep, int *lengthp) 21577c478bd9Sstevel@tonic-gate { 21587c478bd9Sstevel@tonic-gate struct fcu_obj *fjp = NULL; 21597c478bd9Sstevel@tonic-gate struct fdisk *fdp = NULL; 21607c478bd9Sstevel@tonic-gate uint64_t nblocks64; 21617c478bd9Sstevel@tonic-gate 21627c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L1, FDEM_PROP, 21637c478bd9Sstevel@tonic-gate (CE_CONT, "fd_prop_op: dip %p %s\n", (void *)dip, name)); 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate /* 21667c478bd9Sstevel@tonic-gate * Our dynamic properties are all device specific and size oriented. 21677c478bd9Sstevel@tonic-gate * Requests issued under conditions where size is valid are passed 21687c478bd9Sstevel@tonic-gate * to ddi_prop_op_nblocks with the size information, otherwise the 21697c478bd9Sstevel@tonic-gate * request is passed to ddi_prop_op. 21707c478bd9Sstevel@tonic-gate */ 21717c478bd9Sstevel@tonic-gate if (dev == DDI_DEV_T_ANY) { 21727c478bd9Sstevel@tonic-gate pass: return (ddi_prop_op(dev, dip, prop_op, mod_flags, 21737c478bd9Sstevel@tonic-gate name, valuep, lengthp)); 21747c478bd9Sstevel@tonic-gate } else { 21757c478bd9Sstevel@tonic-gate /* 21767c478bd9Sstevel@tonic-gate * Ignoring return value because success is checked by 21777c478bd9Sstevel@tonic-gate * verifying fjp and fdp and returned unit value is not used. 21787c478bd9Sstevel@tonic-gate */ 21797c478bd9Sstevel@tonic-gate (void) fd_getdrive(dev, &fjp, &fdp); 21807c478bd9Sstevel@tonic-gate if (!fjp || !fdp) 21817c478bd9Sstevel@tonic-gate goto pass; 21827c478bd9Sstevel@tonic-gate 21837c478bd9Sstevel@tonic-gate /* get nblocks value */ 21847c478bd9Sstevel@tonic-gate nblocks64 = (ulong_t)fdp->d_part[PARTITION(dev)].p_size; 21857c478bd9Sstevel@tonic-gate 21867c478bd9Sstevel@tonic-gate return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags, 21877c478bd9Sstevel@tonic-gate name, valuep, lengthp, nblocks64)); 21887c478bd9Sstevel@tonic-gate } 21897c478bd9Sstevel@tonic-gate } 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate static void 21927c478bd9Sstevel@tonic-gate fd_media_watch(void *arg) 21937c478bd9Sstevel@tonic-gate { 21947c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 21957c478bd9Sstevel@tonic-gate struct fdisk *fdp; 21967c478bd9Sstevel@tonic-gate 21977c478bd9Sstevel@tonic-gate #ifdef DEBUG 21987c478bd9Sstevel@tonic-gate int unit; 21997c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN unit= 22007c478bd9Sstevel@tonic-gate #else 22017c478bd9Sstevel@tonic-gate #define DEBUG_ASSIGN (void) 22027c478bd9Sstevel@tonic-gate #endif 22037c478bd9Sstevel@tonic-gate DEBUG_ASSIGN fd_getdrive((dev_t)arg, &fjp, &fdp); 22047c478bd9Sstevel@tonic-gate /* 22057c478bd9Sstevel@tonic-gate * Ignoring return in non DEBUG mode because device exist. 22067c478bd9Sstevel@tonic-gate * Returned unit value is not used. 22077c478bd9Sstevel@tonic-gate */ 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_IOCT, 22107c478bd9Sstevel@tonic-gate (CE_CONT, "fd_media_watch unit %d\n", unit)); 22117c478bd9Sstevel@tonic-gate 22127c478bd9Sstevel@tonic-gate /* 22137c478bd9Sstevel@tonic-gate * fd_get_media_state() cannot be called from this timeout function 22147c478bd9Sstevel@tonic-gate * because the floppy drive has to be selected first, and that could 22157c478bd9Sstevel@tonic-gate * force this function to sleep (while waiting for the select 22167c478bd9Sstevel@tonic-gate * semaphore). 22177c478bd9Sstevel@tonic-gate * Instead, just wakeup up driver. 22187c478bd9Sstevel@tonic-gate */ 22197c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 22207c478bd9Sstevel@tonic-gate cv_broadcast(&fdp->d_statecv); 22217c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 22227c478bd9Sstevel@tonic-gate } 22237c478bd9Sstevel@tonic-gate 22247c478bd9Sstevel@tonic-gate enum dkio_state 22257c478bd9Sstevel@tonic-gate fd_get_media_state(struct fcu_obj *fjp, int unit) 22267c478bd9Sstevel@tonic-gate { 22277c478bd9Sstevel@tonic-gate enum dkio_state state; 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 22307c478bd9Sstevel@tonic-gate /* recheck disk only if DSKCHG "high" */ 22317c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_resetchng(fjp, unit); 22327c478bd9Sstevel@tonic-gate if (fjp->fj_ops->fco_getchng(fjp, unit)) { 22337c478bd9Sstevel@tonic-gate if (fjp->fj_flags & FUNIT_CHGDET) { 22347c478bd9Sstevel@tonic-gate /* 22357c478bd9Sstevel@tonic-gate * again no diskette; not a new change 22367c478bd9Sstevel@tonic-gate */ 22377c478bd9Sstevel@tonic-gate state = DKIO_NONE; 22387c478bd9Sstevel@tonic-gate } else { 22397c478bd9Sstevel@tonic-gate /* 22407c478bd9Sstevel@tonic-gate * a new change; diskette was ejected 22417c478bd9Sstevel@tonic-gate */ 22427c478bd9Sstevel@tonic-gate fjp->fj_flags |= FUNIT_CHGDET; 22437c478bd9Sstevel@tonic-gate state = DKIO_EJECTED; 22447c478bd9Sstevel@tonic-gate } 22457c478bd9Sstevel@tonic-gate } else { 22467c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 22477c478bd9Sstevel@tonic-gate state = DKIO_INSERTED; 22487c478bd9Sstevel@tonic-gate } 22497c478bd9Sstevel@tonic-gate } else { 22507c478bd9Sstevel@tonic-gate fjp->fj_flags &= ~FUNIT_CHGDET; 22517c478bd9Sstevel@tonic-gate state = DKIO_INSERTED; 22527c478bd9Sstevel@tonic-gate } 22537c478bd9Sstevel@tonic-gate FDERRPRINT(FDEP_L0, FDEM_IOCT, 22547c478bd9Sstevel@tonic-gate (CE_CONT, "fd_get_media_state unit %d: state %x\n", unit, state)); 22557c478bd9Sstevel@tonic-gate return (state); 22567c478bd9Sstevel@tonic-gate } 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate static int 22597c478bd9Sstevel@tonic-gate fd_check_media(dev_t dev, enum dkio_state state) 22607c478bd9Sstevel@tonic-gate { 22617c478bd9Sstevel@tonic-gate struct fcu_obj *fjp; 22627c478bd9Sstevel@tonic-gate struct fdisk *fdp; 22637c478bd9Sstevel@tonic-gate int unit; 22647c478bd9Sstevel@tonic-gate int err; 22657c478bd9Sstevel@tonic-gate 22667c478bd9Sstevel@tonic-gate unit = fd_getdrive(dev, &fjp, &fdp); 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate mutex_enter(&fjp->fj_lock); 22697c478bd9Sstevel@tonic-gate 22707c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 22717c478bd9Sstevel@tonic-gate fdp->d_media_state = fd_get_media_state(fjp, unit); 22727c478bd9Sstevel@tonic-gate fdp->d_media_timeout = drv_usectohz(fd_check_media_time); 22737c478bd9Sstevel@tonic-gate 22747c478bd9Sstevel@tonic-gate while (fdp->d_media_state == state) { 22757c478bd9Sstevel@tonic-gate /* release the controller and drive */ 22767c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 22777c478bd9Sstevel@tonic-gate 22787c478bd9Sstevel@tonic-gate /* turn on timer */ 22797c478bd9Sstevel@tonic-gate fdp->d_media_timeout_id = timeout(fd_media_watch, 22807c478bd9Sstevel@tonic-gate (void *)dev, fdp->d_media_timeout); 22817c478bd9Sstevel@tonic-gate 22827c478bd9Sstevel@tonic-gate if (cv_wait_sig(&fdp->d_statecv, &fjp->fj_lock) == 0) { 22837c478bd9Sstevel@tonic-gate fdp->d_media_timeout = 0; 22847c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 22857c478bd9Sstevel@tonic-gate return (EINTR); 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 1); 22887c478bd9Sstevel@tonic-gate fdp->d_media_state = fd_get_media_state(fjp, unit); 22897c478bd9Sstevel@tonic-gate } 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate if (fdp->d_media_state == DKIO_INSERTED) { 22927c478bd9Sstevel@tonic-gate err = fdgetlabel(fjp, unit); 22937c478bd9Sstevel@tonic-gate if (err) { 22947c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 22957c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 22967c478bd9Sstevel@tonic-gate return (EIO); 22977c478bd9Sstevel@tonic-gate } 22987c478bd9Sstevel@tonic-gate } 22997c478bd9Sstevel@tonic-gate fjp->fj_ops->fco_select(fjp, unit, 0); 23007c478bd9Sstevel@tonic-gate mutex_exit(&fjp->fj_lock); 23017c478bd9Sstevel@tonic-gate return (0); 23027c478bd9Sstevel@tonic-gate } 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate /* 23057c478bd9Sstevel@tonic-gate * fd_get_media_info : 23067c478bd9Sstevel@tonic-gate * Collects medium information for 23077c478bd9Sstevel@tonic-gate * DKIOCGMEDIAINFO ioctl. 23087c478bd9Sstevel@tonic-gate */ 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate static int 23117c478bd9Sstevel@tonic-gate fd_get_media_info(struct fcu_obj *fjp, caddr_t buf, int flag) 23127c478bd9Sstevel@tonic-gate { 23137c478bd9Sstevel@tonic-gate struct dk_minfo media_info; 23147c478bd9Sstevel@tonic-gate int err = 0; 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate media_info.dki_media_type = DK_FLOPPY; 23177c478bd9Sstevel@tonic-gate media_info.dki_lbsize = fjp->fj_chars->fdc_sec_size; 23187c478bd9Sstevel@tonic-gate media_info.dki_capacity = fjp->fj_chars->fdc_ncyl * 23197c478bd9Sstevel@tonic-gate fjp->fj_chars->fdc_secptrack * fjp->fj_chars->fdc_nhead; 23207c478bd9Sstevel@tonic-gate 23217c478bd9Sstevel@tonic-gate if (ddi_copyout(&media_info, buf, sizeof (struct dk_minfo), flag)) 23227c478bd9Sstevel@tonic-gate err = EFAULT; 23237c478bd9Sstevel@tonic-gate return (err); 23247c478bd9Sstevel@tonic-gate } 2325