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 --- |