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 59249 2000-04-15 05:54:02Z 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
88/* configuration flags */
89#define FDC_PRETEND_D0 (1 << 0) /* pretend drive 0 to be there */
90#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */
91
92/* internally used only, not really from CMOS: */
93#define RTCFDT_144M_PRETENDED 0x1000
94

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

--- 122 unchanged lines hidden ---