1 /* $NetBSD: fdc_pcmcia.c,v 1.19 2008/03/16 00:58:56 cube Exp $ */
4 * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: fdc_pcmcia.c,v 1.19 2008/03/16 00:58:56 cube Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <sys/device.h>
45 #include <dev/pcmcia/pcmciareg.h>
46 #include <dev/pcmcia/pcmciavar.h>
47 #include <dev/pcmcia/pcmciadevs.h>
49 #include <dev/isa/isavar.h>
51 #include <dev/isa/fdreg.h>
52 #include <dev/isa/fdcvar.h>
54 struct fdc_pcmcia_softc
{
55 struct fdc_softc sc_fdc
; /* real "fdc" softc */
57 struct pcmcia_function
*sc_pf
; /* our PCMCIA function */
60 int fdc_pcmcia_match(device_t
, cfdata_t
, void *);
61 int fdc_pcmcia_validate_config(struct pcmcia_config_entry
*);
62 void fdc_pcmcia_attach(device_t
, device_t
, void *);
63 static void fdc_conf(struct fdc_softc
*);
65 CFATTACH_DECL_NEW(fdc_pcmcia
, sizeof(struct fdc_pcmcia_softc
),
66 fdc_pcmcia_match
, fdc_pcmcia_attach
, NULL
, NULL
);
68 const struct pcmcia_product fdc_pcmcia_products
[] = {
69 { PCMCIA_VENDOR_YEDATA
, PCMCIA_PRODUCT_YEDATA_EXTERNAL_FDD
,
70 PCMCIA_CIS_YEDATA_EXTERNAL_FDD
},
72 const size_t fdc_pcmcia_nproducts
=
73 sizeof(fdc_pcmcia_products
) / sizeof(fdc_pcmcia_products
[0]);
76 fdc_conf(struct fdc_softc
*fdc
)
78 bus_space_tag_t iot
= fdc
->sc_iot
;
79 bus_space_handle_t ioh
= fdc
->sc_ioh
;
82 /* Figure out what we have */
83 if (out_fdc_cmd(iot
, ioh
, FDC_CMD_VERSION
) == -1 ||
84 (n
= fdcresult(fdc
, 1)) != 1)
87 /* Nec765 or equivalent */
88 if (FDC_ST0(fdc
->sc_status
[0]) == FDC_ST0_INVL
)
93 if (out_fdc_cmd(iot
, ioh
, FDC_CMD_NSC
) == -1 ||
94 (n
= fdcresult(fdc
, 1)) != 1) {
95 printf("NSC command failed\n");
99 printf("Version %x\n", fdc
->sc_status
[0]);
102 if (out_fdc_cmd(iot
, ioh
, FDC_CMD_DUMPREG
) == -1 ||
103 (n
= fdcresult(fdc
, -1)) == -1)
107 * Expect 10 bytes of status; one means that it did not
108 * understand the command
114 * Configure controller to use FIFO and 8 bytes of FIFO threshold
116 (void)out_fdc_cmd(iot
, ioh
, FDC_CMD_CONFIGURE
);
117 (void)out_fdc(iot
, ioh
, 0x00); /* doc says 0 */
118 (void)out_fdc(iot
, ioh
, 8); /* FIFO is active low. */
119 (void)out_fdc(iot
, ioh
, fdc
->sc_status
[9]); /* same comp */
120 /* No result phase */
122 /* Lock this configuration */
123 if (out_fdc_cmd(iot
, ioh
, FDC_CMD_LOCK(FDC_CMD_FLAGS_LOCK
)) == -1 ||
124 fdcresult(fdc
, 1) != 1)
129 fdc_pcmcia_match(device_t parent
, cfdata_t match
, void *aux
)
131 struct pcmcia_attach_args
*pa
= aux
;
133 if (pcmcia_product_lookup(pa
, fdc_pcmcia_products
, fdc_pcmcia_nproducts
,
134 sizeof(fdc_pcmcia_products
[0]), NULL
))
140 fdc_pcmcia_attach(device_t parent
, device_t self
, void *aux
)
142 struct fdc_pcmcia_softc
*psc
= device_private(self
);
143 struct fdc_softc
*fdc
= &psc
->sc_fdc
;
144 struct pcmcia_attach_args
*pa
= aux
;
145 struct pcmcia_config_entry
*cfe
;
146 struct pcmcia_function
*pf
= pa
->pf
;
147 struct fdc_attach_args fa
;
153 error
= pcmcia_function_configure(pf
, fdc_pcmcia_validate_config
);
155 aprint_error_dev(self
, "configure failed, error=%d\n", error
);
160 fdc
->sc_iot
= cfe
->iospace
[0].handle
.iot
;
161 fdc
->sc_iot
= cfe
->iospace
[0].handle
.ioh
;
163 if (pcmcia_function_enable(pf
))
166 fdc
->sc_flags
= FDC_HEADSETTLE
;
167 fdc
->sc_state
= DEVIDLE
;
168 TAILQ_INIT(&fdc
->sc_drives
);
170 if (!fdcfind(fdc
->sc_iot
, fdc
->sc_ioh
, 1))
171 aprint_error_dev(self
, "coundn't find fdc\n");
175 /* Establish the interrupt handler. */
176 fdc
->sc_ih
= pcmcia_intr_establish(pa
->pf
, IPL_BIO
, fdchwintr
, fdc
);
180 /* physical limit: four drives per controller. */
181 for (fa
.fa_drive
= 0; fa
.fa_drive
< 4; fa
.fa_drive
++) {
183 fa
.fa_deftype
= &fd_types
[0];
185 fa
.fa_deftype
= NULL
; /* unknown */
186 (void)config_found(self
, (void *)&fa
, fdprint
);
192 pcmcia_function_unconfigure(pf
);