mlx_disk.c revision 52273
118334Speter/*- 252284Sobrien * Copyright (c) 1999 Jonathan Lemon 318334Speter * Copyright (c) 1999 Michael Smith 418334Speter * All rights reserved. 518334Speter * 618334Speter * Redistribution and use in source and binary forms, with or without 718334Speter * modification, are permitted provided that the following conditions 818334Speter * are met: 918334Speter * 1. Redistributions of source code must retain the above copyright 1018334Speter * notice, this list of conditions and the following disclaimer. 1118334Speter * 2. Redistributions in binary form must reproduce the above copyright 1218334Speter * notice, this list of conditions and the following disclaimer in the 1318334Speter * documentation and/or other materials provided with the distribution. 1418334Speter * 1518334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1618334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1718334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1818334Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1918334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2018334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2150397Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2250397Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2318334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2418334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2518334Speter * SUCH DAMAGE. 2618334Speter * 2718334Speter * $FreeBSD: head/sys/dev/mlx/mlx_disk.c 52273 1999-10-16 01:46:59Z msmith $ 2818334Speter */ 2918334Speter 3018334Speter/* 3118334Speter * Disk driver for Mylex DAC960 RAID adapters. 3218334Speter */ 3318334Speter 3418334Speter#include <sys/param.h> 3518334Speter#include <sys/systm.h> 3618334Speter#include <sys/malloc.h> 3718334Speter#include <sys/kernel.h> 3818334Speter 3918334Speter#include <sys/buf.h> 4018334Speter#include <sys/bus.h> 4118334Speter#include <sys/conf.h> 4218334Speter#include <sys/devicestat.h> 4318334Speter#include <sys/disk.h> 4418334Speter 4518334Speter#include <machine/bus.h> 4618334Speter#include <machine/clock.h> 4718334Speter#include <sys/rman.h> 4818334Speter 4918334Speter#include <dev/mlx/mlxio.h> 5018334Speter#include <dev/mlx/mlxvar.h> 5118334Speter 5250397Sobrien#if 0 5318334Speter#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args) 5418334Speter#else 5550397Sobrien#define debug(fmt, args...) 5618334Speter#endif 5718334Speter 5850397Sobrien/* prototypes */ 5918334Speterstatic int mlxd_probe(device_t dev); 6018334Speterstatic int mlxd_attach(device_t dev); 6150397Sobrienstatic int mlxd_detach(device_t dev); 6218334Speter 6350397Sobrienstatic d_open_t mlxd_open; 6450397Sobrienstatic d_close_t mlxd_close; 6550397Sobrienstatic d_strategy_t mlxd_strategy; 6650397Sobrienstatic d_ioctl_t mlxd_ioctl; 6750397Sobrien 6850397Sobrien#define MLXD_BDEV_MAJOR 27 6950397Sobrien#define MLXD_CDEV_MAJOR 131 7050397Sobrien 7150397Sobrienstatic struct cdevsw mlxd_cdevsw = { 7250397Sobrien /* open */ mlxd_open, 7350397Sobrien /* close */ mlxd_close, 7450397Sobrien /* read */ physread, 7550397Sobrien /* write */ physwrite, 7650397Sobrien /* ioctl */ mlxd_ioctl, 7750397Sobrien /* poll */ nopoll, 7850397Sobrien /* mmap */ nommap, 7950397Sobrien /* strategy */ mlxd_strategy, 8050397Sobrien /* name */ "mlxd", 8118334Speter /* maj */ MLXD_CDEV_MAJOR, 8218334Speter /* dump */ nodump, 8318334Speter /* psize */ nopsize, 8418334Speter /* flags */ D_DISK, 8518334Speter /* bmaj */ MLXD_BDEV_MAJOR 8618334Speter}; 8718334Speter 8818334Speterstatic devclass_t mlxd_devclass; 8918334Speterstatic struct cdevsw mlxddisk_cdevsw; 9018334Speterstatic int disks_registered = 0; 9150397Sobrien 9250397Sobrienstatic device_method_t mlxd_methods[] = { 9350397Sobrien DEVMETHOD(device_probe, mlxd_probe), 9452284Sobrien DEVMETHOD(device_attach, mlxd_attach), 9518334Speter DEVMETHOD(device_detach, mlxd_detach), 9618334Speter { 0, 0 } 9718334Speter}; 9818334Speter 9918334Speterstatic driver_t mlxd_driver = { 10018334Speter "mlxd", 10118334Speter mlxd_methods, 10218334Speter sizeof(struct mlxd_softc) 10318334Speter}; 10418334Speter 10518334SpeterDRIVER_MODULE(mlxd, mlx, mlxd_driver, mlxd_devclass, 0, 0); 10618334Speter 10718334Speterstatic int 10818334Spetermlxd_open(dev_t dev, int flags, int fmt, struct proc *p) 10918334Speter{ 11018334Speter struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1; 11118334Speter struct disklabel *label; 11218334Speter 11318334Speter debug("called"); 11418334Speter 11518334Speter if (sc == NULL) 11618334Speter return (ENXIO); 11752284Sobrien 11818334Speter /* controller not active? */ 11952284Sobrien if (sc->mlxd_controller->mlx_state & MLX_STATE_SHUTDOWN) 12018334Speter return(ENXIO); 12118334Speter 12218334Speter label = &sc->mlxd_disk.d_label; 12318334Speter bzero(label, sizeof(*label)); 12418334Speter label->d_type = DTYPE_SCSI; 12518334Speter label->d_secsize = MLX_BLKSIZE; 12618334Speter label->d_nsectors = sc->mlxd_drive->ms_sectors; 12718334Speter label->d_ntracks = sc->mlxd_drive->ms_heads; 12818334Speter label->d_ncylinders = sc->mlxd_drive->ms_cylinders; 12918334Speter label->d_secpercyl = sc->mlxd_drive->ms_sectors * sc->mlxd_drive->ms_heads; 13018334Speter label->d_secperunit = sc->mlxd_drive->ms_size; 13118334Speter 13218334Speter sc->mlxd_flags |= MLXD_OPEN; 13318334Speter return (0); 13418334Speter} 13518334Speter 13618334Speterstatic int 13718334Spetermlxd_close(dev_t dev, int flags, int fmt, struct proc *p) 13818334Speter{ 13950397Sobrien struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1; 14018334Speter 14118334Speter debug("called"); 14218334Speter 14318334Speter if (sc == NULL) 14418334Speter return (ENXIO); 14518334Speter sc->mlxd_flags &= ~MLXD_OPEN; 14618334Speter return (0); 14718334Speter} 14818334Speter 14918334Speterstatic int 15018334Spetermlxd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) 15118334Speter{ 15218334Speter struct mlxd_softc *sc = (struct mlxd_softc *)dev->si_drv1; 15318334Speter int error; 15418334Speter 15518334Speter debug("called"); 15618334Speter 15718334Speter if (sc == NULL) 15818334Speter return (ENXIO); 15918334Speter 16018334Speter if ((error = mlx_submit_ioctl(sc->mlxd_controller, sc->mlxd_drive, cmd, addr, flag, p)) != ENOIOCTL) { 16118334Speter debug("mlx_submit_ioctl returned %d\n", error); 16218334Speter return(error); 16318334Speter } 16418334Speter return (ENOTTY); 16518334Speter} 16652284Sobrien 16752284Sobrien/* 16852284Sobrien * Read/write routine for a buffer. Finds the proper unit, range checks 16952284Sobrien * arguments, and schedules the transfer. Does not wait for the transfer 17052284Sobrien * to complete. Multi-page transfers are supported. All I/O requests must 17150397Sobrien * be a multiple of a sector in length. 17218334Speter */ 17318334Speterstatic void 17418334Spetermlxd_strategy(struct buf *bp) 17518334Speter{ 17618334Speter struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_dev->si_drv1; 17718334Speter int s; 17818334Speter 17918334Speter debug("called"); 18018334Speter 18118334Speter /* bogus disk? */ 18218334Speter if (sc == NULL) { 18318334Speter bp->b_error = EINVAL; 18418334Speter goto bad; 18518334Speter } 18618334Speter 18718334Speter /* XXX may only be temporarily offline - sleep? */ 18818334Speter if (sc->mlxd_drive->ms_state == MLX_SYSD_OFFLINE) { 18918334Speter bp->b_error = ENXIO; 19018334Speter goto bad; 19118334Speter } 19218334Speter 19318334Speter /* do-nothing operation */ 19418334Speter if (bp->b_bcount == 0) 19550397Sobrien goto done; 19618334Speter 19718334Speter s = splbio(); 19818334Speter devstat_start_transaction(&sc->mlxd_stats); 19918334Speter mlx_submit_buf(sc->mlxd_controller, bp); 20018334Speter splx(s); 20118334Speter return; 20250397Sobrien 20318334Speter bad: 20418334Speter bp->b_flags |= B_ERROR; 20518334Speter 20618334Speter done: 20718334Speter /* 20818334Speter * Correctly set the buf to indicate a completed transfer 20950397Sobrien */ 21018334Speter bp->b_resid = bp->b_bcount; 21118334Speter biodone(bp); 21218334Speter return; 21318334Speter} 21418334Speter 21518334Spetervoid 21618334Spetermlxd_intr(void *data) 21718334Speter{ 21818334Speter struct buf *bp = (struct buf *)data; 21918334Speter struct mlxd_softc *sc = (struct mlxd_softc *)bp->b_dev->si_drv1; 22018334Speter 22118334Speter debug("called"); 22250397Sobrien 22350397Sobrien if (bp->b_flags & B_ERROR) 22418334Speter bp->b_error = EIO; 22518334Speter else 22618334Speter bp->b_resid = 0; 22718334Speter 22818334Speter devstat_end_transaction_buf(&sc->mlxd_stats, bp); 22918334Speter biodone(bp); 23018334Speter} 23118334Speter 23218334Speterstatic int 23318334Spetermlxd_probe(device_t dev) 23450397Sobrien{ 23550397Sobrien 23650397Sobrien debug("called"); 23718334Speter 23818334Speter device_set_desc(dev, "Mylex System Drive"); 23918334Speter return (0); 24018334Speter} 24118334Speter 24218334Speterstatic int 24318334Spetermlxd_attach(device_t dev) 24418334Speter{ 24518334Speter struct mlxd_softc *sc = (struct mlxd_softc *)device_get_softc(dev); 24618334Speter device_t parent; 24718334Speter char *state; 24818334Speter dev_t dsk; 24918334Speter 25018334Speter debug("called"); 25118334Speter 25218334Speter parent = device_get_parent(dev); 25318334Speter sc->mlxd_controller = (struct mlx_softc *)device_get_softc(parent); 25418334Speter sc->mlxd_unit = device_get_unit(dev); 25518334Speter sc->mlxd_drive = device_get_ivars(dev); 25618334Speter sc->mlxd_dev = dev; 25718334Speter 25818334Speter switch(sc->mlxd_drive->ms_state) { 25918334Speter case MLX_SYSD_ONLINE: 26018334Speter state = "online"; 26118334Speter break; 26218334Speter case MLX_SYSD_CRITICAL: 26318334Speter state = "critical"; 26418334Speter break; 26518334Speter case MLX_SYSD_OFFLINE: 26618334Speter state = "offline"; 26718334Speter break; 26818334Speter default: 26918334Speter state = "unknown state"; 27018334Speter } 27118334Speter 27218334Speter device_printf(dev, "%uMB (%u sectors), RAID %d (%s)\n", 27318334Speter sc->mlxd_drive->ms_size / ((1024 * 1024) / MLX_BLKSIZE), 27418334Speter sc->mlxd_drive->ms_size, sc->mlxd_drive->ms_raidlevel, state); 27518334Speter 27618334Speter devstat_add_entry(&sc->mlxd_stats, "mlxd", sc->mlxd_unit, MLX_BLKSIZE, 27718334Speter DEVSTAT_NO_ORDERED_TAGS, 27818334Speter DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER, 27918334Speter DEVSTAT_PRIORITY_DA); 28018334Speter 28118334Speter dsk = disk_create(sc->mlxd_unit, &sc->mlxd_disk, 0, &mlxd_cdevsw, &mlxddisk_cdevsw); 28218334Speter disks_registered++; 28318334Speter 28418334Speter /* set maximum I/O size */ 28518334Speter dsk->si_iosize_max = sc->mlxd_controller->mlx_maxiosize * MLX_BLKSIZE; 28618334Speter dsk->si_drv1 = sc; 28750397Sobrien 28850397Sobrien return (0); 28950397Sobrien} 29050397Sobrien 29118334Speterstatic int 29250397Sobrienmlxd_detach(device_t dev) 29350397Sobrien{ 29450397Sobrien struct mlxd_softc *sc = (struct mlxd_softc *)device_get_softc(dev); 29550397Sobrien 29618334Speter debug("called"); 29718334Speter 29818334Speter devstat_remove_entry(&sc->mlxd_stats); 29918334Speter 30018334Speter /* hack to handle lack of destroy_disk() */ 30118334Speter if (--disks_registered == 0) 30218334Speter cdevsw_remove(&mlxddisk_cdevsw); 30318334Speter 30418334Speter return(0); 30518334Speter} 30618334Speter 30718334Speter