18c5c0470SJoerg Sonnenberger /*
28c5c0470SJoerg Sonnenberger * Copyright (c) 1990 The Regents of the University of California.
38c5c0470SJoerg Sonnenberger * All rights reserved.
48c5c0470SJoerg Sonnenberger *
58c5c0470SJoerg Sonnenberger * This code is derived from software contributed to Berkeley by
68c5c0470SJoerg Sonnenberger * Don Ahn.
78c5c0470SJoerg Sonnenberger *
88c5c0470SJoerg Sonnenberger * Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu)
98c5c0470SJoerg Sonnenberger * aided by the Linux floppy driver modifications from David Bateman
108c5c0470SJoerg Sonnenberger * (dbateman@eng.uts.edu.au).
118c5c0470SJoerg Sonnenberger *
128c5c0470SJoerg Sonnenberger * Copyright (c) 1993, 1994 by
138c5c0470SJoerg Sonnenberger * jc@irbs.UUCP (John Capo)
148c5c0470SJoerg Sonnenberger * vak@zebub.msk.su (Serge Vakulenko)
158c5c0470SJoerg Sonnenberger * ache@astral.msk.su (Andrew A. Chernov)
168c5c0470SJoerg Sonnenberger *
178c5c0470SJoerg Sonnenberger * Copyright (c) 1993, 1994, 1995 by
188c5c0470SJoerg Sonnenberger * joerg_wunsch@uriah.sax.de (Joerg Wunsch)
198c5c0470SJoerg Sonnenberger * dufault@hda.com (Peter Dufault)
208c5c0470SJoerg Sonnenberger *
218c5c0470SJoerg Sonnenberger * Copyright (c) 2001 Joerg Wunsch,
228c5c0470SJoerg Sonnenberger * joerg_wunsch@uriah.sax.de (Joerg Wunsch)
238c5c0470SJoerg Sonnenberger *
248c5c0470SJoerg Sonnenberger * Redistribution and use in source and binary forms, with or without
258c5c0470SJoerg Sonnenberger * modification, are permitted provided that the following conditions
268c5c0470SJoerg Sonnenberger * are met:
278c5c0470SJoerg Sonnenberger * 1. Redistributions of source code must retain the above copyright
288c5c0470SJoerg Sonnenberger * notice, this list of conditions and the following disclaimer.
298c5c0470SJoerg Sonnenberger * 2. Redistributions in binary form must reproduce the above copyright
308c5c0470SJoerg Sonnenberger * notice, this list of conditions and the following disclaimer in the
318c5c0470SJoerg Sonnenberger * documentation and/or other materials provided with the distribution.
328c5c0470SJoerg Sonnenberger * 3. All advertising materials mentioning features or use of this software
338c5c0470SJoerg Sonnenberger * must display the following acknowledgement:
348c5c0470SJoerg Sonnenberger * This product includes software developed by the University of
358c5c0470SJoerg Sonnenberger * California, Berkeley and its contributors.
368c5c0470SJoerg Sonnenberger * 4. Neither the name of the University nor the names of its contributors
378c5c0470SJoerg Sonnenberger * may be used to endorse or promote products derived from this software
388c5c0470SJoerg Sonnenberger * without specific prior written permission.
398c5c0470SJoerg Sonnenberger *
408c5c0470SJoerg Sonnenberger * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
418c5c0470SJoerg Sonnenberger * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
428c5c0470SJoerg Sonnenberger * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
438c5c0470SJoerg Sonnenberger * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
448c5c0470SJoerg Sonnenberger * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
458c5c0470SJoerg Sonnenberger * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
468c5c0470SJoerg Sonnenberger * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
478c5c0470SJoerg Sonnenberger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
488c5c0470SJoerg Sonnenberger * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
498c5c0470SJoerg Sonnenberger * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
508c5c0470SJoerg Sonnenberger * SUCH DAMAGE.
518c5c0470SJoerg Sonnenberger *
528c5c0470SJoerg Sonnenberger */
538c5c0470SJoerg Sonnenberger
548c5c0470SJoerg Sonnenberger #include <sys/param.h>
558c5c0470SJoerg Sonnenberger #include <sys/systm.h>
568c5c0470SJoerg Sonnenberger #include <sys/buf.h>
578c5c0470SJoerg Sonnenberger #include <sys/bus.h>
588c5c0470SJoerg Sonnenberger #include <sys/kernel.h>
598c5c0470SJoerg Sonnenberger #include <sys/module.h>
608c5c0470SJoerg Sonnenberger
618c5c0470SJoerg Sonnenberger #include "fdc.h"
628c5c0470SJoerg Sonnenberger #include "fdreg.h"
638c5c0470SJoerg Sonnenberger
6457f7b5a3SJoerg Sonnenberger #include <bus/pccard/pccardvar.h>
6557f7b5a3SJoerg Sonnenberger
6657f7b5a3SJoerg Sonnenberger #include "card_if.h"
67*dcb4b80dSSascha Wildner #include "pccarddevs.h"
6857f7b5a3SJoerg Sonnenberger
6957f7b5a3SJoerg Sonnenberger static const struct pccard_product fdc_products[] = {
7057f7b5a3SJoerg Sonnenberger PCMCIA_CARD(YEDATA, EXTERNAL_FDD, 0),
7157f7b5a3SJoerg Sonnenberger { NULL }
7257f7b5a3SJoerg Sonnenberger };
7357f7b5a3SJoerg Sonnenberger
748c5c0470SJoerg Sonnenberger static void
fdctl_wr_pcmcia(fdc_p fdc,u_int8_t v)758c5c0470SJoerg Sonnenberger fdctl_wr_pcmcia(fdc_p fdc, u_int8_t v)
768c5c0470SJoerg Sonnenberger {
778c5c0470SJoerg Sonnenberger bus_space_write_1(fdc->portt, fdc->porth, FDCTL+fdc->port_off, v);
788c5c0470SJoerg Sonnenberger }
798c5c0470SJoerg Sonnenberger
fdc_pccard_match(device_t dev)8057f7b5a3SJoerg Sonnenberger static int fdc_pccard_match(device_t dev)
8157f7b5a3SJoerg Sonnenberger {
8257f7b5a3SJoerg Sonnenberger const struct pccard_product *pp;
8357f7b5a3SJoerg Sonnenberger
8457f7b5a3SJoerg Sonnenberger if ((pp = pccard_product_lookup(dev, fdc_products,
8557f7b5a3SJoerg Sonnenberger sizeof(fdc_products[0]), NULL)) != NULL) {
8657f7b5a3SJoerg Sonnenberger device_set_desc(dev, pp->pp_name);
8757f7b5a3SJoerg Sonnenberger return (0);
8857f7b5a3SJoerg Sonnenberger }
8957f7b5a3SJoerg Sonnenberger return (ENXIO);
9057f7b5a3SJoerg Sonnenberger }
9157f7b5a3SJoerg Sonnenberger
928c5c0470SJoerg Sonnenberger static int
fdc_pccard_probe(device_t dev)938c5c0470SJoerg Sonnenberger fdc_pccard_probe(device_t dev)
948c5c0470SJoerg Sonnenberger {
958c5c0470SJoerg Sonnenberger int error;
968c5c0470SJoerg Sonnenberger struct fdc_data *fdc;
978c5c0470SJoerg Sonnenberger
988c5c0470SJoerg Sonnenberger fdc = device_get_softc(dev);
998c5c0470SJoerg Sonnenberger bzero(fdc, sizeof *fdc);
1008c5c0470SJoerg Sonnenberger fdc->fdc_dev = dev;
1018c5c0470SJoerg Sonnenberger fdc->fdctl_wr = fdctl_wr_pcmcia;
1028c5c0470SJoerg Sonnenberger
1038c5c0470SJoerg Sonnenberger fdc->flags |= FDC_ISPCMCIA | FDC_NODMA;
1048c5c0470SJoerg Sonnenberger
1058c5c0470SJoerg Sonnenberger /* Attempt to allocate our resources for the duration of the probe */
1068c5c0470SJoerg Sonnenberger error = fdc_alloc_resources(fdc);
1078c5c0470SJoerg Sonnenberger if (error)
1088c5c0470SJoerg Sonnenberger goto out;
1098c5c0470SJoerg Sonnenberger
1108c5c0470SJoerg Sonnenberger /* First - lets reset the floppy controller */
1118c5c0470SJoerg Sonnenberger fdout_wr(fdc, 0);
1128c5c0470SJoerg Sonnenberger DELAY(100);
1138c5c0470SJoerg Sonnenberger fdout_wr(fdc, FDO_FRST);
1148c5c0470SJoerg Sonnenberger
1158c5c0470SJoerg Sonnenberger /* see if it can handle a command */
1168c5c0470SJoerg Sonnenberger if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
1178c5c0470SJoerg Sonnenberger NE7_SPEC_2(2, 0), 0)) {
1188c5c0470SJoerg Sonnenberger error = ENXIO;
1198c5c0470SJoerg Sonnenberger goto out;
1208c5c0470SJoerg Sonnenberger }
1218c5c0470SJoerg Sonnenberger
1228c5c0470SJoerg Sonnenberger fdc->fdct = FDC_NE765;
1238c5c0470SJoerg Sonnenberger
1248c5c0470SJoerg Sonnenberger out:
1258c5c0470SJoerg Sonnenberger fdc_release_resources(fdc);
1268c5c0470SJoerg Sonnenberger return (error);
1278c5c0470SJoerg Sonnenberger }
1288c5c0470SJoerg Sonnenberger
1298c5c0470SJoerg Sonnenberger static int
fdc_pccard_detach(device_t dev)1308c5c0470SJoerg Sonnenberger fdc_pccard_detach(device_t dev)
1318c5c0470SJoerg Sonnenberger {
1328c5c0470SJoerg Sonnenberger struct fdc_data *fdc;
1338c5c0470SJoerg Sonnenberger int error;
1348c5c0470SJoerg Sonnenberger
1358c5c0470SJoerg Sonnenberger fdc = device_get_softc(dev);
1368c5c0470SJoerg Sonnenberger
1378c5c0470SJoerg Sonnenberger /* have our children detached first */
1388c5c0470SJoerg Sonnenberger if ((error = bus_generic_detach(dev)))
1398c5c0470SJoerg Sonnenberger return (error);
1408c5c0470SJoerg Sonnenberger
1418c5c0470SJoerg Sonnenberger if ((fdc->flags & FDC_ATTACHED) == 0) {
1428c5c0470SJoerg Sonnenberger device_printf(dev, "already unloaded\n");
1438c5c0470SJoerg Sonnenberger return (0);
1448c5c0470SJoerg Sonnenberger }
1458c5c0470SJoerg Sonnenberger fdc->flags &= ~FDC_ATTACHED;
1468c5c0470SJoerg Sonnenberger
1478c5c0470SJoerg Sonnenberger BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
1488c5c0470SJoerg Sonnenberger fdc->fdc_intr);
1498c5c0470SJoerg Sonnenberger fdc_release_resources(fdc);
1508c5c0470SJoerg Sonnenberger device_printf(dev, "unload\n");
1518c5c0470SJoerg Sonnenberger return (0);
1528c5c0470SJoerg Sonnenberger }
1538c5c0470SJoerg Sonnenberger
1548c5c0470SJoerg Sonnenberger static device_method_t fdc_pccard_methods[] = {
1558c5c0470SJoerg Sonnenberger /* Device interface */
15657f7b5a3SJoerg Sonnenberger DEVMETHOD(device_probe, pccard_compat_probe),
15757f7b5a3SJoerg Sonnenberger DEVMETHOD(device_attach, pccard_compat_attach),
1588c5c0470SJoerg Sonnenberger DEVMETHOD(device_detach, fdc_pccard_detach),
1598c5c0470SJoerg Sonnenberger DEVMETHOD(device_shutdown, bus_generic_shutdown),
1608c5c0470SJoerg Sonnenberger DEVMETHOD(device_suspend, bus_generic_suspend),
1618c5c0470SJoerg Sonnenberger DEVMETHOD(device_resume, bus_generic_resume),
1628c5c0470SJoerg Sonnenberger
16357f7b5a3SJoerg Sonnenberger /* Card interface */
16457f7b5a3SJoerg Sonnenberger DEVMETHOD(card_compat_match, fdc_pccard_match),
16557f7b5a3SJoerg Sonnenberger DEVMETHOD(card_compat_probe, fdc_pccard_probe),
16657f7b5a3SJoerg Sonnenberger DEVMETHOD(card_compat_attach, fdc_attach),
16757f7b5a3SJoerg Sonnenberger /* Device interface */
16857f7b5a3SJoerg Sonnenberger
1698c5c0470SJoerg Sonnenberger /* Bus interface */
1708c5c0470SJoerg Sonnenberger DEVMETHOD(bus_print_child, fdc_print_child),
1718c5c0470SJoerg Sonnenberger DEVMETHOD(bus_read_ivar, fdc_read_ivar),
1728c5c0470SJoerg Sonnenberger /* Our children never use any other bus interface methods. */
1738c5c0470SJoerg Sonnenberger
174d3c9c58eSSascha Wildner DEVMETHOD_END
1758c5c0470SJoerg Sonnenberger };
1768c5c0470SJoerg Sonnenberger
1778c5c0470SJoerg Sonnenberger static driver_t fdc_pccard_driver = {
1788c5c0470SJoerg Sonnenberger "fdc",
1798c5c0470SJoerg Sonnenberger fdc_pccard_methods,
1808c5c0470SJoerg Sonnenberger sizeof(struct fdc_data)
1818c5c0470SJoerg Sonnenberger };
1828c5c0470SJoerg Sonnenberger
183aa2b9d05SSascha Wildner DRIVER_MODULE(fdc, pccard, fdc_pccard_driver, fdc_devclass, NULL, NULL);
184