Deleted Added
sdiff udiff text old ( 58934 ) new ( 59249 )
full compact
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Don Ahn.
7 *
8 * Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu)

--- 33 unchanged lines hidden (view full) ---

42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 *
49 * from: @(#)fd.c 7.4 (Berkeley) 5/25/91
50 * $FreeBSD: head/sys/dev/fdc/fdc.c 58934 2000-04-02 15:24:56Z phk $
51 *
52 */
53
54#include "opt_fdc.h"
55#include "card.h"
56
57#include <sys/param.h>
58#include <sys/systm.h>

--- 20 unchanged lines hidden (view full) ---

79
80#include <isa/isavar.h>
81#include <isa/isareg.h>
82#include <isa/fdreg.h>
83#include <isa/fdc.h>
84#include <isa/rtc.h>
85
86/* misuse a flag to identify format operation */
87#define B_FORMAT B_XXX
88
89/* configuration flags */
90#define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */
91#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */
92
93/* internally used only, not really from CMOS: */
94#define RTCFDT_144M_PRETENDED 0x1000
95

--- 762 unchanged lines hidden (view full) ---

858 /* XXX should integrate with rman */
859 isa_dma_acquire(fdc->dmachan);
860 isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */);
861 }
862 fdc->state = DEVIDLE;
863
864 /* reset controller, turn motor off, clear fdout mirror reg */
865 fdout_wr(fdc, ((fdc->fdout = 0)));
866 bufq_init(&fdc->head);
867
868 /*
869 * Probe and attach any children. We should probably detect
870 * devices from the BIOS unless overridden.
871 */
872 for (i = resource_query_string(-1, "at", device_get_nameunit(dev));
873 i != -1;
874 i = resource_query_string(i, "at", device_get_nameunit(dev)))

--- 567 unchanged lines hidden (view full) ---

1442
1443 return (0);
1444}
1445
1446/****************************************************************************/
1447/* fdstrategy */
1448/****************************************************************************/
1449void
1450fdstrategy(struct buf *bp)
1451{
1452 unsigned nblocks, blknum, cando;
1453 int s;
1454 fdu_t fdu;
1455 fdc_p fdc;
1456 fd_p fd;
1457 size_t fdblk;
1458
1459 fdu = FDUNIT(minor(bp->b_dev));
1460 fd = devclass_get_softc(fd_devclass, fdu);
1461 if (fd == 0)
1462 panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)",
1463 (u_long)major(bp->b_dev), (u_long)minor(bp->b_dev));
1464 fdc = fd->fdc;
1465 if (fd->type == NO_TYPE) {
1466 bp->b_error = ENXIO;
1467 bp->b_ioflags |= BIO_ERROR;
1468 goto bad;
1469 };
1470
1471 fdblk = 128 << (fd->ft->secsize);
1472 if (!(bp->b_flags & B_FORMAT)) {
1473 if (bp->b_blkno < 0) {
1474 printf(
1475 "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n",
1476 fdu, (u_long)bp->b_blkno, bp->b_bcount);
1477 bp->b_error = EINVAL;
1478 bp->b_ioflags |= BIO_ERROR;
1479 goto bad;
1480 }
1481 if ((bp->b_bcount % fdblk) != 0) {
1482 bp->b_error = EINVAL;
1483 bp->b_ioflags |= BIO_ERROR;
1484 goto bad;
1485 }
1486 }
1487
1488 /*
1489 * Set up block calculations.
1490 */
1491 if (bp->b_blkno > 20000000) {
1492 /*
1493 * Reject unreasonably high block number, prevent the
1494 * multiplication below from overflowing.
1495 */
1496 bp->b_error = EINVAL;
1497 bp->b_ioflags |= BIO_ERROR;
1498 goto bad;
1499 }
1500 blknum = (unsigned) bp->b_blkno * DEV_BSIZE/fdblk;
1501 nblocks = fd->ft->size;
1502 bp->b_resid = 0;
1503 if (blknum + (bp->b_bcount / fdblk) > nblocks) {
1504 if (blknum <= nblocks) {
1505 cando = (nblocks - blknum) * fdblk;
1506 bp->b_resid = bp->b_bcount - cando;
1507 if (cando == 0)
1508 goto bad; /* not actually bad but EOF */
1509 } else {
1510 bp->b_error = EINVAL;
1511 bp->b_ioflags |= BIO_ERROR;
1512 goto bad;
1513 }
1514 }
1515 bp->b_pblkno = bp->b_blkno;
1516 s = splbio();
1517 bufqdisksort(&fdc->head, bp);
1518 untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */
1519
1520 /* Tell devstat we are starting on the transaction */
1521 devstat_start_transaction(&fd->device_stats);
1522 device_busy(fd->dev);
1523
1524 fdstart(fdc);
1525 splx(s);

