mlx_disk.c revision 112946
151973Smsmith/*- 251973Smsmith * Copyright (c) 1999 Jonathan Lemon 351973Smsmith * Copyright (c) 1999 Michael Smith 451973Smsmith * All rights reserved. 551973Smsmith * 651973Smsmith * Redistribution and use in source and binary forms, with or without 751973Smsmith * modification, are permitted provided that the following conditions 851973Smsmith * are met: 951973Smsmith * 1. Redistributions of source code must retain the above copyright 1051973Smsmith * notice, this list of conditions and the following disclaimer. 1151973Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1251973Smsmith * notice, this list of conditions and the following disclaimer in the 1351973Smsmith * documentation and/or other materials provided with the distribution. 1451973Smsmith * 1551973Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1651973Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1751973Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1851973Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1951973Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2051973Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2151973Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2251973Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2351973Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2451973Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2551973Smsmith * SUCH DAMAGE. 2651973Smsmith * 2751973Smsmith * $FreeBSD: head/sys/dev/mlx/mlx_disk.c 112946 2003-04-01 15:06:26Z phk $ 2851973Smsmith */ 2951973Smsmith 3051973Smsmith/* 3151973Smsmith * Disk driver for Mylex DAC960 RAID adapters. 3251973Smsmith */ 3351973Smsmith 3451973Smsmith#include <sys/param.h> 3551973Smsmith#include <sys/systm.h> 3651973Smsmith#include <sys/kernel.h> 3751973Smsmith 3851973Smsmith#include <sys/bus.h> 3951973Smsmith#include <sys/conf.h> 4051973Smsmith 4151973Smsmith#include <machine/bus.h> 4251973Smsmith#include <sys/rman.h> 4351973Smsmith 44112946Sphk#include <geom/geom_disk.h> 45112946Sphk 4678752Smsmith#include <dev/mlx/mlx_compat.h> 4751973Smsmith#include <dev/mlx/mlxio.h> 4851973Smsmith#include <dev/mlx/mlxvar.h> 4952544Smsmith#include <dev/mlx/mlxreg.h> 5051973Smsmith 5151973Smsmith/* prototypes */ 5251973Smsmithstatic int mlxd_probe(device_t dev); 5351973Smsmithstatic int mlxd_attach(device_t dev); 5451973Smsmithstatic int mlxd_detach(device_t dev); 5551973Smsmith 5659136Smsmithdevclass_t mlxd_devclass; 5751973Smsmith 5851973Smsmithstatic device_method_t mlxd_methods[] = { 5951973Smsmith DEVMETHOD(device_probe, mlxd_probe), 6051973Smsmith DEVMETHOD(device_attach, mlxd_attach), 6151973Smsmith DEVMETHOD(device_detach, mlxd_detach), 6251973Smsmith { 0, 0 } 6351973Smsmith}; 6451973Smsmith 6551973Smsmithstatic driver_t mlxd_driver = { 6651973Smsmith "mlxd", 6751973Smsmith mlxd_methods, 6851973Smsmith sizeof(struct mlxd_softc) 6951973Smsmith}; 7051973Smsmith 7151973SmsmithDRIVER_MODULE(mlxd, mlx, mlxd_driver, mlxd_devclass, 0, 0); 7251973Smsmith 7351973Smsmithstatic int 74111469Sphkmlxd_open(struct disk *dp) 7551973Smsmith{ 76111469Sphk struct mlxd_softc *sc = (struct mlxd_softc *)dp->d_drv1; 7751973Smsmith 7858188Smsmith debug_called(1); 7951973Smsmith 8051973Smsmith if (sc == NULL) 8151973Smsmith return (ENXIO); 8251973Smsmith 8351973Smsmith /* controller not active? */ 8451973Smsmith if (sc->mlxd_controller->mlx_state & MLX_STATE_SHUTDOWN) 8551973Smsmith return(ENXIO); 8651973Smsmith 8751973Smsmith sc->mlxd_flags |= MLXD_OPEN; 8851973Smsmith return (0); 8951973Smsmith} 9051973Smsmith 9151973Smsmithstatic int 92111469Sphkmlxd_close(struct disk *dp) 9351973Smsmith{ 94111469Sphk struct mlxd_softc *sc = (struct mlxd_softc *)dp->d_drv1; 9551973Smsmith 9658188Smsmith debug_called(1); 9751973Smsmith 9851973Smsmith if (sc == NULL) 9951973Smsmith return (ENXIO); 10051973Smsmith sc->mlxd_flags &= ~MLXD_OPEN; 10151973Smsmith return (0); 10251973Smsmith} 10351973Smsmith 10451973Smsmithstatic int 105111469Sphkmlxd_ioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td) 10651973Smsmith{ 107111469Sphk struct mlxd_softc *sc = (struct mlxd_softc *)dp->d_drv1; 10851973Smsmith int error; 10951973Smsmith 11058188Smsmith debug_called(1); 11151973Smsmith 11251973Smsmith if (sc == NULL) 11351973Smsmith return (ENXIO); 11451973Smsmith 11583366Sjulian if ((error = mlx_submit_ioctl(sc->mlxd_controller, sc->mlxd_drive, cmd, addr, flag, td)) != ENOIOCTL) { 11658188Smsmith debug(0, "mlx_submit_ioctl returned %d\n", error); 11751973Smsmith return(error); 11851973Smsmith } 11951973Smsmith return (ENOTTY); 12051973Smsmith} 12151973Smsmith 12251973Smsmith/* 12351973Smsmith * Read/write routine for a buffer. Finds the proper unit, range checks 12451973Smsmith * arguments, and schedules the transfer. Does not wait for the transfer 12551973Smsmith * to complete. Multi-page transfers are supported. All I/O requests must 12651973Smsmith * be a multiple of a sector in length. 12751973Smsmith */ 12851973Smsmithstatic void 12978752Smsmithmlxd_strategy(mlx_bio *bp) 13051973Smsmith{ 13178752Smsmith struct mlxd_softc *sc = (struct mlxd_softc *)MLX_BIO_SOFTC(bp); 13251973Smsmith 13358188Smsmith debug_called(1); 13451973Smsmith 13551973Smsmith /* bogus disk? */ 13651973Smsmith if (sc == NULL) { 13778752Smsmith MLX_BIO_SET_ERROR(bp, EINVAL); 13851973Smsmith goto bad; 13951973Smsmith } 14051973Smsmith 14151973Smsmith /* XXX may only be temporarily offline - sleep? */ 14251973Smsmith if (sc->mlxd_drive->ms_state == MLX_SYSD_OFFLINE) { 14378752Smsmith MLX_BIO_SET_ERROR(bp, ENXIO); 14451973Smsmith goto bad; 14551973Smsmith } 14651973Smsmith 14778752Smsmith MLX_BIO_STATS_START(bp); 14851973Smsmith mlx_submit_buf(sc->mlxd_controller, bp); 14951973Smsmith return; 15051973Smsmith 15151973Smsmith bad: 15251973Smsmith /* 15378752Smsmith * Correctly set the bio to indicate a failed tranfer. 15451973Smsmith */ 15578752Smsmith MLX_BIO_RESID(bp) = MLX_BIO_LENGTH(bp); 15678752Smsmith MLX_BIO_DONE(bp); 15751973Smsmith return; 15851973Smsmith} 15951973Smsmith 16051973Smsmithvoid 16151973Smsmithmlxd_intr(void *data) 16251973Smsmith{ 16378752Smsmith mlx_bio *bp = (mlx_bio *)data; 16451973Smsmith 16558188Smsmith debug_called(1); 16651973Smsmith 16778752Smsmith if (MLX_BIO_HAS_ERROR(bp)) 16878752Smsmith MLX_BIO_SET_ERROR(bp, EIO); 16951973Smsmith else 17078752Smsmith MLX_BIO_RESID(bp) = 0; 17151973Smsmith 17278752Smsmith MLX_BIO_STATS_END(bp); 17378752Smsmith MLX_BIO_DONE(bp); 17451973Smsmith} 17551973Smsmith 17651973Smsmithstatic int 17751973Smsmithmlxd_probe(device_t dev) 17851973Smsmith{ 17951973Smsmith 18058188Smsmith debug_called(1); 18151973Smsmith 18251973Smsmith device_set_desc(dev, "Mylex System Drive"); 18351973Smsmith return (0); 18451973Smsmith} 18551973Smsmith 18651973Smsmithstatic int 18751973Smsmithmlxd_attach(device_t dev) 18851973Smsmith{ 18951973Smsmith struct mlxd_softc *sc = (struct mlxd_softc *)device_get_softc(dev); 19051973Smsmith device_t parent; 19151973Smsmith char *state; 19260074Smsmith int s1, s2; 19351973Smsmith 19458188Smsmith debug_called(1); 19551973Smsmith 19651973Smsmith parent = device_get_parent(dev); 19751973Smsmith sc->mlxd_controller = (struct mlx_softc *)device_get_softc(parent); 19851973Smsmith sc->mlxd_unit = device_get_unit(dev); 19951973Smsmith sc->mlxd_drive = device_get_ivars(dev); 20052273Smsmith sc->mlxd_dev = dev; 20151973Smsmith 20251973Smsmith switch(sc->mlxd_drive->ms_state) { 20351973Smsmith case MLX_SYSD_ONLINE: 20451973Smsmith state = "online"; 20551973Smsmith break; 20651973Smsmith case MLX_SYSD_CRITICAL: 20751973Smsmith state = "critical"; 20851973Smsmith break; 20951973Smsmith case MLX_SYSD_OFFLINE: 21051973Smsmith state = "offline"; 21151973Smsmith break; 21251973Smsmith default: 21351973Smsmith state = "unknown state"; 21451973Smsmith } 21551973Smsmith 21652785Smsmith device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n", 21751973Smsmith sc->mlxd_drive->ms_size / ((1024 * 1024) / MLX_BLKSIZE), 21851973Smsmith sc->mlxd_drive->ms_size, sc->mlxd_drive->ms_raidlevel, state); 21951973Smsmith 220111469Sphk sc->mlxd_disk.d_open = mlxd_open; 221111469Sphk sc->mlxd_disk.d_close = mlxd_close; 222111469Sphk sc->mlxd_disk.d_ioctl = mlxd_ioctl; 223111469Sphk sc->mlxd_disk.d_strategy = mlxd_strategy; 224111497Sjhb sc->mlxd_disk.d_name = "mlxd"; 225111469Sphk sc->mlxd_disk.d_drv1 = sc; 226111469Sphk sc->mlxd_disk.d_sectorsize = MLX_BLKSIZE; 227111469Sphk sc->mlxd_disk.d_mediasize = MLX_BLKSIZE * (off_t)sc->mlxd_drive->ms_size; 228111469Sphk sc->mlxd_disk.d_fwsectors = sc->mlxd_drive->ms_sectors; 229111469Sphk sc->mlxd_disk.d_fwheads = sc->mlxd_drive->ms_heads; 23051973Smsmith 23160074Smsmith /* 23260074Smsmith * Set maximum I/O size to the lesser of the recommended maximum and the practical 233111499Sjhb * maximum except on v2 cards where the maximum is set to 8 pages. 23460074Smsmith */ 235111499Sjhb if (sc->mlxd_controller->mlx_iftype == MLX_IFTYPE_2) 236111509Sjhb sc->mlxd_disk.d_maxsize = 8 * PAGE_SIZE; 237111499Sjhb else { 238111499Sjhb s1 = sc->mlxd_controller->mlx_enq2->me_maxblk * MLX_BLKSIZE; 239111499Sjhb s2 = (sc->mlxd_controller->mlx_enq2->me_max_sg - 1) * PAGE_SIZE; 240111509Sjhb sc->mlxd_disk.d_maxsize = imin(s1, s2); 241111499Sjhb } 24252225Smsmith 243111469Sphk disk_create(sc->mlxd_unit, &sc->mlxd_disk, 0, NULL, NULL); 244111469Sphk 24551973Smsmith return (0); 24651973Smsmith} 24751973Smsmith 24851973Smsmithstatic int 24951973Smsmithmlxd_detach(device_t dev) 25051973Smsmith{ 25151973Smsmith struct mlxd_softc *sc = (struct mlxd_softc *)device_get_softc(dev); 25251973Smsmith 25358188Smsmith debug_called(1); 25451973Smsmith 255111216Sphk disk_destroy(&sc->mlxd_disk); 25651973Smsmith 25751973Smsmith return(0); 25851973Smsmith} 25951973Smsmith 260