mlx.c (52439) | mlx.c (52544) |
---|---|
1/*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 52439 1999-10-22 20:55:15Z msmith $ | 26 * $FreeBSD: head/sys/dev/mlx/mlx.c 52544 1999-10-26 23:20:43Z msmith $ |
27 */ 28 29/* 30 * Driver for the Mylex DAC960 family of RAID controllers. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> --- 238 unchanged lines hidden (view full) --- 273 struct mlx_enquiry2 *me2; 274 int rid, error; 275 276 debug("called"); 277 278 /* 279 * Initialise per-controller queues. 280 */ | 27 */ 28 29/* 30 * Driver for the Mylex DAC960 family of RAID controllers. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> --- 238 unchanged lines hidden (view full) --- 273 struct mlx_enquiry2 *me2; 274 int rid, error; 275 276 debug("called"); 277 278 /* 279 * Initialise per-controller queues. 280 */ |
281 TAILQ_INIT(&sc->mlx_donecmd); | 281 TAILQ_INIT(&sc->mlx_work); |
282 TAILQ_INIT(&sc->mlx_freecmds); 283 bufq_init(&sc->mlx_bufq); 284 285 /* 286 * Select accessor methods based on controller interface type. 287 */ 288 switch(sc->mlx_iftype) { 289 case MLX_IFTYPE_3: --- 84 unchanged lines hidden (view full) --- 374 sc->mlx_nchan = me2->me_configured_channels; 375 sc->mlx_maxiosize = me2->me_maxblk; 376 sc->mlx_maxtarg = me2->me_max_targets; 377 sc->mlx_maxtags = me2->me_max_tags; 378 sc->mlx_scsicap = me2->me_scsi_cap; 379 sc->mlx_hwid = me2->me_hardware_id; 380 381 /* print a little information about the controller and ourselves */ | 282 TAILQ_INIT(&sc->mlx_freecmds); 283 bufq_init(&sc->mlx_bufq); 284 285 /* 286 * Select accessor methods based on controller interface type. 287 */ 288 switch(sc->mlx_iftype) { 289 case MLX_IFTYPE_3: --- 84 unchanged lines hidden (view full) --- 374 sc->mlx_nchan = me2->me_configured_channels; 375 sc->mlx_maxiosize = me2->me_maxblk; 376 sc->mlx_maxtarg = me2->me_max_targets; 377 sc->mlx_maxtags = me2->me_max_tags; 378 sc->mlx_scsicap = me2->me_scsi_cap; 379 sc->mlx_hwid = me2->me_hardware_id; 380 381 /* print a little information about the controller and ourselves */ |
382 device_printf(sc->mlx_dev, "Mylex %s, firmware %d.%d, %dMB RAM\n", | 382 device_printf(sc->mlx_dev, "Mylex %s, firmware %d.%02d, %dMB RAM\n", |
383 mlx_name_controller(sc->mlx_hwid), sc->mlx_fwmajor, sc->mlx_fwminor, 384 me2->me_mem_size / (1024 * 1024)); 385 free(me2, M_DEVBUF); 386 387 /* 388 * Do quirk/feature related things. 389 */ 390 switch(sc->mlx_iftype) { 391 case MLX_IFTYPE_3: 392 /* XXX certify 3.52? */ | 383 mlx_name_controller(sc->mlx_hwid), sc->mlx_fwmajor, sc->mlx_fwminor, 384 me2->me_mem_size / (1024 * 1024)); 385 free(me2, M_DEVBUF); 386 387 /* 388 * Do quirk/feature related things. 389 */ 390 switch(sc->mlx_iftype) { 391 case MLX_IFTYPE_3: 392 /* XXX certify 3.52? */ |
393 if (sc->mlx_fwminor != 51) { 394 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is NOT SUPPORTED\n"); 395 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 only\n"); | 393 if (sc->mlx_fwminor < 51) { 394 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 395 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n"); |
396 } 397 break; 398 case MLX_IFTYPE_4: 399 /* XXX certify firmware versions? */ | 396 } 397 break; 398 case MLX_IFTYPE_4: 399 /* XXX certify firmware versions? */ |
400 if (sc->mlx_fwminor != 6) { 401 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is NOT SUPPORTED\n"); 402 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.6 only\n"); | 400 if (sc->mlx_fwminor < 6) { 401 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 402 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n"); |
403 } 404 break; 405 default: 406 device_printf(sc->mlx_dev, "interface version corrupted to %d\n", sc->mlx_iftype); 407 return(ENXIO); /* should never happen */ 408 } 409 410 /* --- 237 unchanged lines hidden (view full) --- 648 649/******************************************************************************* 650 * Receive a buf structure from a child device and queue it on a particular 651 * disk resource, then poke the disk resource to start as much work as it can. 652 */ 653int 654mlx_submit_buf(struct mlx_softc *sc, struct buf *bp) 655{ | 403 } 404 break; 405 default: 406 device_printf(sc->mlx_dev, "interface version corrupted to %d\n", sc->mlx_iftype); 407 return(ENXIO); /* should never happen */ 408 } 409 410 /* --- 237 unchanged lines hidden (view full) --- 648 649/******************************************************************************* 650 * Receive a buf structure from a child device and queue it on a particular 651 * disk resource, then poke the disk resource to start as much work as it can. 652 */ 653int 654mlx_submit_buf(struct mlx_softc *sc, struct buf *bp) 655{ |
656 int s; 657 |
|
656 debug("called"); 657 | 658 debug("called"); 659 |
660 s = splbio(); |
|
658 bufq_insert_tail(&sc->mlx_bufq, bp); 659 sc->mlx_waitbufs++; | 661 bufq_insert_tail(&sc->mlx_bufq, bp); 662 sc->mlx_waitbufs++; |
663 splx(s); |
|
660 mlx_startio(sc); 661 return(0); 662} 663 664/******************************************************************************** 665 * Accept an open operation on the control device. 666 */ 667int --- 884 unchanged lines hidden (view full) --- 1552 1553 count = 0; 1554 do { 1555 /* poll for completion */ 1556 mlx_done(mc->mc_sc); 1557 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000)); 1558 if (mc->mc_status != MLX_STATUS_BUSY) { 1559 s = splbio(); | 664 mlx_startio(sc); 665 return(0); 666} 667 668/******************************************************************************** 669 * Accept an open operation on the control device. 670 */ 671int --- 884 unchanged lines hidden (view full) --- 1556 1557 count = 0; 1558 do { 1559 /* poll for completion */ 1560 mlx_done(mc->mc_sc); 1561 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 10000)); 1562 if (mc->mc_status != MLX_STATUS_BUSY) { 1563 s = splbio(); |
1560 TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link); | 1564 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); |
1561 splx(s); 1562 return(0); 1563 } 1564 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status); 1565 return(EIO); 1566} 1567 1568/******************************************************************************** --- 7 unchanged lines hidden (view full) --- 1576mlx_startio(struct mlx_softc *sc) 1577{ 1578 struct mlx_command *mc; 1579 struct mlxd_softc *mlxd; 1580 struct buf *bp; 1581 int blkcount; 1582 int driveno; 1583 int cmd; | 1565 splx(s); 1566 return(0); 1567 } 1568 device_printf(sc->mlx_dev, "I/O error 0x%x\n", mc->mc_status); 1569 return(EIO); 1570} 1571 1572/******************************************************************************** --- 7 unchanged lines hidden (view full) --- 1580mlx_startio(struct mlx_softc *sc) 1581{ 1582 struct mlx_command *mc; 1583 struct mlxd_softc *mlxd; 1584 struct buf *bp; 1585 int blkcount; 1586 int driveno; 1587 int cmd; |
1588 int s; |
|
1584 1585 /* spin until something prevents us from doing any work */ | 1589 1590 /* spin until something prevents us from doing any work */ |
1591 s = splbio(); |
|
1586 for (;;) { 1587 1588 /* see if there's work to be done */ 1589 if ((bp = bufq_first(&sc->mlx_bufq)) == NULL) 1590 break; 1591 /* get a command */ 1592 if ((mc = mlx_alloccmd(sc)) == NULL) 1593 break; 1594 /* get a slot for the command */ 1595 if (mlx_getslot(mc) != 0) { 1596 mlx_releasecmd(mc); 1597 break; 1598 } 1599 /* get the buf containing our work */ 1600 bufq_remove(&sc->mlx_bufq, bp); 1601 sc->mlx_waitbufs--; | 1592 for (;;) { 1593 1594 /* see if there's work to be done */ 1595 if ((bp = bufq_first(&sc->mlx_bufq)) == NULL) 1596 break; 1597 /* get a command */ 1598 if ((mc = mlx_alloccmd(sc)) == NULL) 1599 break; 1600 /* get a slot for the command */ 1601 if (mlx_getslot(mc) != 0) { 1602 mlx_releasecmd(mc); 1603 break; 1604 } 1605 /* get the buf containing our work */ 1606 bufq_remove(&sc->mlx_bufq, bp); 1607 sc->mlx_waitbufs--; |
1608 splx(s); |
|
1602 1603 /* connect the buf to the command */ 1604 mc->mc_complete = mlx_completeio; 1605 mc->mc_private = bp; 1606 mc->mc_data = bp->b_data; 1607 mc->mc_length = bp->b_bcount; 1608 if (bp->b_flags & B_READ) { 1609 mc->mc_flags |= MLX_CMD_DATAIN; --- 28 unchanged lines hidden (view full) --- 1638 1639 1640 /* try to give command to controller */ 1641 if (mlx_start(mc) != 0) { 1642 /* fail the command */ 1643 mc->mc_status = MLX_STATUS_WEDGED; 1644 mlx_completeio(mc); 1645 } | 1609 1610 /* connect the buf to the command */ 1611 mc->mc_complete = mlx_completeio; 1612 mc->mc_private = bp; 1613 mc->mc_data = bp->b_data; 1614 mc->mc_length = bp->b_bcount; 1615 if (bp->b_flags & B_READ) { 1616 mc->mc_flags |= MLX_CMD_DATAIN; --- 28 unchanged lines hidden (view full) --- 1645 1646 1647 /* try to give command to controller */ 1648 if (mlx_start(mc) != 0) { 1649 /* fail the command */ 1650 mc->mc_status = MLX_STATUS_WEDGED; 1651 mlx_completeio(mc); 1652 } |
1653 s = splbio(); |
|
1646 } | 1654 } |
1655 splx(s); |
|
1647} 1648 1649/******************************************************************************** 1650 * Handle completion of an I/O command. 1651 */ 1652static void 1653mlx_completeio(struct mlx_command *mc) 1654{ --- 221 unchanged lines hidden (view full) --- 1876 struct mlx_softc *sc = mc->mc_sc; 1877 int i, s, done, worked; 1878 1879 debug("called"); 1880 1881 /* save the slot number as ident so we can handle this command when complete */ 1882 mc->mc_mailbox[0x1] = mc->mc_slot; 1883 | 1656} 1657 1658/******************************************************************************** 1659 * Handle completion of an I/O command. 1660 */ 1661static void 1662mlx_completeio(struct mlx_command *mc) 1663{ --- 221 unchanged lines hidden (view full) --- 1885 struct mlx_softc *sc = mc->mc_sc; 1886 int i, s, done, worked; 1887 1888 debug("called"); 1889 1890 /* save the slot number as ident so we can handle this command when complete */ 1891 mc->mc_mailbox[0x1] = mc->mc_slot; 1892 |
1884 /* set impossible status so that a woken sleeper can tell the command is in progress */ | 1893 /* mark the command as currently being processed */ |
1885 mc->mc_status = MLX_STATUS_BUSY; 1886 1887 /* assume we don't collect any completed commands */ 1888 worked = 0; 1889 1890 /* spin waiting for the mailbox */ 1891 for (i = 100000, done = 0; (i > 0) && !done; i--) { 1892 s = splbio(); | 1894 mc->mc_status = MLX_STATUS_BUSY; 1895 1896 /* assume we don't collect any completed commands */ 1897 worked = 0; 1898 1899 /* spin waiting for the mailbox */ 1900 for (i = 100000, done = 0; (i > 0) && !done; i--) { 1901 s = splbio(); |
1893 done = sc->mlx_tryqueue(sc, mc); | 1902 if (sc->mlx_tryqueue(sc, mc)) { 1903 done = 1; 1904 /* move command to work queue */ 1905 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link); 1906 } |
1894 splx(s); 1895 /* check for command completion while we're at it */ 1896 if (mlx_done(sc)) 1897 worked = 1; 1898 } 1899 /* check to see if we picked up any completed commands */ 1900 if (worked) 1901 mlx_complete(sc); --- 24 unchanged lines hidden (view full) --- 1926{ 1927 struct mlx_command *mc; 1928 int s; 1929 u_int8_t slot; 1930 u_int16_t status; 1931 1932 debug("called"); 1933 | 1907 splx(s); 1908 /* check for command completion while we're at it */ 1909 if (mlx_done(sc)) 1910 worked = 1; 1911 } 1912 /* check to see if we picked up any completed commands */ 1913 if (worked) 1914 mlx_complete(sc); --- 24 unchanged lines hidden (view full) --- 1939{ 1940 struct mlx_command *mc; 1941 int s; 1942 u_int8_t slot; 1943 u_int16_t status; 1944 1945 debug("called"); 1946 |
1934 s = splbio(); | |
1935 mc = NULL; 1936 slot = 0; 1937 1938 /* poll for a completed command's identifier and status */ | 1947 mc = NULL; 1948 slot = 0; 1949 1950 /* poll for a completed command's identifier and status */ |
1951 s = splbio(); |
|
1939 if (sc->mlx_findcomplete(sc, &slot, &status)) { | 1952 if (sc->mlx_findcomplete(sc, &slot, &status)) { |
1940 mc = sc->mlx_busycmd[slot]; /* find command */ 1941 if (mc != NULL) { /* paranoia */ | 1953 mc = sc->mlx_busycmd[slot]; /* find command */ 1954 if (mc != NULL) { /* paranoia */ |
1942 if (mc->mc_status == MLX_STATUS_BUSY) { 1943 mc->mc_status = status; /* save status */ 1944 | 1955 if (mc->mc_status == MLX_STATUS_BUSY) { 1956 mc->mc_status = status; /* save status */ 1957 |
1945 /* move completed command to 'done' queue */ 1946 TAILQ_INSERT_TAIL(&sc->mlx_donecmd, mc, mc_link); 1947 | |
1948 /* free slot for reuse */ 1949 sc->mlx_busycmd[slot] = NULL; 1950 sc->mlx_busycmds--; 1951 } else { 1952 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot); 1953 mc = NULL; 1954 } 1955 } else { --- 20 unchanged lines hidden (view full) --- 1976 int s, count; 1977 1978 debug("called"); 1979 1980 s = splbio(); 1981 count = 0; 1982 1983 /* scan the list of done commands */ | 1958 /* free slot for reuse */ 1959 sc->mlx_busycmd[slot] = NULL; 1960 sc->mlx_busycmds--; 1961 } else { 1962 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot); 1963 mc = NULL; 1964 } 1965 } else { --- 20 unchanged lines hidden (view full) --- 1986 int s, count; 1987 1988 debug("called"); 1989 1990 s = splbio(); 1991 count = 0; 1992 1993 /* scan the list of done commands */ |
1984 mc = TAILQ_FIRST(&sc->mlx_donecmd); | 1994 mc = TAILQ_FIRST(&sc->mlx_work); |
1985 while (mc != NULL) { 1986 nc = TAILQ_NEXT(mc, mc_link); 1987 1988 /* XXX this is slightly bogus */ 1989 if (count++ > (sc->mlx_maxiop * 2)) | 1995 while (mc != NULL) { 1996 nc = TAILQ_NEXT(mc, mc_link); 1997 1998 /* XXX this is slightly bogus */ 1999 if (count++ > (sc->mlx_maxiop * 2)) |
1990 panic("mlx_donecmd list corrupt!"); | 2000 panic("mlx_work list corrupt!"); |
1991 | 2001 |
1992 /* | 2002 /* Skip commands that are still busy */ 2003 if (mc->mc_status != MLX_STATUS_BUSY) { 2004 2005 2006 /* |
1993 * Does the command have a completion handler? 1994 */ | 2007 * Does the command have a completion handler? 2008 */ |
1995 if (mc->mc_complete != NULL) { 1996 /* remove from list and give to handler */ 1997 TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link); 1998 mc->mc_complete(mc); | 2009 if (mc->mc_complete != NULL) { 2010 /* remove from list and give to handler */ 2011 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); 2012 mc->mc_complete(mc); |
1999 | 2013 |
2000 /* 2001 * Is there a sleeper waiting on this command? 2002 */ 2003 } else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */ | 2014 /* 2015 * Is there a sleeper waiting on this command? 2016 */ 2017 } else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */ |
2004 | 2018 |
2005 /* remove from list and wake up sleeper */ 2006 TAILQ_REMOVE(&sc->mlx_donecmd, mc, mc_link); 2007 wakeup_one(mc->mc_private); | 2019 /* remove from list and wake up sleeper */ 2020 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); 2021 wakeup_one(mc->mc_private); |
2008 | 2022 |
2009 /* 2010 * Leave the command for a caller that's polling for it. 2011 */ 2012 } else { | 2023 /* 2024 * Leave the command for a caller that's polling for it. 2025 */ 2026 } else { 2027 } |
2013 } 2014 mc = nc; 2015 } 2016 splx(s); 2017 2018 /* queue some more work if there is any */ 2019 mlx_startio(sc); 2020} --- 330 unchanged lines hidden (view full) --- 2351 submodel = "PL"; 2352 break; 2353 case 0x10: 2354 submodel = "PG"; 2355 break; 2356 case 0x11: 2357 submodel = "PJ"; 2358 break; | 2028 } 2029 mc = nc; 2030 } 2031 splx(s); 2032 2033 /* queue some more work if there is any */ 2034 mlx_startio(sc); 2035} --- 330 unchanged lines hidden (view full) --- 2366 submodel = "PL"; 2367 break; 2368 case 0x10: 2369 submodel = "PG"; 2370 break; 2371 case 0x11: 2372 submodel = "PJ"; 2373 break; |
2374 case 0x16: 2375 submodel = "PTL"; 2376 break; |
|
2359 default: 2360 sprintf(smbuf, " model 0x%x", hwid & 0xff); 2361 submodel = smbuf; 2362 break; 2363 } 2364 nchn = (hwid >> 8) & 0xff; 2365 sprintf(buf, "DAC960%s, %d channel%s", submodel, nchn, nchn > 1 ? "s" : ""); 2366 return(buf); --- 27 unchanged lines hidden --- | 2377 default: 2378 sprintf(smbuf, " model 0x%x", hwid & 0xff); 2379 submodel = smbuf; 2380 break; 2381 } 2382 nchn = (hwid >> 8) & 0xff; 2383 sprintf(buf, "DAC960%s, %d channel%s", submodel, nchn, nchn > 1 ? "s" : ""); 2384 return(buf); --- 27 unchanged lines hidden --- |