--- 116 unchanged lines hidden (view full) ---

1642\***********************************************************************/
1643static int
1644fdstate(fdc_p fdc)
1645{
1646 int read, format, head, i, sec = 0, sectrac, st0, cyl, st3, idf;
1647 unsigned blknum = 0, b_cylinder = 0;
1648 fdu_t fdu = fdc->fdu;
1649 fd_p fd;
1650 register struct buf *bp;
1651 struct fd_formb *finfo = NULL;
1652 size_t fdblk;
1653
1654 bp = fdc->bp;
1655 if (bp == NULL) {
1656 bp = bufq_first(&fdc->head);
1657 if (bp != NULL) {
1658 bufq_remove(&fdc->head, bp);
1659 fdc->bp = bp;
1660 }
1661 }
1662 if (bp == NULL) {
1663 /***********************************************\
1664 * nothing left for this controller to do *
1665 * Force into the IDLE state, *
1666 \***********************************************/
1667 fdc->state = DEVIDLE;
1668 if (fdc->fd) {
1669 device_printf(fdc->fdc_dev,
1670 "unexpected valid fd pointer\n");
1671 fdc->fd = (fd_p) 0;
1672 fdc->fdu = -1;
1673 }
1674 TRACE1("[fdc%d IDLE]", fdc->fdcu);
1675 return (0);
1676 }
1677 fdu = FDUNIT(minor(bp->b_dev));
1678 fd = devclass_get_softc(fd_devclass, fdu);
1679 fdblk = 128 << fd->ft->secsize;
1680 if (fdc->fd && (fd != fdc->fd))
1681 device_printf(fd->dev, "confused fd pointers\n");
1682 read = bp->b_iocmd == BIO_READ;
1683 if (read)
1684 idf = ISADMA_READ;
1685 else
1686 idf = ISADMA_WRITE;
1687 format = bp->b_flags & B_FORMAT;
1688 if (format) {
1689 finfo = (struct fd_formb *)bp->b_data;
1690 fd->skip = (char *)&(finfo->fd_formb_cylno(0))
1691 - (char *)finfo;
1692 }
1693 if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) {
1694 blknum = (unsigned) bp->b_pblkno * DEV_BSIZE/fdblk +
1695 fd->skip/fdblk;
1696 b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
1697 }
1698 TRACE1("fd%d", fdu);
1699 TRACE1("[%s]", fdstates[fdc->state]);
1700 TRACE1("(0x%x)", fd->flags);
1701 untimeout(fd_turnoff, fd, fd->toffhandle);
1702 fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz);

--- 122 unchanged lines hidden (view full) ---

