xref: /freebsd/sys/dev/mlx/mlx_disk.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
11ac4b82bSMike Smith /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
41ac4b82bSMike Smith  * Copyright (c) 1999 Jonathan Lemon
51ac4b82bSMike Smith  * Copyright (c) 1999 Michael Smith
61ac4b82bSMike Smith  * All rights reserved.
71ac4b82bSMike Smith  *
81ac4b82bSMike Smith  * Redistribution and use in source and binary forms, with or without
91ac4b82bSMike Smith  * modification, are permitted provided that the following conditions
101ac4b82bSMike Smith  * are met:
111ac4b82bSMike Smith  * 1. Redistributions of source code must retain the above copyright
121ac4b82bSMike Smith  *    notice, this list of conditions and the following disclaimer.
131ac4b82bSMike Smith  * 2. Redistributions in binary form must reproduce the above copyright
141ac4b82bSMike Smith  *    notice, this list of conditions and the following disclaimer in the
151ac4b82bSMike Smith  *    documentation and/or other materials provided with the distribution.
161ac4b82bSMike Smith  *
171ac4b82bSMike Smith  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
181ac4b82bSMike Smith  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191ac4b82bSMike Smith  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201ac4b82bSMike Smith  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
211ac4b82bSMike Smith  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221ac4b82bSMike Smith  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231ac4b82bSMike Smith  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241ac4b82bSMike Smith  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251ac4b82bSMike Smith  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261ac4b82bSMike Smith  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271ac4b82bSMike Smith  * SUCH DAMAGE.
281ac4b82bSMike Smith  *
291ac4b82bSMike Smith  */
301ac4b82bSMike Smith 
31aad970f1SDavid E. O'Brien #include <sys/cdefs.h>
321ac4b82bSMike Smith /*
331ac4b82bSMike Smith  * Disk driver for Mylex DAC960 RAID adapters.
341ac4b82bSMike Smith  */
351ac4b82bSMike Smith 
361ac4b82bSMike Smith #include <sys/param.h>
371ac4b82bSMike Smith #include <sys/systm.h>
38b04e4c12SJohn Baldwin #include <sys/bio.h>
391ac4b82bSMike Smith #include <sys/kernel.h>
400fca6f8bSJohn Baldwin #include <sys/lock.h>
41fe12f24bSPoul-Henning Kamp #include <sys/module.h>
420fca6f8bSJohn Baldwin #include <sys/sx.h>
431ac4b82bSMike Smith 
441ac4b82bSMike Smith #include <sys/bus.h>
451ac4b82bSMike Smith #include <sys/conf.h>
461ac4b82bSMike Smith 
471ac4b82bSMike Smith #include <machine/bus.h>
481ac4b82bSMike Smith #include <sys/rman.h>
491ac4b82bSMike Smith 
50891619a6SPoul-Henning Kamp #include <geom/geom_disk.h>
51891619a6SPoul-Henning Kamp 
521ac4b82bSMike Smith #include <dev/mlx/mlxio.h>
531ac4b82bSMike Smith #include <dev/mlx/mlxvar.h>
544b006d7bSMike Smith #include <dev/mlx/mlxreg.h>
551ac4b82bSMike Smith 
561ac4b82bSMike Smith /* prototypes */
571ac4b82bSMike Smith static int mlxd_probe(device_t dev);
581ac4b82bSMike Smith static int mlxd_attach(device_t dev);
591ac4b82bSMike Smith static int mlxd_detach(device_t dev);
601ac4b82bSMike Smith 
611ac4b82bSMike Smith static device_method_t mlxd_methods[] = {
621ac4b82bSMike Smith     DEVMETHOD(device_probe,	mlxd_probe),
631ac4b82bSMike Smith     DEVMETHOD(device_attach,	mlxd_attach),
641ac4b82bSMike Smith     DEVMETHOD(device_detach,	mlxd_detach),
651ac4b82bSMike Smith     { 0, 0 }
661ac4b82bSMike Smith };
671ac4b82bSMike Smith 
681ac4b82bSMike Smith static driver_t mlxd_driver = {
691ac4b82bSMike Smith     "mlxd",
701ac4b82bSMike Smith     mlxd_methods,
711ac4b82bSMike Smith     sizeof(struct mlxd_softc)
721ac4b82bSMike Smith };
731ac4b82bSMike Smith 
749cd54db5SJohn Baldwin DRIVER_MODULE(mlxd, mlx, mlxd_driver, 0, 0);
751ac4b82bSMike Smith 
761ac4b82bSMike Smith static int
mlxd_open(struct disk * dp)77b2fe65c5SPoul-Henning Kamp mlxd_open(struct disk *dp)
781ac4b82bSMike Smith {
79b2fe65c5SPoul-Henning Kamp     struct mlxd_softc	*sc = (struct mlxd_softc *)dp->d_drv1;
801ac4b82bSMike Smith 
81da8bb3a3SMike Smith     debug_called(1);
821ac4b82bSMike Smith 
831ac4b82bSMike Smith     if (sc == NULL)
841ac4b82bSMike Smith 	return (ENXIO);
851ac4b82bSMike Smith 
861ac4b82bSMike Smith     /* controller not active? */
870fca6f8bSJohn Baldwin     MLX_CONFIG_LOCK(sc->mlxd_controller);
880fca6f8bSJohn Baldwin     MLX_IO_LOCK(sc->mlxd_controller);
890fca6f8bSJohn Baldwin     if (sc->mlxd_controller->mlx_state & MLX_STATE_SHUTDOWN) {
900fca6f8bSJohn Baldwin 	MLX_IO_UNLOCK(sc->mlxd_controller);
910fca6f8bSJohn Baldwin 	MLX_CONFIG_UNLOCK(sc->mlxd_controller);
921ac4b82bSMike Smith 	return(ENXIO);
930fca6f8bSJohn Baldwin     }
941ac4b82bSMike Smith 
951ac4b82bSMike Smith     sc->mlxd_flags |= MLXD_OPEN;
960fca6f8bSJohn Baldwin     MLX_IO_UNLOCK(sc->mlxd_controller);
970fca6f8bSJohn Baldwin     MLX_CONFIG_UNLOCK(sc->mlxd_controller);
981ac4b82bSMike Smith     return (0);
991ac4b82bSMike Smith }
1001ac4b82bSMike Smith 
1011ac4b82bSMike Smith static int
mlxd_close(struct disk * dp)102b2fe65c5SPoul-Henning Kamp mlxd_close(struct disk *dp)
1031ac4b82bSMike Smith {
104b2fe65c5SPoul-Henning Kamp     struct mlxd_softc	*sc = (struct mlxd_softc *)dp->d_drv1;
1051ac4b82bSMike Smith 
106da8bb3a3SMike Smith     debug_called(1);
1071ac4b82bSMike Smith 
1081ac4b82bSMike Smith     if (sc == NULL)
1091ac4b82bSMike Smith 	return (ENXIO);
1100fca6f8bSJohn Baldwin     MLX_CONFIG_LOCK(sc->mlxd_controller);
1110fca6f8bSJohn Baldwin     MLX_IO_LOCK(sc->mlxd_controller);
1121ac4b82bSMike Smith     sc->mlxd_flags &= ~MLXD_OPEN;
1130fca6f8bSJohn Baldwin     MLX_IO_UNLOCK(sc->mlxd_controller);
1140fca6f8bSJohn Baldwin     MLX_CONFIG_UNLOCK(sc->mlxd_controller);
1151ac4b82bSMike Smith     return (0);
1161ac4b82bSMike Smith }
1171ac4b82bSMike Smith 
1181ac4b82bSMike Smith static int
mlxd_ioctl(struct disk * dp,u_long cmd,void * addr,int flag,struct thread * td)119b2fe65c5SPoul-Henning Kamp mlxd_ioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
1201ac4b82bSMike Smith {
121b2fe65c5SPoul-Henning Kamp     struct mlxd_softc	*sc = (struct mlxd_softc *)dp->d_drv1;
1221ac4b82bSMike Smith     int error;
1231ac4b82bSMike Smith 
124da8bb3a3SMike Smith     debug_called(1);
1251ac4b82bSMike Smith 
1261ac4b82bSMike Smith     if (sc == NULL)
1271ac4b82bSMike Smith 	return (ENXIO);
1281ac4b82bSMike Smith 
129b40ce416SJulian Elischer     if ((error = mlx_submit_ioctl(sc->mlxd_controller, sc->mlxd_drive, cmd, addr, flag, td)) != ENOIOCTL) {
130da8bb3a3SMike Smith 	debug(0, "mlx_submit_ioctl returned %d\n", error);
1311ac4b82bSMike Smith 	return(error);
1321ac4b82bSMike Smith     }
1331ac4b82bSMike Smith     return (ENOTTY);
1341ac4b82bSMike Smith }
1351ac4b82bSMike Smith 
1361ac4b82bSMike Smith /*
1371ac4b82bSMike Smith  * Read/write routine for a buffer.  Finds the proper unit, range checks
1381ac4b82bSMike Smith  * arguments, and schedules the transfer.  Does not wait for the transfer
1391ac4b82bSMike Smith  * to complete.  Multi-page transfers are supported.  All I/O requests must
1401ac4b82bSMike Smith  * be a multiple of a sector in length.
1411ac4b82bSMike Smith  */
1421ac4b82bSMike Smith static void
mlxd_strategy(struct bio * bp)143b04e4c12SJohn Baldwin mlxd_strategy(struct bio *bp)
1441ac4b82bSMike Smith {
145b04e4c12SJohn Baldwin     struct mlxd_softc	*sc = bp->bio_disk->d_drv1;
1461ac4b82bSMike Smith 
147da8bb3a3SMike Smith     debug_called(1);
1481ac4b82bSMike Smith 
1491ac4b82bSMike Smith     /* bogus disk? */
1501ac4b82bSMike Smith     if (sc == NULL) {
151b04e4c12SJohn Baldwin 	bp->bio_error = EINVAL;
152b04e4c12SJohn Baldwin 	bp->bio_flags |= BIO_ERROR;
1531ac4b82bSMike Smith 	goto bad;
1541ac4b82bSMike Smith     }
1551ac4b82bSMike Smith 
156d176b803SScott Long     if ((bp->bio_cmd != BIO_READ) && (bp->bio_cmd != BIO_WRITE)) {
157d176b803SScott Long 	bp->bio_error = EOPNOTSUPP;
158d176b803SScott Long 	goto bad;
159d176b803SScott Long     }
160d176b803SScott Long 
1611ac4b82bSMike Smith     /* XXX may only be temporarily offline - sleep? */
1620fca6f8bSJohn Baldwin     MLX_IO_LOCK(sc->mlxd_controller);
1631ac4b82bSMike Smith     if (sc->mlxd_drive->ms_state == MLX_SYSD_OFFLINE) {
1640fca6f8bSJohn Baldwin 	MLX_IO_UNLOCK(sc->mlxd_controller);
165b04e4c12SJohn Baldwin 	bp->bio_error = ENXIO;
166b04e4c12SJohn Baldwin 	bp->bio_flags |= BIO_ERROR;
1671ac4b82bSMike Smith 	goto bad;
1681ac4b82bSMike Smith     }
1691ac4b82bSMike Smith 
1701ac4b82bSMike Smith     mlx_submit_buf(sc->mlxd_controller, bp);
1710fca6f8bSJohn Baldwin     MLX_IO_UNLOCK(sc->mlxd_controller);
1721ac4b82bSMike Smith     return;
1731ac4b82bSMike Smith 
1741ac4b82bSMike Smith  bad:
1751ac4b82bSMike Smith     /*
176453130d9SPedro F. Giffuni      * Correctly set the bio to indicate a failed transfer.
1771ac4b82bSMike Smith      */
178b04e4c12SJohn Baldwin     bp->bio_resid = bp->bio_bcount;
179b04e4c12SJohn Baldwin     biodone(bp);
1801ac4b82bSMike Smith     return;
1811ac4b82bSMike Smith }
1821ac4b82bSMike Smith 
1831ac4b82bSMike Smith void
mlxd_intr(struct bio * bp)184b04e4c12SJohn Baldwin mlxd_intr(struct bio *bp)
1851ac4b82bSMike Smith {
1861ac4b82bSMike Smith 
187da8bb3a3SMike Smith     debug_called(1);
1881ac4b82bSMike Smith 
189b04e4c12SJohn Baldwin     if (bp->bio_flags & BIO_ERROR)
190b04e4c12SJohn Baldwin 	bp->bio_error = EIO;
1911ac4b82bSMike Smith     else
192b04e4c12SJohn Baldwin 	bp->bio_resid = 0;
1931ac4b82bSMike Smith 
194b04e4c12SJohn Baldwin     biodone(bp);
1951ac4b82bSMike Smith }
1961ac4b82bSMike Smith 
1971ac4b82bSMike Smith static int
mlxd_probe(device_t dev)1981ac4b82bSMike Smith mlxd_probe(device_t dev)
1991ac4b82bSMike Smith {
2001ac4b82bSMike Smith 
201da8bb3a3SMike Smith     debug_called(1);
2021ac4b82bSMike Smith 
2031ac4b82bSMike Smith     device_set_desc(dev, "Mylex System Drive");
2041ac4b82bSMike Smith     return (0);
2051ac4b82bSMike Smith }
2061ac4b82bSMike Smith 
2071ac4b82bSMike Smith static int
mlxd_attach(device_t dev)2081ac4b82bSMike Smith mlxd_attach(device_t dev)
2091ac4b82bSMike Smith {
2101ac4b82bSMike Smith     struct mlxd_softc	*sc = (struct mlxd_softc *)device_get_softc(dev);
2111ac4b82bSMike Smith     device_t		parent;
2121ac4b82bSMike Smith     char		*state;
213baff09dbSMike Smith     int			s1, s2;
2141ac4b82bSMike Smith 
215da8bb3a3SMike Smith     debug_called(1);
2161ac4b82bSMike Smith 
2171ac4b82bSMike Smith     parent = device_get_parent(dev);
2181ac4b82bSMike Smith     sc->mlxd_controller = (struct mlx_softc *)device_get_softc(parent);
2191ac4b82bSMike Smith     sc->mlxd_unit = device_get_unit(dev);
2201ac4b82bSMike Smith     sc->mlxd_drive = device_get_ivars(dev);
221f01f2af6SMike Smith     sc->mlxd_dev = dev;
2221ac4b82bSMike Smith 
2231ac4b82bSMike Smith     switch(sc->mlxd_drive->ms_state) {
2241ac4b82bSMike Smith     case MLX_SYSD_ONLINE:
2251ac4b82bSMike Smith 	state = "online";
2261ac4b82bSMike Smith 	break;
2271ac4b82bSMike Smith     case MLX_SYSD_CRITICAL:
2281ac4b82bSMike Smith 	state = "critical";
2291ac4b82bSMike Smith 	break;
2301ac4b82bSMike Smith     case MLX_SYSD_OFFLINE:
2311ac4b82bSMike Smith 	state = "offline";
2321ac4b82bSMike Smith 	break;
2331ac4b82bSMike Smith     default:
2341ac4b82bSMike Smith 	state = "unknown state";
2351ac4b82bSMike Smith     }
2361ac4b82bSMike Smith 
23797adfbafSMike Smith     device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n",
2381ac4b82bSMike Smith 		  sc->mlxd_drive->ms_size / ((1024 * 1024) / MLX_BLKSIZE),
2391ac4b82bSMike Smith 		  sc->mlxd_drive->ms_size, sc->mlxd_drive->ms_raidlevel, state);
2401ac4b82bSMike Smith 
2410b7ed341SPoul-Henning Kamp     sc->mlxd_disk = disk_alloc();
2420b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_open = mlxd_open;
2430b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_close = mlxd_close;
2440b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_ioctl = mlxd_ioctl;
2450b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_strategy = mlxd_strategy;
2460b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_name = "mlxd";
2470b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_unit = sc->mlxd_unit;
2480b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_drv1 = sc;
2490b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_sectorsize = MLX_BLKSIZE;
2500b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_mediasize = MLX_BLKSIZE * (off_t)sc->mlxd_drive->ms_size;
2510b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_fwsectors = sc->mlxd_drive->ms_sectors;
2520b7ed341SPoul-Henning Kamp     sc->mlxd_disk->d_fwheads = sc->mlxd_drive->ms_heads;
2531ac4b82bSMike Smith 
254baff09dbSMike Smith     /*
255baff09dbSMike Smith      * Set maximum I/O size to the lesser of the recommended maximum and the practical
256e1159d10SJohn Baldwin      * maximum except on v2 cards where the maximum is set to 8 pages.
257baff09dbSMike Smith      */
258e1159d10SJohn Baldwin     if (sc->mlxd_controller->mlx_iftype == MLX_IFTYPE_2)
2594161b1a1SScott Long 	sc->mlxd_disk->d_maxsize = 8 * MLX_PAGE_SIZE;
260e1159d10SJohn Baldwin     else {
261baff09dbSMike Smith 	s1 = sc->mlxd_controller->mlx_enq2->me_maxblk * MLX_BLKSIZE;
2624161b1a1SScott Long 	s2 = (sc->mlxd_controller->mlx_enq2->me_max_sg - 1) * MLX_PAGE_SIZE;
2630b7ed341SPoul-Henning Kamp 	sc->mlxd_disk->d_maxsize = imin(s1, s2);
264e1159d10SJohn Baldwin     }
265b2fe65c5SPoul-Henning Kamp 
2660b7ed341SPoul-Henning Kamp     disk_create(sc->mlxd_disk, DISK_VERSION);
267f6b84b08SMike Smith 
2681ac4b82bSMike Smith     return (0);
2691ac4b82bSMike Smith }
2701ac4b82bSMike Smith 
2711ac4b82bSMike Smith static int
mlxd_detach(device_t dev)2721ac4b82bSMike Smith mlxd_detach(device_t dev)
2731ac4b82bSMike Smith {
2741ac4b82bSMike Smith     struct mlxd_softc *sc = (struct mlxd_softc *)device_get_softc(dev);
2751ac4b82bSMike Smith 
276da8bb3a3SMike Smith     debug_called(1);
2771ac4b82bSMike Smith 
2780b7ed341SPoul-Henning Kamp     disk_destroy(sc->mlxd_disk);
2791ac4b82bSMike Smith 
2801ac4b82bSMike Smith     return(0);
2811ac4b82bSMike Smith }
2821ac4b82bSMike Smith 
283