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)
--- 36 unchanged lines hidden (view full) ---
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * from: @(#)fd.c 7.4 (Berkeley) 5/25/91
53 * $FreeBSD: head/sys/pc98/cbus/fdc.c 132286 2004-07-17 10:07:19Z nyan $
54 */
55
56#include "opt_fdc.h"
57
58#include <sys/param.h>
59#include <sys/bio.h>
60#include <sys/bus.h>
61#include <sys/devicestat.h>
--- 287 unchanged lines hidden (view full) ---
349static u_int8_t fdsts_rd(fdc_p);
350static void fddata_wr(fdc_p, u_int8_t);
351static u_int8_t fddata_rd(fdc_p);
352static int fdc_err(struct fdc_data *, const char *);
353static int enable_fifo(fdc_p fdc);
354static int fd_sense_drive_status(fdc_p, int *);
355static int fd_sense_int(fdc_p, int *, int *);
356static int fd_read_status(fdc_p);
357static int fd_probe(device_t);
358static int fd_attach(device_t);
359static int fd_detach(device_t);
360static void set_motor(struct fdc_data *, int, int);
361# define TURNON 1
362# define TURNOFF 0
363static timeout_t fd_turnoff;
364static timeout_t fd_motor_on;
--- 390 unchanged lines hidden (view full) ---
755#endif /* PC98 */
756
757void
758fdc_release_resources(struct fdc_data *fdc)
759{
760 device_t dev;
761
762 dev = fdc->fdc_dev;
763 if (fdc->fdc_intr) {
764 BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
765 fdc->fdc_intr);
766 fdc->fdc_intr = NULL;
767 }
768 if (fdc->res_irq != 0) {
769 bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
770 fdc->res_irq);
771 bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
772 fdc->res_irq);
773 fdc->res_irq = NULL;
774 }
775#ifndef PC98
776 if (fdc->res_ctl != 0) {
777 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
778 fdc->res_ctl);
779 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
780 fdc->res_ctl);
781 fdc->res_ctl = NULL;
782 }
783#endif
784#ifdef PC98
785 if (fdc->res_fdsio != 0) {
786 bus_deactivate_resource(dev, SYS_RES_IOPORT, 3,
787 fdc->res_fdsio);
788 bus_release_resource(dev, SYS_RES_IOPORT, 3, fdc->res_fdsio);
789 fdc->res_fdsio = NULL;
790 }
791 if (fdc->res_fdemsio != 0) {
792 bus_deactivate_resource(dev, SYS_RES_IOPORT, 4,
793 fdc->res_fdemsio);
794 bus_release_resource(dev, SYS_RES_IOPORT, 4, fdc->res_fdemsio);
795 fdc->res_fdemsio = NULL;
796 }
797#endif
798 if (fdc->res_ioport != 0) {
799 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
800 fdc->res_ioport);
801 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
802 fdc->res_ioport);
803 fdc->res_ioport = NULL;
804 }
805 if (fdc->res_drq != 0) {
806 bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
807 fdc->res_drq);
808 bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
809 fdc->res_drq);
810 fdc->res_drq = NULL;
811 }
812}
813
814/*
815 * Configuration/initialization stuff, per controller.
816 */
817
818int
--- 69 unchanged lines hidden (view full) ---
888#ifdef PC98
889 /* reset controller, turn motor off */
890 fdc_reset(fdc);
891#else
892 /* reset controller, turn motor off */
893 fdout_wr(fdc, 0);
894#endif
895
896 fdc_release_resources(fdc);
897 return (0);
898}
899
900/*
901 * Add a child device to the fdc controller. It will then be probed etc.
902 */
903device_t
904fdc_add_child(device_t dev, const char *name, int unit)
905{
906 int flags;
907 struct fdc_ivars *ivar;
908 device_t child;
909
910 ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
911 if (ivar == NULL)
912 return (NULL);
913 child = device_add_child(dev, name, unit);
914 if (child == NULL) {
915 free(ivar, M_DEVBUF);
916 return (NULL);
917 }
918 device_set_ivars(child, ivar);
919 ivar->fdunit = unit;
920 ivar->fdtype = FDT_NONE;
921 if (resource_int_value(name, unit, "flags", &flags) == 0)
922 device_set_flags(child, flags);
923 if (resource_disabled(name, unit))
924 device_disable(child);
925 return (child);
926}
927
928int
929fdc_attach(device_t dev)
930{
931 struct fdc_data *fdc;
932 int error;
933
934 fdc = device_get_softc(dev);
935 fdc->fdc_dev = dev;
936 error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq,
937 INTR_TYPE_BIO | INTR_ENTROPY, fdc_intr, fdc,
938 &fdc->fdc_intr);
939 if (error) {
940 device_printf(dev, "cannot setup interrupt\n");
941 return error;
942 }
943 fdc->fdcu = device_get_unit(dev);
944 fdc->flags |= FDC_NEEDS_RESET;
945
946 fdc->state = DEVIDLE;
947
948#ifdef PC98
949 /* reset controller, turn motor off, clear fdout mirror reg */
950 fdc_reset(fdc);
951#else
952 /* reset controller, turn motor off, clear fdout mirror reg */
953 fdout_wr(fdc, fdc->fdout = 0);
954#endif
955 bioq_init(&fdc->head);
956
957 return (0);
958}
959
960int
961fdc_hints_probe(device_t dev)
962{
963 const char *name, *dname;
964 int i, error, dunit;
965
966 /*
967 * Probe and attach any children. We should probably detect
968 * devices from the BIOS unless overridden.
969 */
970 name = device_get_nameunit(dev);
971 i = 0;
972 while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) {
973 resource_int_value(dname, dunit, "drive", &dunit);
974 fdc_add_child(dev, dname, dunit);
975 }
976
977 if ((error = bus_generic_attach(dev)) != 0)
978 return (error);
979 return (0);
980}
981
982int
983fdc_print_child(device_t me, device_t child)
984{
985 int retval = 0, flags;
986
--- 27 unchanged lines hidden (view full) ---
1014 fdc = device_get_softc(device_get_parent(dev));
1015 flags = device_get_flags(dev);
1016
1017 fd->dev = dev;
1018 fd->fdc = fdc;
1019 fd->fdsu = fdsu;
1020 fd->fdu = device_get_unit(dev);
1021
1022 /* Auto-probe if fdinfo is present, but always allow override. */
1023 type = FD_DTYPE(flags);
1024 if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) {
1025 fd->type = type;
1026 goto done;
1027 } else {
1028 /* make sure fdautoselect() will be called */
1029 fd->flags = FD_UA;
1030 fd->type = type;
1031 }
--- 77 unchanged lines hidden (view full) ---
1109
1110 if ((flags & FD_NO_PROBE) == 0 &&
1111 (st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */
1112 return (ENXIO);
1113#endif /* PC98 */
1114
1115done:
1116#ifndef PC98
1117 /* This doesn't work before the first reset. */
1118 if ((fdc->flags & FDC_HAS_FIFO) == 0 &&
1119 fdc->fdct == FDC_ENHANCED &&
1120 (device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0 &&
1121 enable_fifo(fdc) == 0) {
1122 device_printf(device_get_parent(dev),
1123 "FIFO enabled, %d bytes threshold\n", fifo_threshold);
1124 }
1125#endif /* PC98 */
--- 1678 unchanged lines hidden ---
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)
--- 36 unchanged lines hidden (view full) ---
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * from: @(#)fd.c 7.4 (Berkeley) 5/25/91
53 * $FreeBSD: head/sys/pc98/cbus/fdc.c 132286 2004-07-17 10:07:19Z nyan $
54 */
55
56#include "opt_fdc.h"
57
58#include <sys/param.h>
59#include <sys/bio.h>
60#include <sys/bus.h>
61#include <sys/devicestat.h>
--- 287 unchanged lines hidden (view full) ---
349static u_int8_t fdsts_rd(fdc_p);
350static void fddata_wr(fdc_p, u_int8_t);
351static u_int8_t fddata_rd(fdc_p);
352static int fdc_err(struct fdc_data *, const char *);
353static int enable_fifo(fdc_p fdc);
354static int fd_sense_drive_status(fdc_p, int *);
355static int fd_sense_int(fdc_p, int *, int *);
356static int fd_read_status(fdc_p);
357static int fd_probe(device_t);
358static int fd_attach(device_t);
359static int fd_detach(device_t);
360static void set_motor(struct fdc_data *, int, int);
361# define TURNON 1
362# define TURNOFF 0
363static timeout_t fd_turnoff;
364static timeout_t fd_motor_on;
--- 390 unchanged lines hidden (view full) ---
755#endif /* PC98 */
756
757void
758fdc_release_resources(struct fdc_data *fdc)
759{
760 device_t dev;
761
762 dev = fdc->fdc_dev;
763 if (fdc->fdc_intr) {
764 BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
765 fdc->fdc_intr);
766 fdc->fdc_intr = NULL;
767 }
768 if (fdc->res_irq != 0) {
769 bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
770 fdc->res_irq);
771 bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
772 fdc->res_irq);
773 fdc->res_irq = NULL;
774 }
775#ifndef PC98
776 if (fdc->res_ctl != 0) {
777 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
778 fdc->res_ctl);
779 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
780 fdc->res_ctl);
781 fdc->res_ctl = NULL;
782 }
783#endif
784#ifdef PC98
785 if (fdc->res_fdsio != 0) {
786 bus_deactivate_resource(dev, SYS_RES_IOPORT, 3,
787 fdc->res_fdsio);
788 bus_release_resource(dev, SYS_RES_IOPORT, 3, fdc->res_fdsio);
789 fdc->res_fdsio = NULL;
790 }
791 if (fdc->res_fdemsio != 0) {
792 bus_deactivate_resource(dev, SYS_RES_IOPORT, 4,
793 fdc->res_fdemsio);
794 bus_release_resource(dev, SYS_RES_IOPORT, 4, fdc->res_fdemsio);
795 fdc->res_fdemsio = NULL;
796 }
797#endif
798 if (fdc->res_ioport != 0) {
799 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
800 fdc->res_ioport);
801 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
802 fdc->res_ioport);
803 fdc->res_ioport = NULL;
804 }
805 if (fdc->res_drq != 0) {
806 bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
807 fdc->res_drq);
808 bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
809 fdc->res_drq);
810 fdc->res_drq = NULL;
811 }
812}
813
814/*
815 * Configuration/initialization stuff, per controller.
816 */
817
818int
--- 69 unchanged lines hidden (view full) ---
888#ifdef PC98
889 /* reset controller, turn motor off */
890 fdc_reset(fdc);
891#else
892 /* reset controller, turn motor off */
893 fdout_wr(fdc, 0);
894#endif
895
896 fdc_release_resources(fdc);
897 return (0);
898}
899
900/*
901 * Add a child device to the fdc controller. It will then be probed etc.
902 */
903device_t
904fdc_add_child(device_t dev, const char *name, int unit)
905{
906 int flags;
907 struct fdc_ivars *ivar;
908 device_t child;
909
910 ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
911 if (ivar == NULL)
912 return (NULL);
913 child = device_add_child(dev, name, unit);
914 if (child == NULL) {
915 free(ivar, M_DEVBUF);
916 return (NULL);
917 }
918 device_set_ivars(child, ivar);
919 ivar->fdunit = unit;
920 ivar->fdtype = FDT_NONE;
921 if (resource_int_value(name, unit, "flags", &flags) == 0)
922 device_set_flags(child, flags);
923 if (resource_disabled(name, unit))
924 device_disable(child);
925 return (child);
926}
927
928int
929fdc_attach(device_t dev)
930{
931 struct fdc_data *fdc;
932 int error;
933
934 fdc = device_get_softc(dev);
935 fdc->fdc_dev = dev;
936 error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq,
937 INTR_TYPE_BIO | INTR_ENTROPY, fdc_intr, fdc,
938 &fdc->fdc_intr);
939 if (error) {
940 device_printf(dev, "cannot setup interrupt\n");
941 return error;
942 }
943 fdc->fdcu = device_get_unit(dev);
944 fdc->flags |= FDC_NEEDS_RESET;
945
946 fdc->state = DEVIDLE;
947
948#ifdef PC98
949 /* reset controller, turn motor off, clear fdout mirror reg */
950 fdc_reset(fdc);
951#else
952 /* reset controller, turn motor off, clear fdout mirror reg */
953 fdout_wr(fdc, fdc->fdout = 0);
954#endif
955 bioq_init(&fdc->head);
956
957 return (0);
958}
959
960int
961fdc_hints_probe(device_t dev)
962{
963 const char *name, *dname;
964 int i, error, dunit;
965
966 /*
967 * Probe and attach any children. We should probably detect
968 * devices from the BIOS unless overridden.
969 */
970 name = device_get_nameunit(dev);
971 i = 0;
972 while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) {
973 resource_int_value(dname, dunit, "drive", &dunit);
974 fdc_add_child(dev, dname, dunit);
975 }
976
977 if ((error = bus_generic_attach(dev)) != 0)
978 return (error);
979 return (0);
980}
981
982int
983fdc_print_child(device_t me, device_t child)
984{
985 int retval = 0, flags;
986
--- 27 unchanged lines hidden (view full) ---
1014 fdc = device_get_softc(device_get_parent(dev));
1015 flags = device_get_flags(dev);
1016
1017 fd->dev = dev;
1018 fd->fdc = fdc;
1019 fd->fdsu = fdsu;
1020 fd->fdu = device_get_unit(dev);
1021
1022 /* Auto-probe if fdinfo is present, but always allow override. */
1023 type = FD_DTYPE(flags);
1024 if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) {
1025 fd->type = type;
1026 goto done;
1027 } else {
1028 /* make sure fdautoselect() will be called */
1029 fd->flags = FD_UA;
1030 fd->type = type;
1031 }
--- 77 unchanged lines hidden (view full) ---
1109
1110 if ((flags & FD_NO_PROBE) == 0 &&
1111 (st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */
1112 return (ENXIO);
1113#endif /* PC98 */
1114
1115done:
1116#ifndef PC98
1117 /* This doesn't work before the first reset. */
1118 if ((fdc->flags & FDC_HAS_FIFO) == 0 &&
1119 fdc->fdct == FDC_ENHANCED &&
1120 (device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0 &&
1121 enable_fifo(fdc) == 0) {
1122 device_printf(device_get_parent(dev),
1123 "FIFO enabled, %d bytes threshold\n", fifo_threshold);
1124 }
1125#endif /* PC98 */
--- 1678 unchanged lines hidden ---