1825 if (fdc->retry < 3)
1826 fdc->retry = 3;
1827 return (retrier(fdc));
1828 }
1829 }
1830
1831 fd->track = b_cylinder;
1832 if (!(fdc->flags & FDC_NODMA))
1833 isa_dmastart(idf, bp->b_data+fd->skip,
1834 format ? bp->b_bcount : fdblk, fdc->dmachan);
1835 sectrac = fd->ft->sectrac;
1836 sec = blknum % (sectrac * fd->ft->heads);
1837 head = sec / sectrac;
1838 sec = sec % sectrac + 1;
1839 fd->hddrv = ((head&1)<<2)+fdu;
1840
1841 if(format || !read)
1842 {
1843 /* make sure the drive is writable */
1844 if(fd_sense_drive_status(fdc, &st3) != 0)
1845 {
1846 /* stuck controller? */
1847 if (!(fdc->flags & FDC_NODMA))
1848 isa_dmadone(idf,
1849 bp->b_data + fd->skip,
1850 format ? bp->b_bcount : fdblk,
1851 fdc->dmachan);
1852 fdc->retry = 6; /* reset the beast */
1853 return (retrier(fdc));
1854 }
1855 if(st3 & NE7_ST3_WP)
1856 {
1857 /*
1858 * XXX YES! this is ugly.

--- 23 unchanged lines hidden (view full) ---

1882 * fields of the newly formatted track
1883 * entirely with garbage, causing
1884 * `wrong cylinder' errors all over
1885 * the place when trying to read them
1886 * back.
1887 *
1888 * Umpf.
1889 */
1890 SET_BCDR(fdc, 1, bp->b_bcount, 0);
1891
1892 (void)fdcpio(fdc,bp->b_iocmd,
1893 bp->b_data+fd->skip,
1894 bp->b_bcount);
1895
1896 }
1897 /* formatting */
1898 if(fd_cmd(fdc, 6, NE7CMD_FORMAT, head << 2 | fdu,
1899 finfo->fd_formb_secshift,
1900 finfo->fd_formb_nsecs,
1901 finfo->fd_formb_gaplen,
1902 finfo->fd_formb_fillbyte, 0)) {
1903 /* controller fell over */
1904 if (!(fdc->flags & FDC_NODMA))
1905 isa_dmadone(idf,
1906 bp->b_data + fd->skip,
1907 format ? bp->b_bcount : fdblk,
1908 fdc->dmachan);
1909 fdc->retry = 6;
1910 return (retrier(fdc));
1911 }
1912 } else {
1913 if (fdc->flags & FDC_NODMA) {
1914 /*
1915 * this seems to be necessary even when
1916 * reading data
1917 */
1918 SET_BCDR(fdc, 1, fdblk, 0);
1919
1920 /*
1921 * perform the write pseudo-DMA before
1922 * the WRITE command is sent
1923 */
1924 if (!read)
1925 (void)fdcpio(fdc,bp->b_iocmd,
1926 bp->b_data+fd->skip,
1927 fdblk);
1928 }
1929 if (fd_cmd(fdc, 9,
1930 (read ? NE7CMD_READ : NE7CMD_WRITE),
1931 head << 2 | fdu, /* head & unit */
1932 fd->track, /* track */
1933 head,
1934 sec, /* sector + 1 */
1935 fd->ft->secsize, /* sector size */
1936 sectrac, /* sectors/track */
1937 fd->ft->gap, /* gap size */
1938 fd->ft->datalen, /* data length */
1939 0)) {
1940 /* the beast is sleeping again */
1941 if (!(fdc->flags & FDC_NODMA))
1942 isa_dmadone(idf,
1943 bp->b_data + fd->skip,
1944 format ? bp->b_bcount : fdblk,
1945 fdc->dmachan);
1946 fdc->retry = 6;
1947 return (retrier(fdc));
1948 }
1949 }
1950 if (fdc->flags & FDC_NODMA)
1951 /*
1952 * if this is a read, then simply await interrupt
1953 * before performing PIO
1954 */
1955 if (read && !fdcpio(fdc,bp->b_iocmd,
1956 bp->b_data+fd->skip,fdblk)) {
1957 fd->tohandle = timeout(fd_iotimeout, fdc, hz);
1958 return(0); /* will return later */
1959 };
1960
1961 /*
1962 * write (or format) operation will fall through and
1963 * await completion interrupt
1964 */
1965 fdc->state = IOCOMPLETE;
1966 fd->tohandle = timeout(fd_iotimeout, fdc, hz);
1967 return (0); /* will return later */
1968 case PIOREAD:
1969 /*
1970 * actually perform the PIO read. The IOCOMPLETE case
1971 * removes the timeout for us.
1972 */
1973 (void)fdcpio(fdc,bp->b_iocmd,bp->b_data+fd->skip,fdblk);
1974 fdc->state = IOCOMPLETE;
1975 /* FALLTHROUGH */
1976 case IOCOMPLETE: /* IO DONE, post-analyze */
1977 untimeout(fd_iotimeout, fdc, fd->tohandle);
1978
1979 if (fd_read_status(fdc, fd->fdsu)) {
1980 if (!(fdc->flags & FDC_NODMA))
1981 isa_dmadone(idf, bp->b_data + fd->skip,
1982 format ? bp->b_bcount : fdblk,
1983 fdc->dmachan);
1984 if (fdc->retry < 6)
1985 fdc->retry = 6; /* force a reset */
1986 return (retrier(fdc));
1987 }
1988
1989 fdc->state = IOTIMEDOUT;
1990
1991 /* FALLTHROUGH */
1992
1993 case IOTIMEDOUT:
1994 if (!(fdc->flags & FDC_NODMA))
1995 isa_dmadone(idf, bp->b_data + fd->skip,
1996 format ? bp->b_bcount : fdblk, fdc->dmachan);
1997 if (fdc->status[0] & NE7_ST0_IC) {
1998 if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
1999 && fdc->status[1] & NE7_ST1_OR) {
2000 /*
2001 * DMA overrun. Someone hogged the bus
2002 * and didn't release it in time for the
2003 * next FDC transfer.
2004 * Just restart it, don't increment retry

--- 8 unchanged lines hidden (view full) ---

2013 else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
2014 && fdc->status[2] & NE7_ST2_WC
2015 && fdc->retry < 3)
2016 fdc->retry = 3; /* force recalibrate */
2017 return (retrier(fdc));
2018 }
2019 /* All OK */
2020 fd->skip += fdblk;
2021 if (!format && fd->skip < bp->b_bcount - bp->b_resid) {
2022 /* set up next transfer */
2023 fdc->state = DOSEEK;
2024 } else {
2025 /* ALL DONE */
2026 fd->skip = 0;
2027 fdc->bp = NULL;
2028 device_unbusy(fd->dev);
2029 devstat_end_transaction_buf(&fd->device_stats, bp);
2030 biodone(bp);
2031 fdc->fd = (fd_p) 0;
2032 fdc->fdu = -1;
2033 fdc->state = FINDWORK;
2034 }
2035 return (1);
2036 case RESETCTLR:
2037 fdc_reset(fdc);

--- 94 unchanged lines hidden (view full) ---

2132 }
2133 /*XXX confusing: some branches return immediately, others end up here*/
2134 return (1); /* Come back immediatly to new state */
2135}
2136
2137static int
2138retrier(struct fdc_data *fdc)
2139{
2140 register struct buf *bp;
2141 struct fd_data *fd;
2142 int fdu;
2143
2144 bp = fdc->bp;
2145
2146 /* XXX shouldn't this be cached somewhere? */
2147 fdu = FDUNIT(minor(bp->b_dev));
2148 fd = devclass_get_softc(fd_devclass, fdu);
2149 if (fd->options & FDOPT_NORETRY)
2150 goto fail;
2151
2152 switch (fdc->retry) {
2153 case 0: case 1: case 2:
2154 fdc->state = SEEKCOMPLETE;
2155 break;
2156 case 3: case 4: case 5:
2157 fdc->state = STARTRECAL;
2158 break;
2159 case 6:
2160 fdc->state = RESETCTLR;
2161 break;
2162 case 7:
2163 break;
2164 default:
2165 fail:
2166 {
2167 dev_t sav_b_dev = bp->b_dev;
2168 /* Trick diskerr */
2169 bp->b_dev = makedev(major(bp->b_dev),
2170 (FDUNIT(minor(bp->b_dev))<<3)|RAW_PART);
2171 diskerr(bp, "hard error", LOG_PRINTF,
2172 fdc->fd->skip / DEV_BSIZE,
2173 (struct disklabel *)NULL);
2174 bp->b_dev = sav_b_dev;
2175 if (fdc->flags & FDC_STAT_VALID)
2176 {
2177 printf(
2178 " (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n",
2179 fdc->status[0], NE7_ST0BITS,
2180 fdc->status[1], NE7_ST1BITS,
2181 fdc->status[2], NE7_ST2BITS,
2182 fdc->status[3], fdc->status[4],
2183 fdc->status[5]);
2184 }
2185 else
2186 printf(" (No status)\n");
2187 }
2188 bp->b_ioflags |= BIO_ERROR;
2189 bp->b_error = EIO;
2190 bp->b_resid += bp->b_bcount - fdc->fd->skip;
2191 fdc->bp = NULL;
2192 fdc->fd->skip = 0;
2193 device_unbusy(fd->dev);
2194 devstat_end_transaction_buf(&fdc->fd->device_stats, bp);
2195 biodone(bp);
2196 fdc->state = FINDWORK;
2197 fdc->flags |= FDC_NEEDS_RESET;
2198 fdc->fd = (fd_p) 0;
2199 fdc->fdu = -1;
2200 return (1);
2201 }
2202 fdc->retry++;

--- 23 unchanged lines hidden (view full) ---

2226 return ENOBUFS;
2227 /*
2228 * keep the process from being swapped
2229 */
2230 PHOLD(p);
2231 bzero((void *)bp, sizeof(struct buf));
2232 BUF_LOCKINIT(bp);
2233 BUF_LOCK(bp, LK_EXCLUSIVE);
2234 bp->b_flags = B_PHYS | B_FORMAT;
2235 bp->b_iocmd = BIO_WRITE;
2236
2237 /*
2238 * calculate a fake blkno, so fdstrategy() would initiate a
2239 * seek to the requested cylinder
2240 */
2241 bp->b_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads)
2242 + finfo->head * fd->ft->sectrac) * fdblk / DEV_BSIZE;
2243

--- 12 unchanged lines hidden (view full) ---

2256 break;
2257 }
2258 splx(s);
2259
2260 if (rv == EWOULDBLOCK) {
2261 /* timed out */
2262 rv = EIO;
2263 device_unbusy(fd->dev);
2264 biodone(bp);
2265 }
2266 if (bp->b_ioflags & BIO_ERROR)
2267 rv = bp->b_error;
2268 /*
2269 * allow the process to be swapped
2270 */
2271 PRELE(p);
2272 BUF_UNLOCK(bp);

--- 122 unchanged lines hidden ---