From df75ede470fab24d56d3b5c23e1a07c011577f7c Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sun, 22 Jan 2012 22:16:14 +0100 Subject: [PATCH] kernel: Nuke the old (and deprecated) ata(4) driver and atacontrol(8). It's been replaced by nata(4)/natacontrol(8) since more than 4 years. --- Makefile_upgrade.inc | 7 + sbin/Makefile | 1 - sbin/atacontrol/Makefile | 7 - sbin/atacontrol/atacontrol.8 | 255 --- sbin/atacontrol/atacontrol.c | 428 ----- share/man/man4/Makefile | 3 +- share/man/man4/ata.4 | 263 --- share/man/man4/isa.4 | 2 - share/man/man4/nata.4 | 12 +- share/man/man4/{atapicam.4 => natapicam.4} | 40 +- sys/conf/files | 15 - sys/conf/options | 2 +- sys/config/GENERIC | 11 - sys/config/LINT | 26 +- sys/config/LINT64 | 26 +- sys/config/X86_64_GENERIC | 11 - sys/dev/disk/ata/ata-all.c | 1599 ---------------- sys/dev/disk/ata/ata-all.h | 345 ---- sys/dev/disk/ata/ata-card.c | 147 -- sys/dev/disk/ata/ata-disk.c | 988 ---------- sys/dev/disk/ata/ata-disk.h | 86 - sys/dev/disk/ata/ata-dma.c | 1628 ---------------- sys/dev/disk/ata/ata-isa.c | 155 -- sys/dev/disk/ata/ata-pci.c | 987 ---------- sys/dev/disk/ata/ata-raid.c | 1470 -------------- sys/dev/disk/ata/ata-raid.h | 233 --- sys/dev/disk/ata/atapi-all.c | 741 -------- sys/dev/disk/ata/atapi-all.h | 199 -- sys/dev/disk/ata/atapi-cam.c | 735 ------- sys/dev/disk/ata/atapi-cd.c | 1998 -------------------- sys/dev/disk/ata/atapi-cd.h | 330 ---- sys/dev/disk/ata/atapi-fd.c | 430 ----- sys/dev/disk/ata/atapi-fd.h | 81 - sys/dev/disk/ata/atapi-tape.c | 661 ------- sys/dev/disk/ata/atapi-tape.h | 162 -- 35 files changed, 51 insertions(+), 14033 deletions(-) delete mode 100644 sbin/atacontrol/Makefile delete mode 100644 sbin/atacontrol/atacontrol.8 delete mode 100644 sbin/atacontrol/atacontrol.c delete mode 100644 share/man/man4/ata.4 rename share/man/man4/{atapicam.4 => natapicam.4} (84%) delete mode 100644 sys/dev/disk/ata/ata-all.c delete mode 100644 sys/dev/disk/ata/ata-all.h delete mode 100644 sys/dev/disk/ata/ata-card.c delete mode 100644 sys/dev/disk/ata/ata-disk.c delete mode 100644 sys/dev/disk/ata/ata-disk.h delete mode 100644 sys/dev/disk/ata/ata-dma.c delete mode 100644 sys/dev/disk/ata/ata-isa.c delete mode 100644 sys/dev/disk/ata/ata-pci.c delete mode 100644 sys/dev/disk/ata/ata-raid.c delete mode 100644 sys/dev/disk/ata/ata-raid.h delete mode 100644 sys/dev/disk/ata/atapi-all.c delete mode 100644 sys/dev/disk/ata/atapi-all.h delete mode 100644 sys/dev/disk/ata/atapi-cam.c delete mode 100644 sys/dev/disk/ata/atapi-cd.c delete mode 100644 sys/dev/disk/ata/atapi-cd.h delete mode 100644 sys/dev/disk/ata/atapi-fd.c delete mode 100644 sys/dev/disk/ata/atapi-fd.h delete mode 100644 sys/dev/disk/ata/atapi-tape.c delete mode 100644 sys/dev/disk/ata/atapi-tape.h diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 30d5a95939..3e0818c851 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -1883,6 +1883,13 @@ TO_REMOVE+=/usr/share/man/man3/archive_write_set_format_shar_binary.3.gz TO_REMOVE+=/usr/share/man/cat3/archive_write_set_format_shar_binary.3.gz TO_REMOVE+=/usr/share/man/man3/archive_write_set_format_ustar.3.gz TO_REMOVE+=/usr/share/man/cat3/archive_write_set_format_ustar.3.gz +TO_REMOVE+=/sbin/atacontrol +TO_REMOVE+=/usr/share/man/cat8/atacontrol.8.gz +TO_REMOVE+=/usr/share/man/man8/atacontrol.8.gz +TO_REMOVE+=/usr/share/man/cat4/ata.4.gz +TO_REMOVE+=/usr/share/man/man4/ata.4.gz +TO_REMOVE+=/usr/share/man/cat4/atapicam.4.gz +TO_REMOVE+=/usr/share/man/man4/atapicam.4.gz .if ${MACHINE_ARCH} == "x86_64" TO_REMOVE+=/usr/libdata/stallion/2681.sys diff --git a/sbin/Makefile b/sbin/Makefile index 31f0f00389..c1896fd300 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -4,7 +4,6 @@ # XXX MISSING: icheck ncheck SUBDIR= adjkerntz \ - atacontrol \ atm \ badsect \ camcontrol \ diff --git a/sbin/atacontrol/Makefile b/sbin/atacontrol/Makefile deleted file mode 100644 index 8d1f9106af..0000000000 --- a/sbin/atacontrol/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -#$FreeBSD: src/sbin/atacontrol/Makefile,v 1.6.2.1 2002/03/18 08:40:00 sos Exp $ -#$DragonFly: src/sbin/atacontrol/Makefile,v 1.5 2006/10/17 00:55:39 pavalos Exp $ - -PROG= atacontrol -MAN= atacontrol.8 - -.include diff --git a/sbin/atacontrol/atacontrol.8 b/sbin/atacontrol/atacontrol.8 deleted file mode 100644 index 4c828f31a5..0000000000 --- a/sbin/atacontrol/atacontrol.8 +++ /dev/null @@ -1,255 +0,0 @@ -.\" -.\" Copyright (c) 2000,2001,2002 Søren Schmidt -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/sbin/atacontrol/atacontrol.8,v 1.13.2.7 2003/01/26 03:01:09 keramida Exp $ -.\" $DragonFly: src/sbin/atacontrol/atacontrol.8,v 1.3 2004/03/11 12:28:53 hmp Exp $ -.\" -.Dd May 17, 2001 -.Dt ATACONTROL 8 -.Os -.Sh NAME -.Nm atacontrol -.Nd ATA device driver control program -.Sh SYNOPSIS -.Nm -.Aq Ar command -.Ar args -.Pp -.Nm -.Ic attach -.Ar channel -.Nm -.Ic detach -.Ar channel -.Nm -.Ic reinit -.Ar channel -.Nm -.Ic create -.Ar type Oo Ar interleave Oc Ar disk0 ... diskN -.Nm -.Ic delete -.Ar raid -.Nm -.Ic rebuild -.Ar raid -.Nm -.Ic status -.Ar raid -.Nm -.Ic mode -.Ar channel -.Op Ar mastermode slavemode -.Nm -.Ic info -.Ar channel -.Nm -.Ic cap -.Ar channel device -.Nm -.Ic enclosure -.Ar channel device -.Nm -.Ic list -.Sh DESCRIPTION -The -.Nm -utility is a control program that provides the user access and control to the -.Dx -.Xr ata 4 -subsystem. -.Pp -The -.Nm -utility -can cause severe system crashes and loss of data if used improperly. -Please -exercise caution when using this command! -.Pp -The -.Ar channel -argument is the number of the ATA channel on which to operate. -The following commands are supported: -.Bl -tag -width "rebuild" -.It Ic attach -Attach an ATA -.Ar channel . -Devices on the channel are probed and attached as -is done on boot. -.It Ic detach -Detach an ATA -.Ar channel . -Devices on the channel are removed from the kernel, -and all outstanding transfers etc. are returned back to the system marked -as failed. -.It Ic reinit -Reinitialize an ATA -.Ar channel . -Both devices on the channel are reset and -initialized to the parameters the ATA driver has stored internally. -Devices that have gone bad and no longer respond to the probe, or devices -that have physically been removed, are removed from the kernel. -Likewise are devices that show up during a reset, probed and attached. -.It Ic create -Create a -.Ar type -ATA RAID. -The type can be -.Cm RAID0 -(stripe), -.Cm RAID1 -(mirror), -.Cm RAID0+1 -or -.Cm SPAN -(JBOD). -In case the RAID has a -.Cm RAID0 -component, -the -.Ar interleave -must be specified in number of sectors. -The RAID will be created -of the individual disks named -.Bk -words -.Ar disk0 ... diskN . -.Ek -.Pp -Although the ATA driver allows for creating an ATA RAID on disks with any -controller, there are restrictions. -It is only possible to boot on -an array if it is either located on a -.Dq real -ATA RAID controller like -the Promise or Highpoint controllers, or if the RAID declared is of -.Cm RAID1 -or -.Cm SPAN -type; in case of a -.Cm SPAN , -the partition to boot must -reside on the first disk in the SPAN. -.It Ic delete -Delete a RAID array on a RAID capable ATA controller. -.It Ic rebuild -Rebuild a RAID1 array on a RAID capable ATA controller. -.It Ic status -Get the status of an ATA RAID. -.It Ic mode -Without the two mode arguments, the current transfer modes of both -devices are printed. -If the mode arguments are given, the ATA driver -is asked to change the transfer modes to those given. -The ATA driver -will reject modes that are not supported by the hardware. -Modes are given like -.Dq Li PIO3 , -.Dq Li udma2 , -.Dq Li udma100 , -case does not matter. -If one of the devices mode should not be changed, use a nonexisting mode -as argument (i.e.\& -.Dq Li XXX ) , -and the mode will remain unchanged. -.Pp -Currently supported modes are: -.Cm BIOSDMA , -.Cm PIO0 -(alias -.Cm BIOSPIO ) , -.Cm PIO1 , PIO2 , PIO3 , PIO4 , -.Cm WDMA2 , -.Cm UDMA2 -(alias -.Cm UDMA33 ) , -.Cm UDMA4 -(alias -.Cm UDMA66 ) , -.Cm UDMA5 -(alias -.Cm UDMA100 ) -and -.Cm UDMA6 -(alias -.Cm UDMA133 ) . -.It Ic info -Show info about the attached devices on the -.Ar channel . -The device name and manufacture/version strings are shown. -.It Ic cap -Show detailed info about the device on -.Ar channel device -where device is 0 for master and 1 for slave. -.It Ic enclosure -Show detailed info about the enclosure on -.Ar channel device -where device is 0 for master and 1 for slave. -Fan RPM speed, enclosure temperature, 5V and 12V levels are shown. -.It Ic list -Show info about all attached devices on all active controllers. -.El -.Sh EXAMPLES -To see the devices' current access modes, use the command line: -.Pp -.Dl "atacontrol mode 0" -.Pp -which results in the modes of the devices being displayed as a string -like this: -.Bd -literal -offset indent -Master = WDMA2 -Slave = PIO4 -.Ed -.Pp -This means that ata0-master is in DMA mode, -ata0-slave is in PIO mode, -and so forth. -You can set the mode with -.Nm -and a string like the above, -for example: -.Pp -.Dl "atacontrol mode 0 PIO4 PIO4" -.Pp -The new modes are set as soon as the -.Nm -command returns. -.Sh SEE ALSO -.Xr ata 4 -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 4.6 . -.Sh AUTHORS -.An -nosplit -The -.Nm -utility was written by -.An S\(/oren Schmidt -.Aq sos@FreeBSD.org . -.Pp -This manual page was written by -.An S\(/oren Schmidt -.Aq sos@FreeBSD.org . diff --git a/sbin/atacontrol/atacontrol.c b/sbin/atacontrol/atacontrol.c deleted file mode 100644 index a5a925a14d..0000000000 --- a/sbin/atacontrol/atacontrol.c +++ /dev/null @@ -1,428 +0,0 @@ -/*- - * Copyright (c) 2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sbin/atacontrol/atacontrol.c,v 1.11.2.5 2002/08/21 13:18:17 sos Exp $ - * $DragonFly: src/sbin/atacontrol/atacontrol.c,v 1.4 2005/01/09 04:43:33 cpressey Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include - -static const char *mode2str(int); -static int str2mode(char *); -static void usage(void); -static int version(int); -static void param_print(struct ata_params *); -static void cap_print(struct ata_params *); -static int ata_cap_print(int, int, int); -static int info_print(int, int, int); - -const char * -mode2str(int mode) -{ - switch (mode) { - case ATA_PIO: return "BIOSPIO"; - case ATA_PIO0: return "PIO0"; - case ATA_PIO1: return "PIO1"; - case ATA_PIO2: return "PIO2"; - case ATA_PIO3: return "PIO3"; - case ATA_PIO4: return "PIO4"; - case ATA_WDMA2: return "WDMA2"; - case ATA_UDMA2: return "UDMA33"; - case ATA_UDMA4: return "UDMA66"; - case ATA_UDMA5: return "UDMA100"; - case ATA_UDMA6: return "UDMA133"; - case ATA_DMA: return "BIOSDMA"; - default: return "???"; - } -} - -int -str2mode(char *str) -{ - if (!strcasecmp(str, "BIOSPIO")) return ATA_PIO; - if (!strcasecmp(str, "PIO0")) return ATA_PIO0; - if (!strcasecmp(str, "PIO1")) return ATA_PIO1; - if (!strcasecmp(str, "PIO2")) return ATA_PIO2; - if (!strcasecmp(str, "PIO3")) return ATA_PIO3; - if (!strcasecmp(str, "PIO4")) return ATA_PIO4; - if (!strcasecmp(str, "WDMA2")) return ATA_WDMA2; - if (!strcasecmp(str, "UDMA2")) return ATA_UDMA2; - if (!strcasecmp(str, "UDMA33")) return ATA_UDMA2; - if (!strcasecmp(str, "UDMA4")) return ATA_UDMA4; - if (!strcasecmp(str, "UDMA66")) return ATA_UDMA4; - if (!strcasecmp(str, "UDMA5")) return ATA_UDMA5; - if (!strcasecmp(str, "UDMA100")) return ATA_UDMA5; - if (!strcasecmp(str, "UDMA6")) return ATA_UDMA6; - if (!strcasecmp(str, "UDMA133")) return ATA_UDMA6; - if (!strcasecmp(str, "BIOSDMA")) return ATA_DMA; - return -1; -} - - -void -usage(void) -{ - fprintf(stderr, "usage: atacontrol channel [args]\n"); - exit(1); -} - -int -version(int ver) -{ - int bit; - - if (ver == 0xffff) - return 0; - for (bit = 15; bit >= 0; bit--) - if (ver & (1 << bit)) - return bit; - return 0; -} - -void -param_print(struct ata_params *parm) -{ - printf("<%.40s/%.8s> ATA/ATAPI rev %d\n", - parm->model, parm->revision, version(parm->version_major)); -} - -void -cap_print(struct ata_params *parm) -{ - printf("\n"); - printf("ATA/ATAPI revision %d\n", version(parm->version_major)); - printf("device model %.40s\n", parm->model); - printf("serial number %.20s\n", parm->serial); - printf("firmware revision %.8s\n", parm->revision); - - printf("cylinders %d\n", parm->cylinders); - printf("heads %d\n", parm->heads); - printf("sectors/track %d\n", parm->sectors); - - printf("lba%ssupported ", parm->support_lba ? " " : " not "); - if (parm->lba_size) - printf("%d sectors\n", parm->lba_size); - else - printf("\n"); - - printf("lba48%ssupported ", parm->support.address48 ? " " : " not "); - if (parm->lba_size48) - printf("%ju sectors\n", (uintmax_t)parm->lba_size48); - else - printf("\n"); - printf("dma%ssupported\n", parm->support_dma ? " " : " not"); - - printf("overlap%ssupported\n", parm->support_queueing ? " " : " not "); - - printf("\nFeature Support Enable Value Vendor\n"); - - printf("write cache %s %s\n", - parm->support.write_cache ? "yes" : "no", - parm->enabled.write_cache ? "yes" : "no"); - - printf("read ahead %s %s\n", - parm->support.look_ahead ? "yes" : "no", - parm->enabled.look_ahead ? "yes" : "no"); - - printf("dma queued %s %s %d/%02X\n", - parm->support.queued ? "yes" : "no", - parm->enabled.queued ? "yes" : "no", - parm->queuelen, parm->queuelen); - - printf("SMART %s %s\n", - parm->support.smart ? "yes" : "no", - parm->enabled.smart ? "yes" : "no"); - - printf("microcode download %s %s\n", - parm->support.microcode ? "yes" : "no", - parm->enabled.microcode ? "yes" : "no"); - - printf("security %s %s\n", - parm->support.smart ? "yes" : "no", - parm->enabled.smart ? "yes" : "no"); - - printf("power management %s %s\n", - parm->support.power_mngt ? "yes" : "no", - parm->enabled.power_mngt ? "yes" : "no"); - - printf("advanced power management %s %s %d/%02X\n", - parm->support.apm ? "yes" : "no", - parm->enabled.apm ? "yes" : "no", - parm->apm_value, parm->apm_value); - - printf("automatic acoustic management %s %s %d/%02X %d/%02X\n", - parm->support.auto_acoustic ? "yes" : "no", - parm->enabled.auto_acoustic ? "yes" : "no", - parm->current_acoustic, parm->current_acoustic, - parm->vendor_acoustic, parm->vendor_acoustic); -} - -int -ata_cap_print(int fd, int channel, int device) -{ - struct ata_cmd iocmd; - - bzero(&iocmd, sizeof(struct ata_cmd)); - - iocmd.channel = channel; - iocmd.device = -1; - iocmd.cmd = ATAGPARM; - - if (ioctl(fd, IOCATA, &iocmd) < 0) - return errno; - - printf("ATA channel %d, %s", channel, device==0 ? "Master" : "Slave"); - - if (iocmd.u.param.type[device]) { - printf(", device %s:\n", iocmd.u.param.name[device]); - cap_print(&iocmd.u.param.params[device]); - } - else - printf(": no device present\n"); - return 0; -} - -int -info_print(int fd, int channel, int prchan) -{ - struct ata_cmd iocmd; - - bzero(&iocmd, sizeof(struct ata_cmd)); - iocmd.channel = channel; - iocmd.device = -1; - iocmd.cmd = ATAGPARM; - if (ioctl(fd, IOCATA, &iocmd) < 0) - return errno; - if (prchan) - printf("ATA channel %d:\n", channel); - printf("%sMaster: ", prchan ? " " : ""); - if (iocmd.u.param.type[0]) { - printf("%4.4s ", iocmd.u.param.name[0]); - param_print(&iocmd.u.param.params[0]); - } - else - printf(" no device present\n"); - printf("%sSlave: ", prchan ? " " : ""); - if (iocmd.u.param.type[1]) { - printf("%4.4s ", iocmd.u.param.name[1]); - param_print(&iocmd.u.param.params[1]); - } - else - printf(" no device present\n"); - return 0; -} - -int -main(int argc, char **argv) -{ - struct ata_cmd iocmd; - int fd; - - if ((fd = open("/dev/ata", O_RDWR)) < 0) - err(1, "control device not found"); - - if (argc < 2) - usage(); - - bzero(&iocmd, sizeof(struct ata_cmd)); - - if (argc > 2 && strcmp(argv[1], "create")) { - int chan; - - if (!strcmp(argv[1], "delete") || - !strcmp(argv[1], "status") || - !strcmp(argv[1], "rebuild")) { - if (!(sscanf(argv[2], "%d", &chan) == 1 || - sscanf(argv[2], "ar%d", &chan) == 1)) - usage(); - } - else { - if (!(sscanf(argv[2], "%d", &chan) == 1 || - sscanf(argv[2], "ata%d", &chan) == 1)) - usage(); - } - iocmd.channel = chan; - } - - if (!strcmp(argv[1], "list") && argc == 2) { - int unit = 0; - - while (info_print(fd, unit++, 1) != ENXIO); - } - else if (!strcmp(argv[1], "info") && argc == 3) { - info_print(fd, iocmd.channel, 0); - } - else if (!strcmp(argv[1], "cap") && argc == 4) { - ata_cap_print(fd, iocmd.channel, atoi(argv[3])); - } - else if (!strcmp(argv[1], "enclosure") && argc == 4) { - iocmd.device = atoi(argv[3]); - iocmd.cmd = ATAENCSTAT; - if (ioctl(fd, IOCATA, &iocmd) < 0) - err(1, "ioctl(ATAENCSTAT)"); - printf("fan RPM: %d temp: %.1f 5V: %.2f 12V: %.2f\n", - iocmd.u.enclosure.fan, - (double)iocmd.u.enclosure.temp / 10, - (double)iocmd.u.enclosure.v05 / 1000, - (double)iocmd.u.enclosure.v12 / 1000); - } - else if (!strcmp(argv[1], "detach") && argc == 3) { - iocmd.cmd = ATADETACH; - if (ioctl(fd, IOCATA, &iocmd) < 0) - err(1, "ioctl(ATADETACH)"); - } - else if (!strcmp(argv[1], "attach") && argc == 3) { - iocmd.cmd = ATAATTACH; - if (ioctl(fd, IOCATA, &iocmd) < 0) - err(1, "ioctl(ATAATTACH)"); - info_print(fd, iocmd.channel, 0); - } - else if (!strcmp(argv[1], "reinit") && argc == 3) { - iocmd.cmd = ATAREINIT; - if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATAREINIT)"); - info_print(fd, iocmd.channel, 0); - } - else if (!strcmp(argv[1], "create")) { - int disk, dev, offset; - - iocmd.cmd = ATARAIDCREATE; - if (!strcmp(argv[2], "RAID0") || !strcmp(argv[2], "stripe")) - iocmd.u.raid_setup.type = 1; - if (!strcmp(argv[2], "RAID1") || !strcmp(argv[2],"mirror")) - iocmd.u.raid_setup.type = 2; - if (!strcmp(argv[2], "RAID0+1")) - iocmd.u.raid_setup.type = 3; - if (!strcmp(argv[2], "SPAN") || !strcmp(argv[2], "JBOD")) - iocmd.u.raid_setup.type = 4; - if (!iocmd.u.raid_setup.type) - usage(); - - if (iocmd.u.raid_setup.type & 1) { - if (!sscanf(argv[3], "%d", - &iocmd.u.raid_setup.interleave) == 1) - usage(); - offset = 4; - } - else - offset = 3; - - for (disk = 0; disk < 16 && (offset + disk) < argc; disk++) { - if (!(sscanf(argv[offset + disk], "%d", &dev) == 1 || - sscanf(argv[offset + disk], "ad%d", &dev) == 1)) - usage(); - iocmd.u.raid_setup.disks[disk] = dev; - } - iocmd.u.raid_setup.total_disks = disk; - if (ioctl(fd, IOCATA, &iocmd) < 0) - err(1, "ioctl(ATARAIDCREATE)"); - else - printf("ar%d created\n", iocmd.u.raid_setup.unit); - } - else if (!strcmp(argv[1], "delete") && argc == 3) { - iocmd.cmd = ATARAIDDELETE; - if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATARAIDDELETE)"); - } - else if (!strcmp(argv[1], "rebuild") && argc == 3) { - iocmd.cmd = ATARAIDREBUILD; - if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATARAIDREBUILD)"); - } - else if (!strcmp(argv[1], "status") && argc == 3) { - int i; - - iocmd.cmd = ATARAIDSTATUS; - if (ioctl(fd, IOCATA, &iocmd) < 0) - err(1, "ioctl(ATARAIDSTATUS)"); - printf("ar%d: ATA ", iocmd.channel); - switch (iocmd.u.raid_status.type) { - case AR_RAID0: - printf("RAID0"); - break; - case AR_RAID1: - printf("RAID1"); - break; - case AR_RAID0 | AR_RAID1: - printf("RAID0+1"); - break; - case AR_SPAN: - printf("SPAN"); - break; - } - printf(" subdisks: "); - for (i = 0; i < iocmd.u.raid_status.total_disks; i++) { - if (iocmd.u.raid_status.disks[i] >= 0) - printf("ad%d ", iocmd.u.raid_status.disks[i]); - else - printf("DOWN "); - } - printf("status: "); - switch (iocmd.u.raid_status.status) { - case AR_READY: - printf("READY\n"); - break; - case AR_READY | AR_DEGRADED: - printf("DEGRADED\n"); - break; - case AR_READY | AR_DEGRADED | AR_REBUILDING: - printf("REBUILDING %d%% completed\n", - iocmd.u.raid_status.progress); - break; - default: - printf("BROKEN\n"); - } - } - else if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 5)) { - if (argc == 5) { - iocmd.cmd = ATASMODE; - iocmd.device = -1; - iocmd.u.mode.mode[0] = str2mode(argv[3]); - iocmd.u.mode.mode[1] = str2mode(argv[4]); - if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATASMODE)"); - } - if (argc == 3 || argc == 5) { - iocmd.cmd = ATAGMODE; - iocmd.device = -1; - if (ioctl(fd, IOCATA, &iocmd) < 0) - err(1, "ioctl(ATAGMODE)"); - printf("Master = %s \nSlave = %s\n", - mode2str(iocmd.u.mode.mode[0]), - mode2str(iocmd.u.mode.mode[1])); - } - } - else - usage(); - exit(0); -} diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 50dd4e696d..b984874695 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -33,8 +33,6 @@ MAN= aac.4 \ aps.4 \ arcmsr.4 \ arp.4 \ - ata.4 \ - atapicam.4 \ ath.4 \ ath_hal.4 \ atkbd.4 \ @@ -166,6 +164,7 @@ MAN= aac.4 \ mxge.4 \ my.4 \ nata.4 \ + natapicam.4 \ nataraid.4 \ natm.4 \ ncr.4 \ diff --git a/share/man/man4/ata.4 b/share/man/man4/ata.4 deleted file mode 100644 index 414f9ce464..0000000000 --- a/share/man/man4/ata.4 +++ /dev/null @@ -1,263 +0,0 @@ -.\" -.\" Copyright (c) 2000,2004 Jeroen Ruigrok van der Werven -.\" Copyright (c) 2000,2001,2002 Søren Schmidt -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD: src/share/man/man4/ata.4,v 1.3.2.18 2002/10/16 13:40:51 fjoe Exp $ -.\" $DragonFly: src/share/man/man4/ata.4,v 1.9 2008/07/08 14:12:45 thomas Exp $ -.\" -.Dd June 15, 2007 -.Dt ATA 4 -.Os -.Sh NAME -.Nm ata -.Nd deprecated (S)ATA/ATAPI disk controller driver -.Sh SYNOPSIS -For ISA based ATA/ATAPI support: -.Cd device isa -.Cd device ata0 at isa? port IO_WD1 irq 14 -.Cd device ata1 at isa? port IO_WD2 irq 15 -.Pp -For PCI based (S)ATA/ATAPI support: -.Cd device pci -.Cd device ata -.Pp -To support (S)ATA compliant disk drives: -.Cd device atadisk -.Pp -To support ATAPI CD-ROM, CDR, CDRW, DVD-ROM and DVD-RAM drives: -.Cd device atapicd -.Pp -To support ATAPI floppy drives, -such as the ZIP and LS120: -.Cd device atapifd -.Pp -To support ATAPI tape drives: -.Cd device atapist -.Pp -The following tunables are settable from the loader: -.Bl -ohang -.It Va hw.ata.ata_dma -set to 1 for DMA access, 0 for PIO (default is DMA). -.It Va hw.ata.atapi_dma -set to 1 for DMA access, 0 for PIO (default is PIO). -.It Va hw.ata.wc -set to 1 to enable Write Caching, 0 to disable (default is enabled). -(WARNING: might cause data loss on power failures.) -.It Va hw.ata.tags -set to 1 to enable Tagged Queuing support, 0 to disable (default is disabled). -(Only IBM DPTA, DTLA, ICxxxxxxAT, ICxxxxxxAV drives support that.) -.El -.Sh DESCRIPTION -The -.Nm -driver is the deprecated -.Fx 4.8 -ATA driver. -.Dx Ap s -default ATA driver is -.Xr nata 4 -which was ported from newer -.Fx -code. -.Pp -This driver provides access to disk drives, ATAPI CD-ROM and DVD drives, -ZIP drives and tape streamers connected to controllers -according to the ATA and ATAPI standards. -These devices are also commonly known as IDE or EIDE devices. -.Pp -The currently supported ATA controllers with their maximum speed include: -.Pp -.Bl -tag -width "Promise Ultra/Fasttrak-100 TX2/TX2000" -compact -.It Acerlabs Aladdin -Ultra DMA 100 (UDMA5), 100 MB/sec (depending on model, max stated at boot) -.It AMD 756 -Ultra DMA 66 (UDMA4), 66 MB/sec -.It AMD 766 -Ultra DMA 100 (UDMA5), 100 MB/sec -.It AMD 768 -Ultra DMA 100 (UDMA5), 100 MB/sec -.It AMD 8111 -Ultra DMA 133 (UDMA6), 133 MB/sec -.It Cenatek Rocket Drive -Ultra DMA 133 (UDMA6), 133 MB/sec -.It CMD 646 -DMA 2 (WDMA2), 16 MB/sec -.It CMD 648 -Ultra DMA 66 (UDMA4), 66 MB/sec -.It CMD 649 -Ultra DMA 100 (UDMA5), 100 MB/sec -.It Cypress 82C693 -DMA 2 (WDMA2), 16 MB/sec -.It Cyrix 5530 -Ultra DMA 33 (UDMA2), 33 MB/sec -.It HighPoint HPT366 -Ultra DMA 66 (UDMA4), 66 MB/sec -.It HighPoint HPT370 -Ultra DMA 100 (UDMA5), 100 MB/sec -.It HighPoint HPT372/HPT374 -Ultra DMA 133 (UDMA6), 133 MB/sec -.It Intel PIIX/PIIX3 -DMA 2 (WDMA2), 16 MB/sec -.It Intel PIIX4 -Ultra DMA 33 (UDMA2), 33 MB/sec -.It Intel ICH0 -Ultra DMA 33 (UDMA2), 33 MB/sec -.It Intel ICH -Ultra DMA 66 (UDMA4), 66 MB/sec -.It Intel ICH2/ICH3/ICH4/ICH5 -Ultra DMA 100 (UDMA5), 100 MB/sec -.It Intel ICH6R/RW -Ultra DMA 100 (UDMA5), 100 MB/sec -.It NVIDIA nForce ATA100 -Ultra DMA 100 (UDMA5), 100 MB/sec -.It NVIDIA nForce2/nForce3 ATA133 -Ultra DMA 133 (UDMA6), 133 MB/sec -.It Promise Ultra/Fasttrak-33 -Ultra DMA 33 (UDMA2), 33 MB/sec -.It Promise Ultra/Fasttrak-66 -Ultra DMA 66 (UDMA4), 66 MB/sec -.It Promise Ultra/Fasttrak-100 (TX2/TX4) -Ultra DMA 100 (UDMA5), 100 MB/sec -.It Promise Ultra/Fasttrak-133 TX2/TX2000 -Ultra DMA 133 (UDMA6), 133 MB/sec -.It ServerWorks ROSB4 -Ultra DMA 33 (UDMA2), 33 MB/sec -.It ServerWorks CSB5 -Ultra DMA 100 (UDMA5), 100 MB/sec (depending on model, max stated at boot) -.It SiI 0680 -Ultra DMA 133 (UDMA6), 133 MB/sec (depending on model, max stated at boot) -.It SiS 5591 -Ultra DMA 133 (UDMA5), 133 MB/sec (depending on model, max stated at boot) -.It VIA 82C586 -Ultra DMA 33 (UDMA2), 33 MB/sec -.It VIA 82C596 -Ultra DMA 66 (UDMA4), 66 MB/sec (depending on model, max stated at boot) -.It VIA 82C686a -Ultra DMA 66 (UDMA4), 66 MB/sec -.It VIA 82C686b -Ultra DMA 100 (UDMA5), 100 MB/sec -.It VIA 8233/8235/8237 -Ultra DMA 133 (UDMA6), 133 MB/sec (depending on model, max stated at boot) -.El -.Pp -The currently supported SATA controllers with their maximum speed include: -.Pp -.Bl -tag -width "SiI 3112/3114/3124/3512" -compact -.It Intel ICH5 -Serial ATA 150, 150 MB/sec -.It Intel ICH6(R)/(R)W -Serial ATA 150, 150 MB/sec -.It SiI 3112/3114/3124/3512 -Serial ATA 150, 150 MB/sec -.It VIA 8237 -Serial ATA 150, 150 MB/sec -.El -.Pp -All unknown chipsets are supported at the maximum speed of 16 MB/sec. -.Pp -The -.Nm -driver also allows for changes to the transfer mode of the devices -at a later time when the system is up and running, see -.Xr atacontrol 8 . -.Pp -The driver attempts to set the maximum performance transfer mode on your disk -drives by selecting the highest possible DMA mode. However the -.Nm -driver sometimes issue the message -"DMA limited to UDMA33, non-ATA66 cable or device", -if the cable is ATA66 (or above) compliant, it is because the other device -on this channel states it can only accept up to UDMA2/ATA33 signals. -ATAPI devices are left in PIO mode because DMA problems are common despite the -device specifications. -You can always try to set DMA mode on an ATAPI device using -.Xr atacontrol 8 , -but be aware that your hardware might -.Em not -support it and can -.Em hang -the system. -.Sh FILES -.Bl -tag -width "/dev/acd* " -compact -.It Pa /dev/ad* -ATA disk device nodes -.It Pa /dev/acd* -ATAPI CD-ROM device nodes -.It Pa /dev/afd* -ATAPI floppy drive device nodes -.It Pa /dev/ast* -ATAPI tape drive device nodes -.El -.Sh NOTES -Static numbering -(enabled with the -.Dv ATA_STATIC_ID -kernel option) -reserves a number for each possibly connected disk, -even when not present. -This may result in odd situations where, -for example, -ad0 and ad2 exist in the absence of ad1. -The advantage is that the addition of the formerly absent drive -does not cause the numbers of the other drives to change. -.Pp -The -.Nm -driver does not support MFM/RLL/ESDI (ST-506) style disks. -.Pp -Remember that in order to use UDMA4 (and above) mode you -.Em have -to use a special 80 conductor cable, -and the driver tries to determine if you have such a cable -attached before setting UDMA4 mode. -.Pp -The use of UDMA4(66MHz) and higher together with non-UDMA4 devices on -the same ATA channel is not recommended, -unless they are run at the non-UDMA4 device's lower speed. -The driver has been designed to handle that kind of setup but lots of -older devices do not like this. -.Sh SEE ALSO -.Xr nata 4 , -.Xr atacontrol 8 , -.Xr burncd 8 -.Sh HISTORY -The -.Nm -driver first appeared in -.Fx 4.0 . -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An S\(/oren Schmidt -.Aq sos@FreeBSD.org . -.Pp -This manual page was written by -.An Jeroen Ruigrok van der Werven -.Aq asmodai@FreeBSD.org -and -.An S\(/oren Schmidt -.Aq sos@FreeBSD.org . diff --git a/share/man/man4/isa.4 b/share/man/man4/isa.4 index 895f1500c6..9a72df01e9 100644 --- a/share/man/man4/isa.4 +++ b/share/man/man4/isa.4 @@ -73,8 +73,6 @@ Future Domain based SCSI controller driver PC architecture floppy disk controller driver .It Xr nata 4 Generic ATA/ATAPI disk controller driver -.It Xr ata 4 -Generic ATA/ATAPI disk controller driver (deprecated) .El .Ss Serial and parallel interfaces .Bl -tag -width 12n -offset indent -compact diff --git a/share/man/man4/nata.4 b/share/man/man4/nata.4 index 9ea605e592..09ba814f84 100644 --- a/share/man/man4/nata.4 +++ b/share/man/man4/nata.4 @@ -26,7 +26,6 @@ .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $FreeBSD: src/share/man/man4/ata.4,v 1.72 2007/03/10 12:44:22 brueffer Exp $ -.\" $DragonFly: src/share/man/man4/nata.4,v 1.4 2008/01/01 12:16:40 swildner Exp $ .\" .Dd January 1, 2008 .Dt NATA 4 @@ -81,15 +80,6 @@ driver provides access to ATA (IDE) and SerialATA disk drives, ATAPI CDROM/DVD drives, ZIP/LS120 ATAPI drives and ATAPI tape drives connected to controllers according to the ATA/ATAPI standards. .Pp -.Nm Nata -is the default ATA driver of -.Dx . -The old -.Fx 4.8 -driver is still available, but deprecated. -For more information, see -.Xr ata 4 . -.Pp The currently supported ATA/SATA controller chips are: .Pp .Bl -tag -width "Silicon Image:" -compact @@ -207,7 +197,7 @@ as the same numbered device, and not depend on attach order. Native Command Queuing (NCQ) on SATA drives is not yet supported. .Sh SEE ALSO .Xr ahci 4 , -.Xr ata 4 , +.Xr natapicam 4 , .Xr nataraid 4 , .Xr sili 4 , .Xr burncd 8 , diff --git a/share/man/man4/atapicam.4 b/share/man/man4/natapicam.4 similarity index 84% rename from share/man/man4/atapicam.4 rename to share/man/man4/natapicam.4 index 22f1f01ede..099a0a9fd7 100644 --- a/share/man/man4/atapicam.4 +++ b/share/man/man4/natapicam.4 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2002 +.\" Copyright (c) 2002, 2004 .\" Thomas Quinot . All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -16,7 +16,7 @@ .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS @@ -25,17 +25,30 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF .\" THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $FreeBSD: src/share/man/man4/atapicam.4,v 1.2.2.2 2003/03/03 18:51:16 trhodes Exp $ -.\" $DragonFly: src/share/man/man4/atapicam.4,v 1.3 2008/09/06 10:36:27 thomas Exp $ +.\" $FreeBSD: src/share/man/man4/atapicam.4,v 1.8 2009/10/29 15:59:27 brueffer Exp $ .\" -.Dd October 23, 2002 -.Dt ATAPICAM 4 +.Dd January 22, 2012 +.Dt NATAPICAM 4 .Os .Sh NAME -.Nm atapicam +.Nm natapicam .Nd CAM XPT (transport) module for ATAPI devices .Sh SYNOPSIS -.Cd "device atapicam" +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device scbus" +.Cd "device nata" +.Cd "device natapicam" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +natapicam_load="YES" +.Ed .Sh DESCRIPTION The ATAPI/CAM module allows ATAPI devices (CD-ROM, CD-RW, DVD drives, floppy drives such as Iomega Zip, tape drives) to be accessed through @@ -43,8 +56,6 @@ the SCSI subsystem, .Xr cam 4 . .Pp .Xr nata 4 -or -.Xr ata 4 and .Xr scbus 4 must be configured in the kernel as well. @@ -78,7 +89,8 @@ extended information. .Sh EXAMPLES .Bd -literal -offset indent -device atapicam +device nata +device natapicam device scbus device cd device pass @@ -92,17 +104,15 @@ driver to the kernel. .Pp Print the list of all devices available through CAM. .Pp -.Dl "mount -t cd9660 /dev/cd0c /mnt" +.Dl "mount -t cd9660 /dev/cd0 /mnt" .Pp Mount a CD-ROM from an ATAPI CD-ROM drive (the command above assumes that the ATAPI drive is the only CD-ROM unit). .Sh SEE ALSO -.Xr ata 4 , .Xr cam 4 , .Xr nata 4 , .Xr scsi 4 , -.Xr atacontrol 8 , -.Xr camcontrol 8 +.Xr camcontrol 8 , .Xr natacontrol 8 .Sh HISTORY The ATAPI/CAM driver first appeared in diff --git a/sys/conf/files b/sys/conf/files index a26134c8a2..80b9572577 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -142,21 +142,6 @@ dev/netif/an/if_an_pccard.c optional an pccard dev/netif/ar/if_ar.c optional ar dev/netif/ar/if_ar_pci.c optional ar pci dev/raid/asr/asr.c optional asr pci -dev/disk/ata/ata-all.c optional ata -dev/disk/ata/ata-isa.c optional ata isa -dev/disk/ata/ata-card.c optional ata pccard -dev/disk/ata/ata-pci.c optional ata pci -dev/disk/ata/ata-dma.c optional ata pci -dev/disk/ata/ata-disk.c optional atadisk -dev/disk/ata/ata-raid.c optional atadisk -dev/disk/ata/atapi-all.c optional atapicd -dev/disk/ata/atapi-all.c optional atapifd -dev/disk/ata/atapi-all.c optional atapist -dev/disk/ata/atapi-all.c optional atapicam -dev/disk/ata/atapi-cd.c optional atapicd -dev/disk/ata/atapi-fd.c optional atapifd -dev/disk/ata/atapi-tape.c optional atapist -dev/disk/ata/atapi-cam.c optional atapicam dev/disk/ahci/ahci.c optional ahci dev/disk/ahci/ahci_dragonfly.c optional ahci dev/disk/ahci/ahci_attach.c optional ahci diff --git a/sys/conf/options b/sys/conf/options index 00af8194db..0450fc2551 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -253,7 +253,7 @@ SCSI_NCR_MYADDR opt_ncr.h # Options used only in pci/isp_pci.c ISP_TARGET_MODE opt_isp.h -# Options used in the 'ata' ATA/ATAPI driver +# Options used in the 'nata' ATA/ATAPI driver ATA_STATIC_ID opt_ata.h # Net stuff. diff --git a/sys/config/GENERIC b/sys/config/GENERIC index 694d5308b4..87849754e2 100644 --- a/sys/config/GENERIC +++ b/sys/config/GENERIC @@ -109,17 +109,6 @@ device nataraid # support for ATA software RAID device natausb # ATA-over-USB support options ATA_STATIC_ID # Static device numbering -# LEGACY ATA and ATAPI devices -#device ata0 at isa? port IO_WD1 irq 14 -#device ata1 at isa? port IO_WD2 irq 15 -#device ata -#device atadisk # ATA disk drives -#device atapicd # ATAPI CDROM drives -#device atapifd # ATAPI floppy drives -#device atapist # ATAPI tape drives -#device atapicam # Emulate ATAPI devices as SCSI via CAM -#options ATA_STATIC_ID #Static device numbering - # SCSI Controllers device ahc # AHA2940 and onboard AIC7xxx devices device ahd # AHA39320/29320 and onboard AIC79xx devices diff --git a/sys/config/LINT b/sys/config/LINT index 3e3e57e327..d219437407 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -1253,17 +1253,6 @@ device pst # device ips -# -# The 'ATA' driver supports all ATA and ATAPI devices. -# You only need one "device ata" for it to find all -# PCI ATA/ATAPI devices on modern machines. -#device ata -#device atadisk # ATA disk drives -#device atapicd # ATAPI CDROM drives -#device atapifd # ATAPI floppy drives -#device atapist # ATAPI tape drives -#device atapicam # emulate ATAPI devices as SCSI ditto via CAM - # needs CAM to be present (scbus & pass) # AHCI driver, this will override NATA for AHCI devices, # both drivers may be included. # @@ -1273,9 +1262,10 @@ device ahci # device sili -# The 'NATA' set of drivers are set to replace the previous ATA drivers, -# and this set of drivers is mutually exclusive with the old ones. This means, -# you can't have both at the same time! +# The 'NATA' driver supports all ATA and ATAPI devices. +# You only need one "device nata" for it to find all +# PCI ATA/ATAPI devices on modern machines. +# device nata device natadisk # ATA disk drives device natapicd # ATAPI CD/DVD drives @@ -1285,16 +1275,16 @@ device natapicam # ATAPI CAM layer emulation device nataraid # support for ATA software RAID controllers device natausb # ATA-over-USB support -#The following options are valid on the ATA & NATA drivers: +# The following options are valid for the NATA driver: # # ATA_STATIC_ID: controller numbering is static (like the old driver) # else the device numbers are dynamically allocated. options ATA_STATIC_ID -# # For older non-PCI systems, these are the lines to use: -#device ata0 at isa? port IO_WD1 irq 14 -#device ata1 at isa? port IO_WD2 irq 15 +# +#device nata0 at isa? port IO_WD1 irq 14 +#device nata1 at isa? port IO_WD2 irq 15 # # Standard floppy disk controllers: `fdc' and `fd' diff --git a/sys/config/LINT64 b/sys/config/LINT64 index bebb73dc7e..41808e583a 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -1076,17 +1076,6 @@ device tws # 3ware 9750 series SATA/SAS RAID # device ips -# -# The 'ATA' driver supports all ATA and ATAPI devices. -# You only need one "device ata" for it to find all -# PCI ATA/ATAPI devices on modern machines. -#device ata -#device atadisk # ATA disk drives -#device atapicd # ATAPI CDROM drives -#device atapifd # ATAPI floppy drives -#device atapist # ATAPI tape drives -#device atapicam # emulate ATAPI devices as SCSI ditto via CAM - # needs CAM to be present (scbus & pass) # AHCI driver, this will override NATA for AHCI devices, # both drivers may be included. # @@ -1096,9 +1085,10 @@ device ahci # device sili -# The 'NATA' set of drivers are set to replace the previous ATA drivers, -# and this set of drivers is mutually exclusive with the old ones. This means, -# you can't have both at the same time! +# The 'NATA' driver supports all ATA and ATAPI devices. +# You only need one "device nata" for it to find all +# PCI ATA/ATAPI devices on modern machines. +# device nata device natadisk # ATA disk drives device natapicd # ATAPI CD/DVD drives @@ -1108,16 +1098,16 @@ device natapicam # ATAPI CAM layer emulation device nataraid # support for ATA software RAID controllers device natausb # ATA-over-USB support -#The following options are valid on the ATA & NATA drivers: +# The following options are valid for the NATA driver: # # ATA_STATIC_ID: controller numbering is static (like the old driver) # else the device numbers are dynamically allocated. options ATA_STATIC_ID -# # For older non-PCI systems, these are the lines to use: -#device ata0 at isa? port IO_WD1 irq 14 -#device ata1 at isa? port IO_WD2 irq 15 +# +#device nata0 at isa? port IO_WD1 irq 14 +#device nata1 at isa? port IO_WD2 irq 15 # # Standard floppy disk controllers: `fdc' and `fd' diff --git a/sys/config/X86_64_GENERIC b/sys/config/X86_64_GENERIC index a67b1ed307..d4a9c9a3ad 100644 --- a/sys/config/X86_64_GENERIC +++ b/sys/config/X86_64_GENERIC @@ -95,17 +95,6 @@ device nataraid # support for ATA software RAID device natausb # ATA-over-USB support options ATA_STATIC_ID # Static device numbering -# LEGACY ATA and ATAPI devices -#device ata0 at isa? port IO_WD1 irq 14 -#device ata1 at isa? port IO_WD2 irq 15 -#device ata -#device atadisk # ATA disk drives -#device atapicd # ATAPI CDROM drives -#device atapifd # ATAPI floppy drives -#device atapist # ATAPI tape drives -#device atapicam # Emulate ATAPI devices as SCSI via CAM -#options ATA_STATIC_ID #Static device numbering - # SCSI Controllers device ahc # AHA2940 and onboard AIC7xxx devices device ahd # AHA39320/29320 and onboard AIC79xx devices diff --git a/sys/dev/disk/ata/ata-all.c b/sys/dev/disk/ata/ata-all.c deleted file mode 100644 index b48c223b56..0000000000 --- a/sys/dev/disk/ata/ata-all.c +++ /dev/null @@ -1,1599 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-all.c,v 1.50.2.45 2003/03/12 14:47:12 sos Exp $ - */ - -#include "opt_ata.h" -#include "use_atadisk.h" -#include "use_atapicd.h" -#include "use_atapifd.h" -#include "use_atapist.h" -#include "use_atapicam.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "ata-all.h" -#include "ata-disk.h" -#include "ata-raid.h" -#include "atapi-all.h" - -union ata_request { - struct ad_request ad; - struct atapi_request atapi; -}; - -/* device structures */ -static d_ioctl_t ataioctl; -static struct dev_ops ata_ops = { - { "ata", 159, 0 }, - .d_open = nullopen, - .d_close = nullclose, - .d_ioctl = ataioctl, -}; - -/* prototypes */ -#if 0 -static void ata_boot_attach(void); -#endif -static void ata_intr(void *); -static int ata_getparam(struct ata_device *, u_int8_t); -static int ata_service(struct ata_channel *); -static void bswap(int8_t *, int); -static void btrim(int8_t *, int); -static void bpack(int8_t *, int8_t *, int); -static void ata_change_mode(struct ata_device *, int); -static u_int8_t ata_enclosure_sensor(struct ata_device *, int, u_int8_t, u_int8_t); -static int ata_enclosure_status(struct ata_device *, int *, int *, int *, int *); - -/* sysctl vars */ -SYSCTL_NODE(_hw, OID_AUTO, ata, CTLFLAG_RD, 0, "ATA driver parameters"); - -int ata_mpipe_size = 4; -TUNABLE_INT("hw.ata.mpipe_size", &ata_mpipe_size); -SYSCTL_INT(_hw_ata, OID_AUTO, mpipe_size, CTLFLAG_RW, &ata_mpipe_size, 0, - "ATA global I/O pipeline max size"); - - -/* global vars */ -devclass_t ata_devclass; - -/* local vars */ -static MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer"); - -/* misc defines */ -#define DEV_ATAPIALL NATAPICD > 0 || NATAPIFD > 0 || \ - NATAPIST > 0 || NATAPICAM > 0 - -int -ata_probe(device_t dev) -{ - struct ata_channel *ch; - int rid; - - if (!dev || !(ch = device_get_softc(dev))) - return ENXIO; - - if (ch->r_io || ch->r_altio || ch->r_irq) - return EEXIST; - - /* initialize the softc basics */ - ch->active = ATA_IDLE; - ch->dev = dev; - - rid = ATA_IOADDR_RID; - ch->r_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_IOSIZE, RF_ACTIVE); - if (!ch->r_io) - goto failure; - - rid = ATA_ALTADDR_RID; - ch->r_altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_ALTIOSIZE, RF_ACTIVE); - if (!ch->r_altio) - goto failure; - - rid = ATA_BMADDR_RID; - ch->r_bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_BMIOSIZE, RF_ACTIVE); - if (bootverbose) - ata_printf(ch, -1, "iobase=0x%04x altiobase=0x%04x bmaddr=0x%04x\n", - (int)rman_get_start(ch->r_io), - (int)rman_get_start(ch->r_altio), - (ch->r_bmio) ? (int)rman_get_start(ch->r_bmio) : 0); - - ata_reset(ch); - - ch->device[MASTER].channel = ch; - ch->device[MASTER].unit = ATA_MASTER; - ch->device[MASTER].mode = ATA_PIO; - ch->device[SLAVE].channel = ch; - ch->device[SLAVE].unit = ATA_SLAVE; - ch->device[SLAVE].mode = ATA_PIO; - TAILQ_INIT(&ch->ata_queue); - TAILQ_INIT(&ch->atapi_queue); - - mpipe_init(&ch->req_mpipe, M_ATA, sizeof(union ata_request), - 4, ata_mpipe_size, 0, NULL, NULL, NULL); - mpipe_init(&ch->dma_mpipe, M_DEVBUF, PAGE_SIZE, - 4, ata_mpipe_size, MPF_NOZERO, NULL, NULL, NULL); - - return 0; - -failure: - if (ch->r_io) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ch->r_io); - if (ch->r_altio) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, ch->r_altio); - if (ch->r_bmio) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, ch->r_bmio); - if (bootverbose) - ata_printf(ch, -1, "probe allocation failed\n"); - return ENXIO; -} - -int -ata_attach(device_t dev) -{ - struct ata_channel *ch; - int error, rid; - - if (!dev || !(ch = device_get_softc(dev))) - return ENXIO; - - rid = ATA_IRQ_RID; - ch->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - if (!ch->r_irq) { - ata_printf(ch, -1, "unable to allocate interrupt\n"); - return ENXIO; - } - - /* - * Traditional ata registers are sensitive to when they can be accessed - * in the face of e.g. ongoing DMA. Do not allow the interrupt to be - * polled. - */ - if ((error = bus_setup_intr(dev, ch->r_irq, INTR_NOPOLL, - ata_intr, ch, &ch->ih, NULL))) { - ata_printf(ch, -1, "unable to setup interrupt\n"); - return error; - } - - /* - * do not attach devices if we are in early boot, this is done later - * when interrupts are enabled by a hook into the boot process. - * otherwise attach what the probe has found in ch->devices. - */ - crit_enter(); - - if (ch->devices & ATA_ATA_SLAVE) - if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY)) - ch->devices &= ~ATA_ATA_SLAVE; - if (ch->devices & ATA_ATAPI_SLAVE) - if (ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY)) - ch->devices &= ~ATA_ATAPI_SLAVE; - if (ch->devices & ATA_ATA_MASTER) - if (ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY)) - ch->devices &= ~ATA_ATA_MASTER; - if (ch->devices & ATA_ATAPI_MASTER) - if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY)) - ch->devices &= ~ATA_ATAPI_MASTER; -#if NATADISK > 0 - if (ch->devices & ATA_ATA_MASTER) - ad_attach(&ch->device[MASTER], 0); - if (ch->devices & ATA_ATA_SLAVE) - ad_attach(&ch->device[SLAVE], 0); -#endif -#if DEV_ATAPIALL - if (ch->devices & ATA_ATAPI_MASTER) - atapi_attach(&ch->device[MASTER], 0); - if (ch->devices & ATA_ATAPI_SLAVE) - atapi_attach(&ch->device[SLAVE], 0); -#endif -#if NATAPICAM > 0 - atapi_cam_attach_bus(ch); -#endif - crit_exit(); - return 0; -} - -int -ata_detach(device_t dev) -{ - struct ata_channel *ch; - - if (!dev || !(ch = device_get_softc(dev)) || - !ch->r_io || !ch->r_altio || !ch->r_irq) - return ENXIO; - - /* make sure channel is not busy */ - crit_enter(); - ATA_SLEEPLOCK_CH(ch, ATA_CONTROL); -#if NATADISK > 0 - if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) - ad_detach(&ch->device[MASTER], 1); - if (ch->devices & ATA_ATA_SLAVE && ch->device[SLAVE].driver) - ad_detach(&ch->device[SLAVE], 1); -#endif -#if DEV_ATAPIALL - if (ch->devices & ATA_ATAPI_MASTER && ch->device[MASTER].driver) - atapi_detach(&ch->device[MASTER]); - if (ch->devices & ATA_ATAPI_SLAVE && ch->device[SLAVE].driver) - atapi_detach(&ch->device[SLAVE]); -#endif -#if NATAPICAM > 0 - atapi_cam_detach_bus(ch); -#endif - crit_exit(); - - if (ch->device[MASTER].param) { - kfree(ch->device[MASTER].param, M_ATA); - ch->device[MASTER].param = NULL; - } - if (ch->device[SLAVE].param) { - kfree(ch->device[SLAVE].param, M_ATA); - ch->device[SLAVE].param = NULL; - } - ch->device[MASTER].driver = NULL; - ch->device[SLAVE].driver = NULL; - ch->device[MASTER].mode = ATA_PIO; - ch->device[SLAVE].mode = ATA_PIO; - ch->devices = 0; - ata_dmafreetags(ch); - - bus_teardown_intr(dev, ch->r_irq, ch->ih); - bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); - if (ch->r_bmio) - bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, ch->r_bmio); - bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, ch->r_altio); - bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, ch->r_io); - ch->r_io = NULL; - ch->r_altio = NULL; - ch->r_bmio = NULL; - ch->r_irq = NULL; - mpipe_done(&ch->req_mpipe); - mpipe_done(&ch->dma_mpipe); - - ATA_UNLOCK_CH(ch); - return 0; -} - -int -ata_suspend(device_t dev) -{ - struct ata_channel *ch; - - if (dev == NULL || (ch = device_get_softc(dev)) == NULL) - return ENXIO; - - /* wait for the channel to be IDLE or detached before suspending */ - while (ch->r_irq) { - crit_enter(); - if (ch->active == ATA_IDLE) { - ch->active = ATA_CONTROL; - crit_exit(); - break; - } - crit_exit(); - tsleep(ch, 0, "atasusp", hz / 10); - } - return 0; -} - -int -ata_resume(device_t dev) -{ - return ata_reinit(device_get_softc(dev)); -} - -static int -ataioctl(struct dev_ioctl_args *ap) -{ - struct ata_cmd *iocmd = (struct ata_cmd *)ap->a_data; - struct ata_channel *ch; - device_t device = devclass_get_device(ata_devclass, iocmd->channel); - int error; - - if (ap->a_cmd != IOCATA) - return ENOTTY; - - if (iocmd->channel < -1 || iocmd->device < -1 || iocmd->device > SLAVE) - return ENXIO; - - switch (iocmd->cmd) { - case ATAATTACH: - /* should enable channel HW on controller that can SOS XXX */ - error = ata_probe(device); - if (!error) - error = ata_attach(device); - return error; - - case ATADETACH: - error = ata_detach(device); - /* should disable channel HW on controller that can SOS XXX */ - return error; - - case ATAREINIT: - if (!device || !(ch = device_get_softc(device))) - return ENXIO; - crit_enter(); /* interlock non-atomic channel lock */ - ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE); - if ((error = ata_reinit(ch))) - ATA_UNLOCK_CH(ch); - crit_exit(); - return error; - - case ATAGMODE: - if (!device || !(ch = device_get_softc(device))) - return ENXIO; - - if ((iocmd->device == MASTER || iocmd->device == -1) && - ch->device[MASTER].driver) - iocmd->u.mode.mode[MASTER] = ch->device[MASTER].mode; - else - iocmd->u.mode.mode[MASTER] = -1; - - if ((iocmd->device == SLAVE || iocmd->device == -1) && - ch->device[SLAVE].param) - iocmd->u.mode.mode[SLAVE] = ch->device[SLAVE].mode; - else - iocmd->u.mode.mode[SLAVE] = -1; - return 0; - - case ATASMODE: - if (!device || !(ch = device_get_softc(device))) - return ENXIO; - - if ((iocmd->device == MASTER || iocmd->device == -1) && - iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param) { - ata_change_mode(&ch->device[MASTER],iocmd->u.mode.mode[MASTER]); - iocmd->u.mode.mode[MASTER] = ch->device[MASTER].mode; - } - else - iocmd->u.mode.mode[MASTER] = -1; - - if ((iocmd->device == SLAVE || iocmd->device == -1) && - iocmd->u.mode.mode[SLAVE] >= 0 && ch->device[SLAVE].param) { - ata_change_mode(&ch->device[SLAVE], iocmd->u.mode.mode[SLAVE]); - iocmd->u.mode.mode[SLAVE] = ch->device[SLAVE].mode; - } - else - iocmd->u.mode.mode[SLAVE] = -1; - return 0; - - case ATAGPARM: - if (!device || !(ch = device_get_softc(device))) - return ENXIO; - - iocmd->u.param.type[MASTER] = - ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER); - iocmd->u.param.type[SLAVE] = - ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE); - - if (ch->device[MASTER].name) - strcpy(iocmd->u.param.name[MASTER], ch->device[MASTER].name); - if (ch->device[SLAVE].name) - strcpy(iocmd->u.param.name[SLAVE], ch->device[SLAVE].name); - - if (ch->device[MASTER].param) - bcopy(ch->device[MASTER].param, &iocmd->u.param.params[MASTER], - sizeof(struct ata_params)); - if (ch->device[SLAVE].param) - bcopy(ch->device[SLAVE].param, &iocmd->u.param.params[SLAVE], - sizeof(struct ata_params)); - return 0; - - case ATAENCSTAT: { - struct ata_device *atadev; - - if (!device || !(ch = device_get_softc(device))) - return ENXIO; - - if (iocmd->device == SLAVE) - atadev = &ch->device[SLAVE]; - else - atadev = &ch->device[MASTER]; - - return ata_enclosure_status(atadev, - &iocmd->u.enclosure.fan, - &iocmd->u.enclosure.temp, - &iocmd->u.enclosure.v05, - &iocmd->u.enclosure.v12); - } - -#if NATADISK > 0 - case ATARAIDREBUILD: - return ata_raid_rebuild(iocmd->channel); - - case ATARAIDCREATE: - return ata_raid_create(&iocmd->u.raid_setup); - - case ATARAIDDELETE: - return ata_raid_delete(iocmd->channel); - - case ATARAIDSTATUS: - return ata_raid_status(iocmd->channel, &iocmd->u.raid_status); -#endif -#if DEV_ATAPIALL - case ATAPICMD: { - struct ata_device *atadev; - caddr_t buf; - - if (!device || !(ch = device_get_softc(device))) - return ENXIO; - - if (!(atadev = &ch->device[iocmd->device]) || - !(ch->devices & (iocmd->device == MASTER ? - ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE))) - return ENODEV; - - buf = kmalloc(iocmd->u.atapi.count, M_ATA, M_INTWAIT); - - if (iocmd->u.atapi.flags & ATAPI_CMD_WRITE) { - error = copyin(iocmd->u.atapi.data, buf, iocmd->u.atapi.count); - if (error) - return error; - } - error = atapi_queue_cmd(atadev, iocmd->u.atapi.ccb, - buf, iocmd->u.atapi.count, - (iocmd->u.atapi.flags == ATAPI_CMD_READ ? - ATPR_F_READ : 0) | ATPR_F_QUIET, - iocmd->u.atapi.timeout, NULL, NULL); - if (error) { - iocmd->u.atapi.error = error; - bcopy(&atadev->result, iocmd->u.atapi.sense_data, - sizeof(struct atapi_reqsense)); - error = 0; - } - else if (iocmd->u.atapi.flags & ATAPI_CMD_READ) - error = copyout(buf, iocmd->u.atapi.data, iocmd->u.atapi.count); - - kfree(buf, M_ATA); - return error; - } -#endif - default: - break; - } - return ENOTTY; -} - -static int -ata_getparam(struct ata_device *atadev, u_int8_t command) -{ - struct ata_params *ata_parm; - int retry = 0; - - ata_parm = kmalloc(sizeof(struct ata_params), M_ATA, M_INTWAIT); - - /* apparently some devices needs this repeated */ - do { - if (ata_command(atadev, command, 0, 0, 0, ATA_IMMEDIATE)) { - ata_prtdev(atadev, "%s identify failed\n", - command == ATA_C_ATAPI_IDENTIFY ? "ATAPI" : "ATA"); - kfree(ata_parm, M_ATA); - return -1; - } - if (retry++ > 4) { - ata_prtdev(atadev, "%s identify retries exceeded\n", - command == ATA_C_ATAPI_IDENTIFY ? "ATAPI" : "ATA"); - kfree(ata_parm, M_ATA); - return -1; - } - } while (ata_wait(atadev, ((command == ATA_C_ATAPI_IDENTIFY) ? - ATA_S_DRQ : (ATA_S_READY|ATA_S_DSC|ATA_S_DRQ)))); - ATA_INSW(atadev->channel->r_io, ATA_DATA, (int16_t *)ata_parm, - sizeof(struct ata_params)/sizeof(int16_t)); - - if (command == ATA_C_ATA_IDENTIFY || - !((ata_parm->model[0] == 'N' && ata_parm->model[1] == 'E') || - (ata_parm->model[0] == 'F' && ata_parm->model[1] == 'X') || - (ata_parm->model[0] == 'P' && ata_parm->model[1] == 'i'))) - bswap(ata_parm->model, sizeof(ata_parm->model)); - btrim(ata_parm->model, sizeof(ata_parm->model)); - bpack(ata_parm->model, ata_parm->model, sizeof(ata_parm->model)); - bswap(ata_parm->revision, sizeof(ata_parm->revision)); - btrim(ata_parm->revision, sizeof(ata_parm->revision)); - bpack(ata_parm->revision, ata_parm->revision, sizeof(ata_parm->revision)); - bswap(ata_parm->serial, sizeof(ata_parm->serial)); - btrim(ata_parm->serial, sizeof(ata_parm->serial)); - bpack(ata_parm->serial, ata_parm->serial, sizeof(ata_parm->serial)); - atadev->param = ata_parm; - return 0; -} - -#if 0 - -static void -ata_boot_attach(void) -{ - struct ata_channel *ch; - int ctlr; - - crit_enter(); - - /* - * run through all ata devices and look for real ATA & ATAPI devices - * using the hints we found in the early probe, this avoids some of - * the delays probing of non-exsistent devices can cause. - */ - for (ctlr=0; ctlrdevices & ATA_ATA_SLAVE) - if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY)) - ch->devices &= ~ATA_ATA_SLAVE; - if (ch->devices & ATA_ATAPI_SLAVE) - if (ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY)) - ch->devices &= ~ATA_ATAPI_SLAVE; - if (ch->devices & ATA_ATA_MASTER) - if (ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY)) - ch->devices &= ~ATA_ATA_MASTER; - if (ch->devices & ATA_ATAPI_MASTER) - if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY)) - ch->devices &= ~ATA_ATAPI_MASTER; - } - -#if NATADISK > 0 - /* now we know whats there, do the real attach, first the ATA disks */ - for (ctlr=0; ctlrdevices & ATA_ATA_MASTER) - ad_attach(&ch->device[MASTER], 0); - if (ch->devices & ATA_ATA_SLAVE) - ad_attach(&ch->device[SLAVE], 0); - } - ata_raid_attach(); -#endif -#if DEV_ATAPIALL - /* then the atapi devices */ - for (ctlr=0; ctlrdevices & ATA_ATAPI_MASTER) - atapi_attach(&ch->device[MASTER], 0); - if (ch->devices & ATA_ATAPI_SLAVE) - atapi_attach(&ch->device[SLAVE], 0); -#if NATAPICAM > 0 - atapi_cam_attach_bus(ch); -#endif - } -#endif - crit_exit(); -} - -#endif - -static void -ata_intr(void *data) -{ - struct ata_channel *ch = (struct ata_channel *)data; - /* - * on PCI systems we might share an interrupt line with another - * device or our twin ATA channel, so call ch->intr_func to figure - * out if it is really an interrupt we should process here - */ - if (ch->intr_func && ch->intr_func(ch)) - return; - - /* if drive is busy it didn't interrupt */ - if (ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_BUSY) { - DELAY(100); - if (!(ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_DRQ)) - return; - } - - /* clear interrupt and get status */ - ch->status = ATA_INB(ch->r_io, ATA_STATUS); - - if (ch->status & ATA_S_ERROR) - ch->error = ATA_INB(ch->r_io, ATA_ERROR); - - /* find & call the responsible driver to process this interrupt */ - switch (ch->active) { -#if NATADISK > 0 - case ATA_ACTIVE_ATA: - if (!ch->running || ad_interrupt(ch->running) == ATA_OP_CONTINUES) - return; - break; -#endif -#if DEV_ATAPIALL - case ATA_ACTIVE_ATAPI: - if (!ch->running || atapi_interrupt(ch->running) == ATA_OP_CONTINUES) - return; - break; -#endif - case ATA_WAIT_INTR: - case ATA_WAIT_INTR | ATA_CONTROL: - wakeup((caddr_t)ch); - break; - - case ATA_WAIT_READY: - case ATA_WAIT_READY | ATA_CONTROL: - break; - - case ATA_IDLE: - if (ch->flags & ATA_QUEUED) { - ch->active = ATA_ACTIVE; - if (ata_service(ch) == ATA_OP_CONTINUES) - return; - } - /* FALLTHROUGH */ - - default: -#ifdef ATA_DEBUG - { - static int intr_count = 0; - - if (intr_count++ < 10) - ata_printf(ch, -1, "unwanted interrupt #%d active=%02x s=%02x\n", - intr_count, ch->active, ch->status); - } -#endif - break; - } - ch->active &= ATA_CONTROL; - if (ch->active & ATA_CONTROL) - return; - ch->running = NULL; - ata_start(ch); - return; -} - -void -ata_start(struct ata_channel *ch) -{ -#if NATADISK > 0 - struct ad_request *ad_request; -#endif -#if DEV_ATAPIALL - struct atapi_request *atapi_request; -#endif - - crit_enter(); /* interlock non-atomic channel lock */ - if (!ATA_LOCK_CH(ch, ATA_ACTIVE)) { - crit_exit(); - return; - } - -#if NATADISK > 0 - /* find & call the responsible driver if anything on the ATA queue */ - if (TAILQ_EMPTY(&ch->ata_queue)) { - if (ch->devices & (ATA_ATA_MASTER) && ch->device[MASTER].driver) - ad_start(&ch->device[MASTER]); - if (ch->devices & (ATA_ATA_SLAVE) && ch->device[SLAVE].driver) - ad_start(&ch->device[SLAVE]); - } - if ((ad_request = TAILQ_FIRST(&ch->ata_queue))) { - TAILQ_REMOVE(&ch->ata_queue, ad_request, chain); - ch->active = ATA_ACTIVE_ATA; - ch->running = ad_request; - - /* - * The donecount had better be 0 here because the channel may not - * have retained the setup for the request (if a retry). - */ - KKASSERT(ad_request->donecount == 0); - if (ad_transfer(ad_request) == ATA_OP_CONTINUES) { - crit_exit(); - return; - } - } - -#endif -#if DEV_ATAPIALL - /* find & call the responsible driver if anything on the ATAPI queue */ - if (TAILQ_EMPTY(&ch->atapi_queue)) { - if (ch->devices & (ATA_ATAPI_MASTER) && ch->device[MASTER].driver) - atapi_start(&ch->device[MASTER]); - if (ch->devices & (ATA_ATAPI_SLAVE) && ch->device[SLAVE].driver) - atapi_start(&ch->device[SLAVE]); - } - if ((atapi_request = TAILQ_FIRST(&ch->atapi_queue))) { - TAILQ_REMOVE(&ch->atapi_queue, atapi_request, chain); - ch->active = ATA_ACTIVE_ATAPI; - ch->running = atapi_request; - if (atapi_transfer(atapi_request) == ATA_OP_CONTINUES) { - crit_exit(); - return; - } - } -#endif - ATA_UNLOCK_CH(ch); - crit_exit(); -} - -void -ata_reset(struct ata_channel *ch) -{ - u_int8_t lsb, msb, ostat0, ostat1; - u_int8_t stat0 = 0, stat1 = 0; - int mask = 0, timeout; - - /* do we have any signs of ATA/ATAPI HW being present ? */ - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); - DELAY(10); - ostat0 = ATA_INB(ch->r_io, ATA_STATUS); - if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) { - stat0 = ATA_S_BUSY; - mask |= 0x01; - } - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); - DELAY(10); - ostat1 = ATA_INB(ch->r_io, ATA_STATUS); - if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) { - stat1 = ATA_S_BUSY; - mask |= 0x02; - } - - ch->devices = 0; - if (!mask) - return; - - /* in some setups we dont want to test for a slave */ - if (ch->flags & ATA_NO_SLAVE) { - stat1 = 0x0; - mask &= ~0x02; - } - - if (bootverbose) - ata_printf(ch, -1, "mask=%02x ostat0=%02x ostat2=%02x\n", - mask, ostat0, ostat1); - - /* reset channel */ - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); - DELAY(10); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_RESET); - DRIVERSLEEP(10000); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_IDS); - DRIVERSLEEP(100000); - ATA_INB(ch->r_io, ATA_ERROR); - - /* wait for BUSY to go inactive */ - for (timeout = 0; timeout < 3100; timeout++) { - if (stat0 & ATA_S_BUSY) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); - DELAY(10); - - /* check for ATAPI signature while its still there */ - lsb = ATA_INB(ch->r_io, ATA_CYL_LSB); - msb = ATA_INB(ch->r_io, ATA_CYL_MSB); - stat0 = ATA_INB(ch->r_io, ATA_STATUS); - if (!(stat0 & ATA_S_BUSY)) { - if (bootverbose) - ata_printf(ch, ATA_MASTER, "ATAPI %02x %02x\n", lsb, msb); - if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB) - ch->devices |= ATA_ATAPI_MASTER; - } - } - if (stat1 & ATA_S_BUSY) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); - DELAY(10); - - /* check for ATAPI signature while its still there */ - lsb = ATA_INB(ch->r_io, ATA_CYL_LSB); - msb = ATA_INB(ch->r_io, ATA_CYL_MSB); - stat1 = ATA_INB(ch->r_io, ATA_STATUS); - if (!(stat1 & ATA_S_BUSY)) { - if (bootverbose) - ata_printf(ch, ATA_SLAVE, "ATAPI %02x %02x\n", lsb, msb); - if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB) - ch->devices |= ATA_ATAPI_SLAVE; - } - } - if (mask == 0x01) /* wait for master only */ - if (!(stat0 & ATA_S_BUSY)) - break; - if (mask == 0x02) /* wait for slave only */ - if (!(stat1 & ATA_S_BUSY)) - break; - if (mask == 0x03) /* wait for both master & slave */ - if (!(stat0 & ATA_S_BUSY) && !(stat1 & ATA_S_BUSY)) - break; - DRIVERSLEEP(10000); - } - /* - * some devices release BUSY before they are ready to accept commands. - * We must wait at least 50ms before attempting to issue a command after - * BUSY is released. - */ - DRIVERSLEEP(50000); - ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_4BIT); - - if (stat0 & ATA_S_BUSY) - mask &= ~0x01; - if (stat1 & ATA_S_BUSY) - mask &= ~0x02; - if (bootverbose) - ata_printf(ch, -1, "mask=%02x stat0=%02x stat1=%02x\n", - mask, stat0, stat1); - if (!mask) - return; - - if (mask & 0x01 && ostat0 != 0x00 && !(ch->devices & ATA_ATAPI_MASTER)) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); - DELAY(10); - ATA_OUTB(ch->r_io, ATA_ERROR, 0x58); - ATA_OUTB(ch->r_io, ATA_CYL_LSB, 0xa5); - lsb = ATA_INB(ch->r_io, ATA_ERROR); - msb = ATA_INB(ch->r_io, ATA_CYL_LSB); - if (bootverbose) - ata_printf(ch, ATA_MASTER, "ATA %02x %02x\n", lsb, msb); - if (lsb != 0x58 && msb == 0xa5) - ch->devices |= ATA_ATA_MASTER; - } - if (mask & 0x02 && ostat1 != 0x00 && !(ch->devices & ATA_ATAPI_SLAVE)) { - ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); - DELAY(10); - ATA_OUTB(ch->r_io, ATA_ERROR, 0x58); - ATA_OUTB(ch->r_io, ATA_CYL_LSB, 0xa5); - lsb = ATA_INB(ch->r_io, ATA_ERROR); - msb = ATA_INB(ch->r_io, ATA_CYL_LSB); - if (bootverbose) - ata_printf(ch, ATA_SLAVE, "ATA %02x %02x\n", lsb, msb); - if (lsb != 0x58 && msb == 0xa5) - ch->devices |= ATA_ATA_SLAVE; - } - if (bootverbose) - ata_printf(ch, -1, "devices=%02x\n", ch->devices); -} - -int -ata_reinit(struct ata_channel *ch) -{ - int devices, misdev, newdev; - - if (!ch->r_io || !ch->r_altio || !ch->r_irq) - return ENXIO; - - ATA_FORCELOCK_CH(ch, ATA_CONTROL); - ch->running = NULL; - devices = ch->devices; - ata_printf(ch, -1, "resetting devices .. "); - ata_reset(ch); - - if ((misdev = devices & ~ch->devices)) { - if (misdev) - kprintf("\n"); -#if NATADISK > 0 - if (misdev & ATA_ATA_MASTER && ch->device[MASTER].driver) - ad_detach(&ch->device[MASTER], 0); - if (misdev & ATA_ATA_SLAVE && ch->device[SLAVE].driver) - ad_detach(&ch->device[SLAVE], 0); -#endif -#if DEV_ATAPIALL - if (misdev & ATA_ATAPI_MASTER && ch->device[MASTER].driver) - atapi_detach(&ch->device[MASTER]); - if (misdev & ATA_ATAPI_SLAVE && ch->device[SLAVE].driver) - atapi_detach(&ch->device[SLAVE]); -#endif - if (misdev & ATA_ATA_MASTER || misdev & ATA_ATAPI_MASTER) { - if (ch->device[MASTER].param) - kfree(ch->device[MASTER].param, M_ATA); - ch->device[MASTER].param = NULL; - } - if (misdev & ATA_ATA_SLAVE || misdev & ATA_ATAPI_SLAVE) { - if (ch->device[SLAVE].param) - kfree(ch->device[SLAVE].param, M_ATA); - ch->device[SLAVE].param = NULL; - } - } - if ((newdev = ~devices & ch->devices)) { - if (newdev & ATA_ATA_MASTER) - if (ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY)) - ch->devices &= ~ATA_ATA_MASTER; - if (newdev & ATA_ATA_SLAVE) - if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY)) - ch->devices &= ~ATA_ATA_SLAVE; - if (newdev & ATA_ATAPI_MASTER) - if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY)) - ch->devices &= ~ATA_ATAPI_MASTER; - if (newdev & ATA_ATAPI_SLAVE) - if (ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY)) - ch->devices &= ~ATA_ATAPI_SLAVE; - } - newdev = ~devices & ch->devices; - if (!misdev && newdev) - kprintf("\n"); -#if NATADISK > 0 - if (newdev & ATA_ATA_MASTER && !ch->device[MASTER].driver) - ad_attach(&ch->device[MASTER], 1); - else if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) { - ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY); - ad_reinit(&ch->device[MASTER]); - } - if (newdev & ATA_ATA_SLAVE && !ch->device[SLAVE].driver) - ad_attach(&ch->device[SLAVE], 1); - else if (ch->devices & (ATA_ATA_SLAVE) && ch->device[SLAVE].driver) { - ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY); - ad_reinit(&ch->device[SLAVE]); - } -#endif -#if DEV_ATAPIALL - if (newdev & ATA_ATAPI_MASTER && !ch->device[MASTER].driver) - atapi_attach(&ch->device[MASTER], 1); - else if (ch->devices & (ATA_ATAPI_MASTER) && ch->device[MASTER].driver) { - ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY); - atapi_reinit(&ch->device[MASTER]); - } - if (newdev & ATA_ATAPI_SLAVE && !ch->device[SLAVE].driver) - atapi_attach(&ch->device[SLAVE], 1); - else if (ch->devices & (ATA_ATAPI_SLAVE) && ch->device[SLAVE].driver) { - ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY); - atapi_reinit(&ch->device[SLAVE]); - } -#endif -#if NATAPICAM > 0 - if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE)) - atapi_cam_reinit_bus(ch); -#endif - kprintf("done\n"); - ATA_UNLOCK_CH(ch); - ata_start(ch); - return 0; -} - -static int -ata_service(struct ata_channel *ch) -{ - /* do we have a SERVICE request from the drive ? */ - if ((ch->status & (ATA_S_SERVICE|ATA_S_ERROR|ATA_S_DRQ)) == ATA_S_SERVICE) { - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - ata_dmastatus(ch) | ATA_BMSTAT_INTERRUPT); -#if NATADISK > 0 - if ((ATA_INB(ch->r_io, ATA_DRIVE) & ATA_SLAVE) == ATA_MASTER) { - if ((ch->devices & ATA_ATA_MASTER) && ch->device[MASTER].driver) - return ad_service((struct ad_softc *) - ch->device[MASTER].driver, 0); - } - else { - if ((ch->devices & ATA_ATA_SLAVE) && ch->device[SLAVE].driver) - return ad_service((struct ad_softc *) - ch->device[SLAVE].driver, 0); - } -#endif - } - return ATA_OP_FINISHED; -} - -int -ata_wait(struct ata_device *atadev, u_int8_t mask) -{ - int timeout = 0; - - DELAY(1); - while (timeout < 5000000) { /* timeout 5 secs */ - atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS); - - /* if drive fails status, reselect the drive just to be sure */ - if (atadev->channel->status == 0xff) { - ata_prtdev(atadev, "no status, reselecting device\n"); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM|atadev->unit); - DELAY(10); - atadev->channel->status = ATA_INB(atadev->channel->r_io,ATA_STATUS); - if (atadev->channel->status == 0xff) - return -1; - } - - /* are we done ? */ - if (!(atadev->channel->status & ATA_S_BUSY)) - break; - - if (timeout > 1000) { - timeout += 1000; - DELAY(1000); - } - else { - timeout += 10; - DELAY(10); - } - } - if (atadev->channel->status & ATA_S_ERROR) - atadev->channel->error = ATA_INB(atadev->channel->r_io, ATA_ERROR); - if (timeout >= 5000000) - return -1; - if (!mask) - return (atadev->channel->status & ATA_S_ERROR); - - /* Wait 50 msec for bits wanted. */ - timeout = 5000; - while (timeout--) { - atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS); - if ((atadev->channel->status & mask) == mask) { - if (atadev->channel->status & ATA_S_ERROR) - atadev->channel->error=ATA_INB(atadev->channel->r_io,ATA_ERROR); - return (atadev->channel->status & ATA_S_ERROR); - } - DELAY (10); - } - return -1; -} - -int -ata_command(struct ata_device *atadev, u_int8_t command, - u_int64_t lba, u_int16_t count, u_int8_t feature, int flags) -{ - int error = 0; -#ifdef ATA_DEBUG - ata_prtdev(atadev, "ata_command: addr=%04lx, cmd=%02x, " - "lba=%lld, count=%d, feature=%d, flags=%02x\n", - rman_get_start(atadev->channel->r_io), - command, lba, count, feature, flags); -#endif - - /* select device */ - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); - - /* disable interrupt from device */ - if (atadev->channel->flags & ATA_QUEUED) - ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT); - - /* ready to issue command ? */ - if (ata_wait(atadev, 0) < 0) { - ata_prtdev(atadev, "timeout sending command=%02x s=%02x e=%02x\n", - command, atadev->channel->status, atadev->channel->error); - return -1; - } - - /* only use 48bit addressing if needed because of the overhead */ - if ((lba >= 268435455 || count > 256) && atadev->param && - atadev->param->support.address48) { - ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, (feature>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, feature); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, (count>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, count & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, (lba>>24) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, lba & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>32) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>40) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>16) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_LBA | atadev->unit); - - /* translate command into 48bit version */ - switch (command) { - case ATA_C_READ: - command = ATA_C_READ48; break; - case ATA_C_READ_MUL: - command = ATA_C_READ_MUL48; break; - case ATA_C_READ_DMA: - command = ATA_C_READ_DMA48; break; - case ATA_C_READ_DMA_QUEUED: - command = ATA_C_READ_DMA_QUEUED48; break; - case ATA_C_WRITE: - command = ATA_C_WRITE48; break; - case ATA_C_WRITE_MUL: - command = ATA_C_WRITE_MUL48; break; - case ATA_C_WRITE_DMA: - command = ATA_C_WRITE_DMA48; break; - case ATA_C_WRITE_DMA_QUEUED: - command = ATA_C_WRITE_DMA_QUEUED48; break; - case ATA_C_FLUSHCACHE: - command = ATA_C_FLUSHCACHE48; break; - default: - ata_prtdev(atadev, "can't translate cmd to 48bit version\n"); - return -1; - } - } - else { - ATA_OUTB(atadev->channel->r_io, ATA_FEATURE, feature); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, count); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, lba & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_LSB, (lba>>8) & 0xff); - ATA_OUTB(atadev->channel->r_io, ATA_CYL_MSB, (lba>>16) & 0xff); - if (atadev->flags & ATA_D_USE_CHS) - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, - ATA_D_IBM | atadev->unit | ((lba>>24) & 0xf)); - else - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, - ATA_D_IBM | ATA_D_LBA | atadev->unit | ((lba>>24) &0xf)); - } - - switch (flags & ATA_WAIT_MASK) { - case ATA_IMMEDIATE: - ATA_OUTB(atadev->channel->r_io, ATA_CMD, command); - - /* enable interrupt */ - if (atadev->channel->flags & ATA_QUEUED) - ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_4BIT); - break; - - case ATA_WAIT_INTR: - atadev->channel->active |= ATA_WAIT_INTR; - ATA_OUTB(atadev->channel->r_io, ATA_CMD, command); - - /* enable interrupt */ - if (atadev->channel->flags & ATA_QUEUED) - ATA_OUTB(atadev->channel->r_altio, ATA_ALTSTAT, ATA_A_4BIT); - - if (tsleep((caddr_t)atadev->channel, 0, "atacmd", 10 * hz)) { - ata_prtdev(atadev, "timeout waiting for interrupt\n"); - atadev->channel->active &= ~ATA_WAIT_INTR; - error = -1; - } - break; - - case ATA_WAIT_READY: - atadev->channel->active |= ATA_WAIT_READY; - ATA_OUTB(atadev->channel->r_io, ATA_CMD, command); - if (ata_wait(atadev, ATA_S_READY) < 0) { - ata_prtdev(atadev, "timeout waiting for cmd=%02x s=%02x e=%02x\n", - command, atadev->channel->status,atadev->channel->error); - error = -1; - } - atadev->channel->active &= ~ATA_WAIT_READY; - break; - } - return error; -} - -static void -ata_enclosure_start(struct ata_device *atadev) -{ - ATA_INB(atadev->channel->r_io, ATA_DRIVE); - DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_DRIVE); - DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_CMD); - DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); - DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); - DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); - DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_COUNT); - DELAY(1); - ATA_INB(atadev->channel->r_io, ATA_DRIVE); - DELAY(1); -} - -static void -ata_enclosure_end(struct ata_device *atadev) -{ - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); - DELAY(1); -} - -static void -ata_enclosure_chip_start(struct ata_device *atadev) -{ - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0b); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0a); - DELAY(25); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08); -} - -static void -ata_enclosure_chip_end(struct ata_device *atadev) -{ - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08); - DELAY(64); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0a); - DELAY(25); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x0b); - DELAY(64); -} - -static u_int8_t -ata_enclosure_chip_rdbit(struct ata_device *atadev) -{ - u_int8_t val; - - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0); - DELAY(64); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x02); - DELAY(25); - val = ATA_INB(atadev->channel->r_io, ATA_SECTOR) & 0x01; - DELAY(38); - return val; -} - -static void -ata_enclosure_chip_wrbit(struct ata_device *atadev, u_int8_t data) -{ - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08 | (data & 0x01)); - DELAY(64); - ATA_OUTB(atadev->channel->r_io, ATA_SECTOR, 0x08 | 0x02 | (data & 0x01)); - DELAY(64); -} - -static u_int8_t -ata_enclosure_chip_rw(struct ata_device *atadev, int rw, u_int8_t val) -{ - int i; - - if (rw) { - for (i = 0; i < 8; i++) - ata_enclosure_chip_wrbit(atadev, (val & (0x80 >> i)) ? 1 : 0); - } - else { - for (i = 0; i < 8; i++) - val = (val << 1) | ata_enclosure_chip_rdbit(atadev); - } - ata_enclosure_chip_wrbit(atadev, 0); - return val; -} - -static u_int8_t -ata_enclosure_sensor(struct ata_device *atadev, - int rw, u_int8_t idx, u_int8_t data) -{ - ata_enclosure_start(atadev); - ata_enclosure_chip_start(atadev); - ata_enclosure_chip_rw(atadev, 1, 0x5a); - ata_enclosure_chip_rw(atadev, 1, idx); - if (rw) { - ata_enclosure_chip_rw(atadev, 1, data); - } - else { - ata_enclosure_chip_end(atadev); - ata_enclosure_chip_start(atadev); - ata_enclosure_chip_rw(atadev, 1, 0x5b); - data = ata_enclosure_chip_rw(atadev, 0, 0); - } - ata_enclosure_chip_end(atadev); - ata_enclosure_end(atadev); - return data; -} - -static int -ata_enclosure_status(struct ata_device *atadev, - int *fan, int *temp, int *v05, int *v12) -{ - u_int8_t id1, id2, cnt, div; - int error = ENXIO; - - if (atadev->flags & ATA_D_ENC_PRESENT) { - ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); - ata_enclosure_sensor(atadev, 1, 0x4e, 0); - id1 = ata_enclosure_sensor(atadev, 0, 0x4f, 0); - ata_enclosure_sensor(atadev, 1, 0x4e, 0x80); - id2 = ata_enclosure_sensor(atadev, 0, 0x4f, 0); - if (id1 == 0xa3 && id2 == 0x5c) { - div = 1 << (((ata_enclosure_sensor(atadev, 0, 0x5d, 0)&0x20)>>3)+ - ((ata_enclosure_sensor(atadev, 0, 0x47, 0)&0x30)>>4)+1); - cnt = ata_enclosure_sensor(atadev, 0, 0x28, 0); - if (cnt == 0xff) - *fan = 0; - else - *fan = 1350000 / cnt / div; - ata_enclosure_sensor(atadev, 1, 0x4e, 0x01); - *temp = (ata_enclosure_sensor(atadev, 0, 0x50, 0) * 10) + - (ata_enclosure_sensor(atadev, 0, 0x50, 0) & 0x80 ? 5 : 0); - *v05 = ata_enclosure_sensor(atadev, 0, 0x23, 0) * 27; - *v12 = ata_enclosure_sensor(atadev, 0, 0x24, 0) * 61; - error = 0; - } - ATA_UNLOCK_CH(atadev->channel); - } - return error; -} - -void -ata_enclosure_print(struct ata_device *atadev) -{ - u_int8_t id, st; - int fan, temp, v05, v12; - - ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); - ata_enclosure_start(atadev); - id = ATA_INB(atadev->channel->r_io, ATA_DRIVE); - DELAY(1); - st = ATA_INB(atadev->channel->r_io, ATA_COUNT); - DELAY(1); - ata_enclosure_end(atadev); - ATA_UNLOCK_CH(atadev->channel); - - switch (id & 0x93) { - case 0x00: - ata_prtdev(atadev, "Universal enclosure"); - break; - case 0x01: - ata_prtdev(atadev, "FastSwap enclosure"); - break; - case 0x10: - case 0x11: - ata_prtdev(atadev, "SuperSwap enclosure"); - break; - default: - atadev->flags &= ~ATA_D_ENC_PRESENT; - return; - } - atadev->flags |= ATA_D_ENC_PRESENT; - - if (ata_enclosure_status(atadev, &fan, &temp, &v05, &v12)) - kprintf(" detected\n"); - else - kprintf(" [FAN:%drpm TEMP:%d.%01dC %d.%03dV %d.%03dV]\n", - fan, temp/10, temp%10, v05/1000, v05%1000, v12/1000, v12%1000); -} - -void -ata_enclosure_leds(struct ata_device *atadev, u_int8_t color) -{ - if (atadev->flags & ATA_D_ENC_PRESENT) { - u_int8_t reg; - - ata_enclosure_start(atadev); - reg = ATA_INB(atadev->channel->r_io, ATA_COUNT); - DELAY(1); - ATA_OUTB(atadev->channel->r_io, ATA_COUNT, - (color & ATA_LED_MASK) | (reg & ~ATA_LED_MASK)); - DELAY(1); - ata_enclosure_end(atadev); - } -} - -static void -ata_change_mode(struct ata_device *atadev, int mode) -{ - int umode, wmode, pmode; - - umode = ata_umode(atadev->param); - wmode = ata_wmode(atadev->param); - pmode = ata_pmode(atadev->param); - - switch (mode & ATA_DMA_MASK) { - case ATA_UDMA: - if ((mode & ATA_MODE_MASK) < umode) - umode = mode & ATA_MODE_MASK; - break; - case ATA_WDMA: - if ((mode & ATA_MODE_MASK) < wmode) - wmode = mode & ATA_MODE_MASK; - umode = -1; - break; - default: - if (((mode & ATA_MODE_MASK) - ATA_PIO0) < pmode) - pmode = (mode & ATA_MODE_MASK) - ATA_PIO0; - umode = -1; - wmode = -1; - } - - crit_enter(); /* interlock non-atomic channel lock */ - ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE); - ata_dmainit(atadev, pmode, wmode, umode); - ATA_UNLOCK_CH(atadev->channel); - crit_exit(); - ata_start(atadev->channel); /* XXX SOS */ -} - -int -ata_printf(struct ata_channel *ch, int device, const char * fmt, ...) -{ - __va_list ap; - int ret; - - if (device == -1) - ret = kprintf("ata%d: ", device_get_unit(ch->dev)); - else { - if (ch->device[ATA_DEV(device)].name) - ret = kprintf("%s: ", ch->device[ATA_DEV(device)].name); - else - ret = kprintf("ata%d-%s: ", device_get_unit(ch->dev), - (device == ATA_MASTER) ? "master" : "slave"); - } - __va_start(ap, fmt); - ret += kvprintf(fmt, ap); - __va_end(ap); - return ret; -} - -int -ata_prtdev(struct ata_device *atadev, const char * fmt, ...) -{ - __va_list ap; - int ret; - - if (atadev->name) - ret = kprintf("%s: ", atadev->name); - else - ret = kprintf("ata%d-%s: ", device_get_unit(atadev->channel->dev), - (atadev->unit == ATA_MASTER) ? "master" : "slave"); - __va_start(ap, fmt); - ret += kvprintf(fmt, ap); - __va_end(ap); - return ret; -} - -void -ata_set_name(struct ata_device *atadev, char *name, int lun) -{ - atadev->name = kmalloc(strlen(name) + 4, M_ATA, M_INTWAIT); - ksprintf(atadev->name, "%s%d", name, lun); -} - -void -ata_free_name(struct ata_device *atadev) -{ - if (atadev->name) - kfree(atadev->name, M_ATA); - atadev->name = NULL; -} - -int -ata_get_lun(u_int32_t *map) -{ - int lun = ffs(~*map) - 1; - - *map |= (1 << lun); - return lun; -} - -int -ata_test_lun(u_int32_t *map, int lun) -{ - return (*map & (1 << lun)); -} - -void -ata_free_lun(u_int32_t *map, int lun) -{ - *map &= ~(1 << lun); -} - -char * -ata_mode2str(int mode) -{ - switch (mode) { - case ATA_PIO: return "BIOSPIO"; - case ATA_PIO0: return "PIO0"; - case ATA_PIO1: return "PIO1"; - case ATA_PIO2: return "PIO2"; - case ATA_PIO3: return "PIO3"; - case ATA_PIO4: return "PIO4"; - case ATA_DMA: return "BIOSDMA"; - case ATA_WDMA2: return "WDMA2"; - case ATA_UDMA2: return "UDMA33"; - case ATA_UDMA4: return "UDMA66"; - case ATA_UDMA5: return "UDMA100"; - case ATA_UDMA6: return "UDMA133"; - default: return "???"; - } -} - -int -ata_pmode(struct ata_params *ap) -{ - if (ap->atavalid & ATA_FLAG_64_70) { - if (ap->apiomodes & 2) - return 4; - if (ap->apiomodes & 1) - return 3; - } - if (ap->retired_piomode == 2) - return 2; - if (ap->retired_piomode == 1) - return 1; - if (ap->retired_piomode == 0) - return 0; - return -1; -} - -int -ata_wmode(struct ata_params *ap) -{ - if (ap->mwdmamodes & 0x04) - return 2; - if (ap->mwdmamodes & 0x02) - return 1; - if (ap->mwdmamodes & 0x01) - return 0; - return -1; -} - -int -ata_umode(struct ata_params *ap) -{ - if (ap->atavalid & ATA_FLAG_88) { - if (ap->udmamodes & 0x40) - return 6; - if (ap->udmamodes & 0x20) - return 5; - if (ap->udmamodes & 0x10) - return 4; - if (ap->udmamodes & 0x08) - return 3; - if (ap->udmamodes & 0x04) - return 2; - if (ap->udmamodes & 0x02) - return 1; - if (ap->udmamodes & 0x01) - return 0; - } - return -1; -} - -static void -bswap(int8_t *buf, int len) -{ - u_int16_t *ptr = (u_int16_t*)(buf + len); - - while (--ptr >= (u_int16_t*)buf) - *ptr = ntohs(*ptr); -} - -static void -btrim(int8_t *buf, int len) -{ - int8_t *ptr; - - for (ptr = buf; ptr < buf+len; ++ptr) - if (!*ptr) - *ptr = ' '; - for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr) - *ptr = 0; -} - -static void -bpack(int8_t *src, int8_t *dst, int len) -{ - int i, j, blank; - - for (i = j = blank = 0 ; i < len; i++) { - if (blank && src[i] == ' ') continue; - if (blank && src[i] != ' ') { - dst[j++] = src[i]; - blank = 0; - continue; - } - if (src[i] == ' ') { - blank = 1; - if (i == 0) - continue; - } - dst[j++] = src[i]; - } - if (j < len) - dst[j] = 0x00; -} - -static void -ata_init(void) -{ - make_dev(&ata_ops, 0, UID_ROOT, GID_OPERATOR, 0600, "ata"); -} - -SYSINIT(atadev, SI_SUB_DRIVERS, SI_ORDER_SECOND, ata_init, NULL) diff --git a/sys/dev/disk/ata/ata-all.h b/sys/dev/disk/ata/ata-all.h deleted file mode 100644 index dbc026e4e3..0000000000 --- a/sys/dev/disk/ata/ata-all.h +++ /dev/null @@ -1,345 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-all.h,v 1.26.2.12 2003/01/30 07:19:59 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/ata-all.h,v 1.8 2006/10/12 04:02:37 y0netan1 Exp $ - */ - -#ifndef _SYS_MPIPE_H_ -#include -#endif - -/* ATA register defines */ -#define ATA_DATA 0x00 /* data register */ -#define ATA_ERROR 0x01 /* (R) error register */ -#define ATA_E_NM 0x02 /* no media */ -#define ATA_E_ABORT 0x04 /* command aborted */ -#define ATA_E_MCR 0x08 /* media change request */ -#define ATA_E_IDNF 0x10 /* ID not found */ -#define ATA_E_MC 0x20 /* media changed */ -#define ATA_E_UNC 0x40 /* uncorrectable data */ -#define ATA_E_ICRC 0x80 /* UDMA crc error */ - -#define ATA_FEATURE 0x01 /* (W) feature register */ -#define ATA_F_DMA 0x01 /* enable DMA */ -#define ATA_F_OVL 0x02 /* enable overlap */ - -#define ATA_COUNT 0x02 /* (W) sector count */ -#define ATA_IREASON 0x02 /* (R) interrupt reason */ -#define ATA_I_CMD 0x01 /* cmd (1) | data (0) */ -#define ATA_I_IN 0x02 /* read (1) | write (0) */ -#define ATA_I_RELEASE 0x04 /* released bus (1) */ -#define ATA_I_TAGMASK 0xf8 /* tag mask */ - -#define ATA_SECTOR 0x03 /* sector # */ -#define ATA_CYL_LSB 0x04 /* cylinder# LSB */ -#define ATA_CYL_MSB 0x05 /* cylinder# MSB */ -#define ATA_DRIVE 0x06 /* Sector/Drive/Head register */ -#define ATA_D_LBA 0x40 /* use LBA addressing */ -#define ATA_D_IBM 0xa0 /* 512 byte sectors, ECC */ - -#define ATA_CMD 0x07 /* command register */ -#define ATA_C_NOP 0x00 /* NOP command */ -#define ATA_C_F_FLUSHQUEUE 0x00 /* flush queued cmd's */ -#define ATA_C_F_AUTOPOLL 0x01 /* start autopoll function */ -#define ATA_C_ATAPI_RESET 0x08 /* reset ATAPI device */ -#define ATA_C_READ 0x20 /* read command */ -#define ATA_C_READ48 0x24 /* read command */ -#define ATA_C_READ_DMA48 0x25 /* read w/DMA command */ -#define ATA_C_READ_DMA_QUEUED48 0x26 /* read w/DMA QUEUED command */ -#define ATA_C_READ_MUL48 0x29 /* read multi command */ -#define ATA_C_WRITE 0x30 /* write command */ -#define ATA_C_WRITE48 0x34 /* write command */ -#define ATA_C_WRITE_DMA48 0x35 /* write w/DMA command */ -#define ATA_C_WRITE_DMA_QUEUED48 0x36 /* write w/DMA QUEUED command */ -#define ATA_C_WRITE_MUL48 0x39 /* write multi command */ -#define ATA_C_PACKET_CMD 0xa0 /* packet command */ -#define ATA_C_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/ -#define ATA_C_SERVICE 0xa2 /* service command */ -#define ATA_C_READ_MUL 0xc4 /* read multi command */ -#define ATA_C_WRITE_MUL 0xc5 /* write multi command */ -#define ATA_C_SET_MULTI 0xc6 /* set multi size command */ -#define ATA_C_READ_DMA_QUEUED 0xc7 /* read w/DMA QUEUED command */ -#define ATA_C_READ_DMA 0xc8 /* read w/DMA command */ -#define ATA_C_WRITE_DMA 0xca /* write w/DMA command */ -#define ATA_C_WRITE_DMA_QUEUED 0xcc /* write w/DMA QUEUED command */ -#define ATA_C_SLEEP 0xe6 /* sleep command */ -#define ATA_C_FLUSHCACHE 0xe7 /* flush cache to disk */ -#define ATA_C_FLUSHCACHE48 0xea /* flush cache to disk */ -#define ATA_C_ATA_IDENTIFY 0xec /* get ATA params */ -#define ATA_C_SETFEATURES 0xef /* features command */ -#define ATA_C_F_SETXFER 0x03 /* set transfer mode */ -#define ATA_C_F_ENAB_WCACHE 0x02 /* enable write cache */ -#define ATA_C_F_DIS_WCACHE 0x82 /* disable write cache */ -#define ATA_C_F_ENAB_RCACHE 0xaa /* enable readahead cache */ -#define ATA_C_F_DIS_RCACHE 0x55 /* disable readahead cache */ -#define ATA_C_F_ENAB_RELIRQ 0x5d /* enable release interrupt */ -#define ATA_C_F_DIS_RELIRQ 0xdd /* disable release interrupt */ -#define ATA_C_F_ENAB_SRVIRQ 0x5e /* enable service interrupt */ -#define ATA_C_F_DIS_SRVIRQ 0xde /* disable service interrupt */ - -#define ATA_STATUS 0x07 /* status register */ -#define ATA_S_ERROR 0x01 /* error */ -#define ATA_S_INDEX 0x02 /* index */ -#define ATA_S_CORR 0x04 /* data corrected */ -#define ATA_S_DRQ 0x08 /* data request */ -#define ATA_S_DSC 0x10 /* drive seek completed */ -#define ATA_S_SERVICE 0x10 /* drive needs service */ -#define ATA_S_DWF 0x20 /* drive write fault */ -#define ATA_S_DMA 0x20 /* DMA ready */ -#define ATA_S_READY 0x40 /* drive ready */ -#define ATA_S_BUSY 0x80 /* busy */ - -#define ATA_ALTSTAT 0x00 /* alternate status register */ -#define ATA_ALTOFFSET 0x206 /* alternate registers offset */ -#define ATA_PCCARD_ALTOFFSET 0x0e /* do for PCCARD devices */ -#define ATA_A_IDS 0x02 /* disable interrupts */ -#define ATA_A_RESET 0x04 /* RESET controller */ -#define ATA_A_4BIT 0x08 /* 4 head bits */ - -/* misc defines */ -#define ATA_PRIMARY 0x1f0 -#define ATA_SECONDARY 0x170 -#define ATA_IOSIZE 0x08 -#define ATA_ALTIOSIZE 0x01 -#define ATA_BMIOSIZE 0x08 -#define ATA_OP_FINISHED 0x00 -#define ATA_OP_CONTINUES 0x01 -#define ATA_IOADDR_RID 0 -#define ATA_ALTADDR_RID 1 -#define ATA_BMADDR_RID 2 -#define ATA_IRQ_RID 0 -#define ATA_DEV(device) ((device == ATA_MASTER) ? 0 : 1) - -/* busmaster DMA related defines */ -#define ATA_DMA_ENTRIES 256 -#define ATA_DMA_EOT 0x80000000 - -#define ATA_BMCMD_PORT 0x00 -#define ATA_BMCMD_START_STOP 0x01 -#define ATA_BMCMD_WRITE_READ 0x08 - -#define ATA_BMDEVSPEC_0 0x01 - -#define ATA_BMSTAT_PORT 0x02 -#define ATA_BMSTAT_ACTIVE 0x01 -#define ATA_BMSTAT_ERROR 0x02 -#define ATA_BMSTAT_INTERRUPT 0x04 -#define ATA_BMSTAT_MASK 0x07 -#define ATA_BMSTAT_DMA_MASTER 0x20 -#define ATA_BMSTAT_DMA_SLAVE 0x40 -#define ATA_BMSTAT_DMA_SIMPLEX 0x80 - -#define ATA_BMDEVSPEC_1 0x03 -#define ATA_BMDTP_PORT 0x04 - -/* structure for holding DMA address data */ -struct ata_dmaentry { - u_int32_t base; - u_int32_t count; -}; - -struct ata_dmastate { - bus_dma_tag_t ddmatag; /* data DMA tag */ - bus_dmamap_t ddmamap; /* data DMA map */ - bus_dma_tag_t cdmatag; /* control DMA tag */ - bus_dmamap_t cdmamap; /* control DMA map */ - struct ata_dmaentry *dmatab; /* DMA transfer table */ - bus_addr_t mdmatab; /* bus address of dmatab */ - int flags; /* debugging */ -#define ATA_DS_ACTIVE 0x01 /* debugging */ -#define ATA_DS_READ 0x02 /* transaction is a read */ -}; - -/* structure describing an ATA/ATAPI device */ -struct ata_device { - struct ata_channel *channel; - int unit; /* unit number */ -#define ATA_MASTER 0x00 -#define ATA_SLAVE 0x10 - - char *name; /* device name */ - struct ata_params *param; /* ata param structure */ - void *driver; /* ptr to driver for device */ - int flags; -#define ATA_D_USE_CHS 0x0001 -#define ATA_D_DETACHING 0x0002 -#define ATA_D_MEDIA_CHANGED 0x0004 -#define ATA_D_ENC_PRESENT 0x0008 - - int mode; /* transfermode */ - int cmd; /* last cmd executed */ - void *result; /* misc data */ - struct ata_dmastate dmastate; -}; - -/* structure describing an ATA channel */ -struct ata_channel { - struct device *dev; /* device handle */ - int unit; /* channel number */ - struct resource *r_io; /* io addr resource handle */ - struct resource *r_altio; /* altio addr resource handle */ - struct resource *r_bmio; /* bmio addr resource handle */ - struct resource *r_irq; /* interrupt of this channel */ - void *ih; /* interrupt handle */ - int (*intr_func)(struct ata_channel *); /* interrupt function */ - u_int32_t chiptype; /* pciid of controller chip */ - u_int32_t alignment; /* dma engine min alignment */ - int flags; /* controller flags */ -#define ATA_NO_SLAVE 0x01 -#define ATA_USE_16BIT 0x02 -#define ATA_ATAPI_DMA_RO 0x04 -#define ATA_QUEUED 0x08 -#define ATA_DMA_ACTIVE 0x10 - - struct ata_device device[2]; /* devices on this channel */ -#define MASTER 0x00 -#define SLAVE 0x01 - - int devices; /* what is present */ -#define ATA_ATA_MASTER 0x01 -#define ATA_ATA_SLAVE 0x02 -#define ATA_ATAPI_MASTER 0x04 -#define ATA_ATAPI_SLAVE 0x08 - - u_int8_t status; /* last controller status */ - u_int8_t error; /* last controller error */ - int active; /* active processing request */ -#define ATA_IDLE 0x0000 -#define ATA_IMMEDIATE 0x0001 -#define ATA_WAIT_INTR 0x0002 -#define ATA_WAIT_READY 0x0004 -#define ATA_WAIT_MASK 0x0007 -#define ATA_ACTIVE 0x0010 -#define ATA_ACTIVE_ATA 0x0020 -#define ATA_ACTIVE_ATAPI 0x0040 -#define ATA_CONTROL 0x0080 - - TAILQ_HEAD(, ad_request) ata_queue; /* head of ATA queue */ - TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */ - void *running; /* currently running request */ - struct malloc_pipe req_mpipe; /* request allocations */ - struct malloc_pipe dma_mpipe; /* dma allocations */ -}; - -/* disk bay/enclosure related */ -#define ATA_LED_OFF 0x00 -#define ATA_LED_RED 0x01 -#define ATA_LED_GREEN 0x02 -#define ATA_LED_ORANGE 0x03 -#define ATA_LED_MASK 0x03 - -/* externs */ -extern devclass_t ata_devclass; -extern int ata_mpipe_size; - -/* public prototypes */ -int ata_probe(device_t); -int ata_attach(device_t); -int ata_detach(device_t); -int ata_resume(device_t); -int ata_suspend(device_t); - -void ata_start(struct ata_channel *); -void ata_reset(struct ata_channel *); -int ata_reinit(struct ata_channel *); -int ata_wait(struct ata_device *, u_int8_t); -int ata_command(struct ata_device *, u_int8_t, u_int64_t, u_int16_t, u_int8_t, int); -void ata_enclosure_leds(struct ata_device *, u_int8_t); -void ata_enclosure_print(struct ata_device *); -int ata_printf(struct ata_channel *, int, const char *, ...) __printflike(3, 4); -int ata_prtdev(struct ata_device *, const char *, ...) __printflike(2, 3); -void ata_set_name(struct ata_device *, char *, int); -void ata_free_name(struct ata_device *); -int ata_get_lun(u_int32_t *); -int ata_test_lun(u_int32_t *, int); -void ata_free_lun(u_int32_t *, int); -char *ata_mode2str(int); -int ata_pmode(struct ata_params *); -int ata_wmode(struct ata_params *); -int ata_umode(struct ata_params *); -int ata_find_dev(device_t, u_int32_t, u_int32_t); - -int ata_dmaalloc(struct ata_device *, int); -void ata_dmafree(struct ata_device *); -void ata_dmafreetags(struct ata_channel *); -void ata_dmainit(struct ata_device *, int, int, int); -int ata_dmasetup(struct ata_device *, caddr_t, int); -int ata_dmastart(struct ata_device *, caddr_t, int32_t, int); -int ata_dmastatus(struct ata_channel *); -int ata_dmadone(struct ata_device *); - -/* macros for locking a channel */ -#define ATA_LOCK_CH(ch, value)\ - (((ch)->active == ATA_IDLE) ? ((ch)->active = value) : 0) - -#define ATA_SLEEPLOCK_CH(ch, value) {\ - while ((ch)->active != ATA_IDLE)\ - tsleep((caddr_t)&(ch), 0, "atalck", 1);\ - (ch)->active = value; } - -#define ATA_FORCELOCK_CH(ch, value) \ - (ch)->active = value - -#define ATA_UNLOCK_CH(ch) \ - (ch)->active = ATA_IDLE - -/* macros to hide busspace uglyness */ -#define ATA_INB(res, offset) \ - bus_space_read_1(rman_get_bustag((res)), \ - rman_get_bushandle((res)), (offset)) -#define ATA_INW(res, offset) \ - bus_space_read_2(rman_get_bustag((res)), \ - rman_get_bushandle((res)), (offset)) -#define ATA_INL(res, offset) \ - bus_space_read_4(rman_get_bustag((res)), \ - rman_get_bushandle((res)), (offset)) -#define ATA_INSW(res, offset, addr, count) \ - bus_space_read_multi_2(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ - (offset), (addr), (count)) -#define ATA_INSL(res, offset, addr, count) \ - bus_space_read_multi_4(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ - (offset), (addr), (count)) -#define ATA_OUTB(res, offset, value) \ - bus_space_write_1(rman_get_bustag((res)), \ - rman_get_bushandle((res)), (offset), (value)) -#define ATA_OUTW(res, offset, value) \ - bus_space_write_2(rman_get_bustag((res)), \ - rman_get_bushandle((res)), (offset), (value)) -#define ATA_OUTL(res, offset, value) \ - bus_space_write_4(rman_get_bustag((res)), \ - rman_get_bushandle((res)), (offset), (value)) -#define ATA_OUTSW(res, offset, addr, count) \ - bus_space_write_multi_2(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ - (offset), (addr), (count)) -#define ATA_OUTSL(res, offset, addr, count) \ - bus_space_write_multi_4(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ - (offset), (addr), (count)) diff --git a/sys/dev/disk/ata/ata-card.c b/sys/dev/disk/ata/ata-card.c deleted file mode 100644 index d9aadae1c0..0000000000 --- a/sys/dev/disk/ata/ata-card.c +++ /dev/null @@ -1,147 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-card.c,v 1.4.2.1 2002/03/18 08:37:33 sos Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "ata-all.h" - -#include -#include -#include -#include - -static const struct pccard_product ata_pccard_products[] = { - PCMCIA_CARD(FREECOM, PCCARDIDE, 0), - PCMCIA_CARD(EXP, EXPMULTIMEDIA, 0), - PCMCIA_CARD(IODATA3, CBIDE2, 0), - PCMCIA_CARD(OEM2, CDROM1, 0), - PCMCIA_CARD(OEM2, IDE, 0), - PCMCIA_CARD(PANASONIC, KXLC005, 0), - PCMCIA_CARD(TEAC, IDECARDII, 0), - {NULL} -}; - -static int -ata_pccard_match(device_t dev) -{ - const struct pccard_product *pp; - u_int32_t fcn = PCCARD_FUNCTION_UNSPEC; - - fcn = pccard_get_function_number(dev); - - /* if it says its a disk we should register it */ - if (fcn == PCCARD_FUNCTION_DISK) - return (0); - - /* match other devices here, primarily cdrom/dvd rom */ - if ((pp = pccard_product_lookup(dev, ata_pccard_products, - sizeof(ata_pccard_products[0]), NULL))) { - if (pp->pp_name) - device_set_desc(dev, pp->pp_name); - return (0); - } - return (ENXIO); -} - -static int -ata_pccard_probe(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - struct resource *io; - int rid, len, start, end; - u_long tmp; - - /* allocate the io range to get start and length */ - rid = ATA_IOADDR_RID; - len = bus_get_resource_count(dev, SYS_RES_IOPORT, rid); - io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_IOSIZE, RF_ACTIVE); - if (!io) - return ENOMEM; - - /* reallocate the io address to only cover the io ports */ - start = rman_get_start(io); - end = start + ATA_IOSIZE - 1; - bus_release_resource(dev, SYS_RES_IOPORT, rid, io); - io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - start, end, ATA_IOSIZE, RF_ACTIVE); - bus_release_resource(dev, SYS_RES_IOPORT, rid, io); - - /* - * if we got more than the default ATA_IOSIZE ports, this is likely - * a pccard system where the altio ports are located at offset 14 - * otherwise its the normal altio offset - */ - if (bus_get_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, &tmp, &tmp)) { - if (len > ATA_IOSIZE) { - bus_set_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, - start + ATA_PCCARD_ALTOFFSET, ATA_ALTIOSIZE, -1); - } - else { - bus_set_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, - start + ATA_ALTOFFSET, ATA_ALTIOSIZE, -1); - } - } - else - return ENOMEM; - - ch->unit = 0; - ch->flags |= (ATA_USE_16BIT | ATA_NO_SLAVE); - return ata_probe(dev); -} - -static device_method_t ata_pccard_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, pccard_compat_probe), - DEVMETHOD(device_attach, pccard_compat_attach), - DEVMETHOD(device_detach, ata_detach), - - /* Card interface */ - DEVMETHOD(card_compat_match, ata_pccard_match), - DEVMETHOD(card_compat_probe, ata_pccard_probe), - DEVMETHOD(card_compat_attach, ata_attach), - - { 0, 0 } -}; - -static driver_t ata_pccard_driver = { - "ata", - ata_pccard_methods, - sizeof(struct ata_channel), -}; - -DRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, NULL, NULL); diff --git a/sys/dev/disk/ata/ata-disk.c b/sys/dev/disk/ata/ata-disk.c deleted file mode 100644 index e87898d55b..0000000000 --- a/sys/dev/disk/ata/ata-disk.c +++ /dev/null @@ -1,988 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-disk.c,v 1.60.2.24 2003/01/30 07:19:59 sos Exp $ - */ - -#include "opt_ata.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "ata-all.h" -#include "ata-disk.h" -#include "ata-raid.h" - -/* device structures */ -static d_open_t adopen; -static d_close_t adclose; -static d_strategy_t adstrategy; -static d_dump_t addump; - -static struct dev_ops ad_ops = { - { "ad", 0, D_DISK }, - .d_open = adopen, - .d_close = adclose, - .d_read = physread, - .d_write = physwrite, - .d_strategy = adstrategy, - .d_dump = addump, -}; - -/* prototypes */ -static void ad_requeue(struct ata_channel *, struct ad_request *); -static void ad_invalidatequeue(struct ad_softc *, struct ad_request *); -static int ad_tagsupported(struct ad_softc *); -static void ad_timeout(struct ad_request *); -static void ad_free(struct ad_request *); -static int ad_version(u_int16_t); - -/* misc defines */ -#define AD_MAX_RETRIES 3 - -/* internal vars */ -static u_int32_t adp_lun_map = 0; -static int ata_dma = 1; -static int ata_wc = 1; -static int ata_tags = 0; -TUNABLE_INT("hw.ata.ata_dma", &ata_dma); -TUNABLE_INT("hw.ata.wc", &ata_wc); -TUNABLE_INT("hw.ata.tags", &ata_tags); -static MALLOC_DEFINE(M_AD, "AD driver", "ATA disk driver"); - -/* sysctl vars */ -SYSCTL_DECL(_hw_ata); -SYSCTL_INT(_hw_ata, OID_AUTO, ata_dma, CTLFLAG_RD, &ata_dma, 0, - "ATA disk DMA mode control"); -SYSCTL_INT(_hw_ata, OID_AUTO, wc, CTLFLAG_RD, &ata_wc, 0, - "ATA disk write caching"); -SYSCTL_INT(_hw_ata, OID_AUTO, tags, CTLFLAG_RD, &ata_tags, 0, - "ATA disk tagged queuing support"); - -void -ad_attach(struct ata_device *atadev, int alreadylocked) -{ - struct ad_softc *adp; - struct disk_info info; - cdev_t dev; - - adp = kmalloc(sizeof(struct ad_softc), M_AD, M_WAITOK | M_ZERO); - - KKASSERT(atadev->channel->req_mpipe.max_count != 0); - - adp->device = atadev; -#ifdef ATA_STATIC_ID - adp->lun = (device_get_unit(atadev->channel->dev)<<1)+ATA_DEV(atadev->unit); -#else - adp->lun = ata_get_lun(&adp_lun_map); -#endif - ata_set_name(atadev, "ad", adp->lun); - adp->heads = atadev->param->heads; - adp->sectors = atadev->param->sectors; - adp->total_secs = atadev->param->cylinders * adp->heads * adp->sectors; - bioq_init(&adp->bio_queue); - - /* does this device need oldstyle CHS addressing */ - if (!ad_version(atadev->param->version_major) || - !(atadev->param->atavalid & ATA_FLAG_54_58) || !atadev->param->lba_size) - adp->flags |= AD_F_CHS_USED; - - /* use the 28bit LBA size if valid */ - if (atadev->param->cylinders == 16383 && - adp->total_secs < atadev->param->lba_size) - adp->total_secs = atadev->param->lba_size; - - /* use the 48bit LBA size if valid */ - if (atadev->param->support.address48 && - atadev->param->lba_size48 > 268435455) - adp->total_secs = atadev->param->lba_size48; - - if (!alreadylocked) - ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); - /* use multiple sectors/interrupt if device supports it */ - adp->transfersize = DEV_BSIZE; - if (ad_version(atadev->param->version_major)) { - int secsperint = max(1, min(atadev->param->sectors_intr, 16)); - - if (!ata_command(atadev, ATA_C_SET_MULTI, 0, secsperint, - 0, ATA_WAIT_INTR) && !ata_wait(atadev, 0)) - adp->transfersize *= secsperint; - } - - /* enable read caching if not default on device */ - if (ata_command(atadev, ATA_C_SETFEATURES, - 0, 0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_INTR)) - ata_prtdev(atadev, "enabling readahead cache failed\n"); - - /* enable write caching if allowed and not default on device */ - if (ata_wc || (ata_tags && ad_tagsupported(adp))) { - if (ata_command(atadev, ATA_C_SETFEATURES, - 0, 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_INTR)) - ata_prtdev(atadev, "enabling write cache failed\n"); - } - else { - if (ata_command(atadev, ATA_C_SETFEATURES, - 0, 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_INTR)) - ata_prtdev(atadev, "disabling write cache failed\n"); - } - - /* use DMA if allowed and if drive/controller supports it */ - if (ata_dma) - ata_dmainit(atadev, ata_pmode(atadev->param), - ata_wmode(atadev->param), ata_umode(atadev->param)); - else - ata_dmainit(atadev, ata_pmode(atadev->param), -1, -1); - - /* use tagged queueing if allowed and supported */ - if (ata_tags && ad_tagsupported(adp)) { - adp->num_tags = atadev->param->queuelen; - adp->flags |= AD_F_TAG_ENABLED; - adp->device->channel->flags |= ATA_QUEUED; - if (ata_command(atadev, ATA_C_SETFEATURES, - 0, 0, ATA_C_F_DIS_RELIRQ, ATA_WAIT_INTR)) - ata_prtdev(atadev, "disabling release interrupt failed\n"); - if (ata_command(atadev, ATA_C_SETFEATURES, - 0, 0, ATA_C_F_DIS_SRVIRQ, ATA_WAIT_INTR)) - ata_prtdev(atadev, "disabling service interrupt failed\n"); - } - - ATA_UNLOCK_CH(atadev->channel); - - devstat_add_entry(&adp->stats, "ad", adp->lun, DEV_BSIZE, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE, - DEVSTAT_PRIORITY_DISK); - - dev = disk_create(adp->lun, &adp->disk, &ad_ops); - dev->si_drv1 = adp; - dev->si_iosize_max = 256 * DEV_BSIZE; - adp->dev = dev; - - /* construct the disk_info */ - bzero(&info, sizeof(info)); - info.d_media_blksize = DEV_BSIZE; - info.d_media_blocks = adp->total_secs; - info.d_nheads = adp->heads; - info.d_secpertrack = adp->sectors; - info.d_ncylinders = adp->total_secs / - (info.d_nheads * info.d_secpertrack); - info.d_secpercyl = info.d_secpertrack * info.d_nheads; - disk_setdiskinfo(&adp->disk, &info); - - atadev->driver = adp; - atadev->flags = 0; - - /* if this disk belongs to an ATA RAID dont print the probe */ - if (ata_raiddisk_attach(adp)) - adp->flags |= AD_F_RAID_SUBDISK; - else { - if (atadev->driver) { - ad_print(adp); - ata_enclosure_print(atadev); - } - } -} - -void -ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */ -{ - struct ad_softc *adp = atadev->driver; - struct ad_request *request; - struct bio *bio; - struct buf *bp; - - atadev->flags |= ATA_D_DETACHING; - ata_prtdev(atadev, "removed from configuration\n"); - ad_invalidatequeue(adp, NULL); - TAILQ_FOREACH(request, &atadev->channel->ata_queue, chain) { - if (request->softc != adp) - continue; - TAILQ_REMOVE(&atadev->channel->ata_queue, request, chain); - request->bio->bio_buf->b_error = ENXIO; - request->bio->bio_buf->b_flags |= B_ERROR; - biodone(request->bio); - ad_free(request); - } - ata_dmafree(atadev); - while ((bio = bioq_first(&adp->bio_queue))) { - bioq_remove(&adp->bio_queue, bio); - bp = bio->bio_buf; - bp->b_error = ENXIO; - bp->b_flags |= B_ERROR; - biodone(bio); - } - disk_invalidate(&adp->disk); - devstat_remove_entry(&adp->stats); - disk_destroy(&adp->disk); - if (flush) { - if (ata_command(atadev, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY)) - ata_prtdev(atadev, "flushing cache on detach failed\n"); - } - if (adp->flags & AD_F_RAID_SUBDISK) - ata_raiddisk_detach(adp); - ata_free_name(atadev); - ata_free_lun(&adp_lun_map, adp->lun); - atadev->driver = NULL; - atadev->flags = 0; - kfree(adp, M_AD); -} - -static int -adopen(struct dev_open_args *ap) -{ - struct ad_softc *adp = ap->a_head.a_dev->si_drv1; - - if (adp->flags & AD_F_RAID_SUBDISK) - return EBUSY; - return 0; -} - -static int -adclose(struct dev_close_args *ap) -{ - struct ad_softc *adp = ap->a_head.a_dev->si_drv1; - - crit_enter(); /* interlock non-atomic channel lock */ - ATA_SLEEPLOCK_CH(adp->device->channel, ATA_CONTROL); - if (ata_command(adp->device, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY)) - ata_prtdev(adp->device, "flushing cache on close failed\n"); - ATA_UNLOCK_CH(adp->device->channel); - crit_exit(); - return 0; -} - -/* - * note: always use the passed device rather then bp->b_dev, as the bp - * may have been translated through several layers. - */ -static int -adstrategy(struct dev_strategy_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct bio *bio = ap->a_bio; - struct buf *bp = bio->bio_buf; - struct ad_softc *adp = dev->si_drv1; - - if (adp->device->flags & ATA_D_DETACHING) { - bp->b_error = ENXIO; - bp->b_flags |= B_ERROR; - biodone(bio); - return(0); - } - bio->bio_driver_info = dev; - crit_enter(); - bioqdisksort(&adp->bio_queue, bio); - crit_exit(); - ata_start(adp->device->channel); - return(0); -} - -int -addump(struct dev_dump_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ad_softc *adp = dev->si_drv1; - struct ad_request request; - - if (!adp) - return ENXIO; - - /* force PIO mode for dumps */ - adp->device->mode = ATA_PIO; - ata_reinit(adp->device->channel); - - /* set up request */ - bzero(&request, sizeof(struct ad_request)); - request.softc = adp; - request.blockaddr = ap->a_offset / DEV_BSIZE; - request.bytecount = ap->a_length; - request.data = ap->a_virtual; - callout_init(&request.callout); - while (request.bytecount > 0) { - ad_transfer(&request); - if (request.flags & ADR_F_ERROR) - return EIO; - request.donecount += request.currentsize; - request.bytecount -= request.currentsize; - DELAY(20); - } - - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DSC) < 0) - ata_prtdev(adp->device, "timeout waiting for final ready\n"); - - return 0; -} - -/* - * Critical section is held when this function is called - * by ata_start(). - */ -void -ad_start(struct ata_device *atadev) -{ - struct ad_softc *adp = atadev->driver; - struct bio *bio = bioq_first(&adp->bio_queue); - struct buf *bp; - struct ad_request *request; - int tag = 0; - - if (bio == NULL) - return; - bp = bio->bio_buf; - - /* if tagged queueing enabled get next free tag */ - if (adp->flags & AD_F_TAG_ENABLED) { - while (tag <= adp->num_tags && adp->tags[tag]) - tag++; - if (tag > adp->num_tags ) - return; - } - - /* - * Allocate a request. The allocation can only fail if the pipeline - * is full, in which case the request will be picked up later when - * ad_start() is called after another request completes. - */ - request = mpipe_alloc_nowait(&atadev->channel->req_mpipe); - if (request == NULL) { - ata_prtdev(atadev, "pipeline full allocating request in ad_start\n"); - return; - } - - KASSERT((bio->bio_offset & DEV_BMASK) == 0, - ("bio_offset not on sector boundary %08llx", bio->bio_offset)); - - /* setup request */ - request->softc = adp; - request->bio = bio; - request->blockaddr = (u_int64_t)(bio->bio_offset >> DEV_BSHIFT); - request->bytecount = bp->b_bcount; - request->data = bp->b_data; - request->tag = tag; - callout_init(&request->callout); - if (bp->b_cmd == BUF_CMD_READ) - request->flags |= ADR_F_READ; - if (adp->device->mode >= ATA_DMA) { - if (ata_dmaalloc(atadev, M_NOWAIT) != 0) { - mpipe_free(&atadev->channel->req_mpipe, request); - ata_prtdev(atadev, "pipeline full allocated dmabuf in ad_start\n"); - /* do not revert to PIO, wait for ad_start after I/O completion */ - return; - } - } - - /* insert in tag array */ - adp->tags[tag] = request; - - /* remove from drive queue */ - bioq_remove(&adp->bio_queue, bio); - - /* link onto controller queue */ - TAILQ_INSERT_TAIL(&atadev->channel->ata_queue, request, chain); -} - -void -ad_requeue(struct ata_channel *chan, struct ad_request *req) -{ - if (req->donecount) { - ata_printf(chan, -1, - "WARNING: resetting donecount %u for retry\n", - req->donecount); - req->bytecount += req->donecount; - req->donecount = 0; - } - TAILQ_INSERT_HEAD(&chan->ata_queue, req, chain); -} - -int -ad_transfer(struct ad_request *request) -{ - struct ad_softc *adp; - u_int64_t lba; - u_int32_t count, max_count; - u_int8_t cmd; - int flags = ATA_IMMEDIATE; - - /* get request params */ - adp = request->softc; - - /* calculate transfer details */ - lba = request->blockaddr + (request->donecount / DEV_BSIZE); - - if (request->donecount == 0) { - - /* start timeout for this transfer */ - if (dumping) { - callout_stop(&request->callout); - } else { - callout_reset(&request->callout, 10 * hz, - (void *)ad_timeout, request); - } - - /* setup transfer parameters */ - count = howmany(request->bytecount, DEV_BSIZE); - max_count = adp->device->param->support.address48 ? 65536 : 256; - if (count > max_count) { - ata_prtdev(adp->device, - "count %d size transfers not supported\n", count); - count = max_count; - } - - if (adp->flags & AD_F_CHS_USED) { - int sector = (lba % adp->sectors) + 1; - int cylinder = lba / (adp->sectors * adp->heads); - int head = (lba % (adp->sectors * adp->heads)) / adp->sectors; - - lba = (sector&0xff) | ((cylinder&0xffff)<<8) | ((head&0xf)<<24); - adp->device->flags |= ATA_D_USE_CHS; - } - - /* setup first transfer length */ - request->currentsize = min(request->bytecount, adp->transfersize); - - devstat_start_transaction(&adp->stats); - - /* does this drive & transfer work with DMA ? */ - request->flags &= ~ADR_F_DMA_USED; - if (adp->device->mode >= ATA_DMA && - !ata_dmasetup(adp->device, request->data, request->bytecount)) { - request->flags |= ADR_F_DMA_USED; - request->currentsize = request->bytecount; - - /* do we have tags enabled ? */ - if (adp->flags & AD_F_TAG_ENABLED) { - cmd = (request->flags & ADR_F_READ) ? - ATA_C_READ_DMA_QUEUED : ATA_C_WRITE_DMA_QUEUED; - - if (ata_command(adp->device, cmd, lba, - request->tag << 3, count, flags)) { - ata_prtdev(adp->device, "error executing command"); - goto transfer_failed; - } - if (ata_wait(adp->device, ATA_S_READY)) { - ata_prtdev(adp->device, "timeout waiting for READY\n"); - goto transfer_failed; - } - adp->outstanding++; - - /* if ATA bus RELEASE check for SERVICE */ - if (adp->flags & AD_F_TAG_ENABLED && - ATA_INB(adp->device->channel->r_io, ATA_IREASON) & - ATA_I_RELEASE) - return ad_service(adp, 1); - } - else { - cmd = (request->flags & ADR_F_READ) ? - ATA_C_READ_DMA : ATA_C_WRITE_DMA; - - if (ata_command(adp->device, cmd, lba, count, 0, flags)) { - ata_prtdev(adp->device, "error executing command"); - goto transfer_failed; - } -#if 0 - /* - * wait for data transfer phase - * - * well this should be here acording to specs, but older - * promise controllers doesn't like it, they lockup! - */ - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DRQ)) { - ata_prtdev(adp->device, "timeout waiting for data phase\n"); - goto transfer_failed; - } -#endif - } - - /* start transfer, return and wait for interrupt */ - ata_dmastart(adp->device, request->data, request->bytecount, - request->flags & ADR_F_READ); - return ATA_OP_CONTINUES; - } - - /* does this drive support multi sector transfers ? */ - if (request->currentsize > DEV_BSIZE) - cmd = request->flags&ADR_F_READ ? ATA_C_READ_MUL : ATA_C_WRITE_MUL; - - /* just plain old single sector transfer */ - else - cmd = request->flags&ADR_F_READ ? ATA_C_READ : ATA_C_WRITE; - - if (ata_command(adp->device, cmd, lba, count, 0, flags)){ - ata_prtdev(adp->device, "error executing command"); - goto transfer_failed; - } - } - - /* calculate this transfer length */ - request->currentsize = min(request->bytecount, adp->transfersize); - - /* if this is a PIO read operation, return and wait for interrupt */ - if (request->flags & ADR_F_READ) - return ATA_OP_CONTINUES; - - /* ready to write PIO data ? */ - if (ata_wait(adp->device, (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) < 0) { - ata_prtdev(adp->device, "timeout waiting for DRQ"); - goto transfer_failed; - } - - /* output the data */ - if (adp->device->channel->flags & ATA_USE_16BIT) - ATA_OUTSW(adp->device->channel->r_io, ATA_DATA, - (void *)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int16_t)); - else - ATA_OUTSL(adp->device->channel->r_io, ATA_DATA, - (void *)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int32_t)); - return ATA_OP_CONTINUES; - -transfer_failed: - callout_stop(&request->callout); - ad_invalidatequeue(adp, request); - kprintf(" - resetting\n"); - - /* if retries still permit, reinject this request */ - if (request->retries++ < AD_MAX_RETRIES) - ad_requeue(adp->device->channel, request); - else { - /* retries all used up, return error */ - request->bio->bio_buf->b_error = EIO; - request->bio->bio_buf->b_flags |= B_ERROR; - request->bio->bio_buf->b_resid = request->bytecount; - devstat_end_transaction_buf(&adp->stats, request->bio->bio_buf); - biodone(request->bio); - ad_free(request); - } - ata_reinit(adp->device->channel); - return ATA_OP_CONTINUES; -} - -int -ad_interrupt(struct ad_request *request) -{ - struct ad_softc *adp = request->softc; - int dma_stat = 0; - cdev_t dev; - - /* finish DMA transfer */ - if (request->flags & ADR_F_DMA_USED) - dma_stat = ata_dmadone(adp->device); - - dev = request->bio->bio_driver_info; - /* do we have a corrected soft error ? */ - if (adp->device->channel->status & ATA_S_CORR) - diskerr(request->bio, dev, - "soft error (ECC corrected)", LOG_PRINTF, - request->donecount); - - /* did any real errors happen ? */ - if ((adp->device->channel->status & ATA_S_ERROR) || - (request->flags & ADR_F_DMA_USED && dma_stat & ATA_BMSTAT_ERROR)) { - adp->device->channel->error = - ATA_INB(adp->device->channel->r_io, ATA_ERROR); - diskerr(request->bio, dev, - (adp->device->channel->error & ATA_E_ICRC) ? - "UDMA ICRC error" : "hard error", LOG_PRINTF, - request->donecount); - - /* if this is a UDMA CRC error, reinject request */ - if (request->flags & ADR_F_DMA_USED && - adp->device->channel->error & ATA_E_ICRC) { - callout_stop(&request->callout); - ad_invalidatequeue(adp, request); - - if (request->retries++ < AD_MAX_RETRIES) - kprintf(" retrying\n"); - else { - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); - kprintf(" falling back to PIO mode\n"); - } - ad_requeue(adp->device->channel, request); - return ATA_OP_FINISHED; - } - - /* if using DMA, try once again in PIO mode */ - if (request->flags & ADR_F_DMA_USED) { - callout_stop(&request->callout); - ad_invalidatequeue(adp, request); - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); - request->flags |= ADR_F_FORCE_PIO; - kprintf(" trying PIO mode\n"); - ad_requeue(adp->device->channel, request); - return ATA_OP_FINISHED; - } - - request->flags |= ADR_F_ERROR; - kprintf(" status=%02x error=%02x\n", - adp->device->channel->status, adp->device->channel->error); - } - - /* if we arrived here with forced PIO mode, DMA doesn't work right */ - if (request->flags & ADR_F_FORCE_PIO && !(request->flags & ADR_F_ERROR)) - ata_prtdev(adp->device, "DMA problem fallback to PIO mode\n"); - - /* if this was a PIO read operation, get the data */ - if (!(request->flags & ADR_F_DMA_USED) && - (request->flags & (ADR_F_READ | ADR_F_ERROR)) == ADR_F_READ) { - - /* ready to receive data? */ - if ((adp->device->channel->status & ATA_S_READY) == 0) - ata_prtdev(adp->device, "read interrupt arrived early"); - - if (ata_wait(adp->device, (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) != 0) { - ata_prtdev(adp->device, "read error detected (too) late"); - request->flags |= ADR_F_ERROR; - } - else { - /* data ready, read in */ - if (adp->device->channel->flags & ATA_USE_16BIT) - ATA_INSW(adp->device->channel->r_io, ATA_DATA, - (void*)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int16_t)); - else - ATA_INSL(adp->device->channel->r_io, ATA_DATA, - (void*)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int32_t)); - } - } - - /* finish up transfer */ - if (request->flags & ADR_F_ERROR) { - request->bio->bio_buf->b_error = EIO; - request->bio->bio_buf->b_flags |= B_ERROR; - } - else { - request->bytecount -= request->currentsize; - request->donecount += request->currentsize; - if (request->bytecount > 0) { - ad_transfer(request); - return ATA_OP_CONTINUES; - } - } - - /* disarm timeout for this transfer */ - callout_stop(&request->callout); - - request->bio->bio_buf->b_resid = request->bytecount; - - devstat_end_transaction_buf(&adp->stats, request->bio->bio_buf); - biodone(request->bio); - ad_free(request); - adp->outstanding--; - - /* check for SERVICE (tagged operations only) */ - return ad_service(adp, 1); -} - -int -ad_service(struct ad_softc *adp, int change) -{ - /* do we have to check the other device on this channel ? */ - if (adp->device->channel->flags & ATA_QUEUED && change) { - int device = adp->device->unit; - - if (adp->device->unit == ATA_MASTER) { - if ((adp->device->channel->devices & ATA_ATA_SLAVE) && - (adp->device->channel->device[SLAVE].driver) && - ((struct ad_softc *) (adp->device->channel-> - device[SLAVE].driver))->flags & AD_F_TAG_ENABLED) - device = ATA_SLAVE; - } - else { - if ((adp->device->channel->devices & ATA_ATA_MASTER) && - (adp->device->channel->device[MASTER].driver) && - ((struct ad_softc *) (adp->device->channel-> - device[MASTER].driver))->flags & AD_F_TAG_ENABLED) - device = ATA_MASTER; - } - if (device != adp->device->unit && - ((struct ad_softc *) - (adp->device->channel-> - device[ATA_DEV(device)].driver))->outstanding > 0) { - ATA_OUTB(adp->device->channel->r_io, ATA_DRIVE, ATA_D_IBM | device); - adp = adp->device->channel->device[ATA_DEV(device)].driver; - DELAY(10); - } - } - adp->device->channel->status = - ATA_INB(adp->device->channel->r_altio, ATA_ALTSTAT); - - /* do we have a SERVICE request from the drive ? */ - if (adp->flags & AD_F_TAG_ENABLED && - adp->outstanding > 0 && - adp->device->channel->status & ATA_S_SERVICE) { - struct ad_request *request; - int tag; - - /* check for error */ - if (adp->device->channel->status & ATA_S_ERROR) { - ata_prtdev(adp->device, "Oops! controller says s=0x%02x e=0x%02x\n", - adp->device->channel->status, - adp->device->channel->error); - ad_invalidatequeue(adp, NULL); - return ATA_OP_FINISHED; - } - - /* issue SERVICE cmd */ - if (ata_command(adp->device, ATA_C_SERVICE, 0, 0, 0, ATA_IMMEDIATE)) { - ata_prtdev(adp->device, "problem executing SERVICE cmd\n"); - ad_invalidatequeue(adp, NULL); - return ATA_OP_FINISHED; - } - - /* setup the transfer environment when ready */ - if (ata_wait(adp->device, ATA_S_READY)) { - ata_prtdev(adp->device, "SERVICE timeout tag=%d s=%02x e=%02x\n", - ATA_INB(adp->device->channel->r_io, ATA_COUNT) >> 3, - adp->device->channel->status, - adp->device->channel->error); - ad_invalidatequeue(adp, NULL); - return ATA_OP_FINISHED; - } - tag = ATA_INB(adp->device->channel->r_io, ATA_COUNT) >> 3; - if (!(request = adp->tags[tag])) { - ata_prtdev(adp->device, "no request for tag=%d\n", tag); - ad_invalidatequeue(adp, NULL); - return ATA_OP_FINISHED; - } - ATA_FORCELOCK_CH(adp->device->channel, ATA_ACTIVE_ATA); - adp->device->channel->running = request; - request->serv++; - - /* start DMA transfer when ready */ - if (ata_wait(adp->device, ATA_S_READY | ATA_S_DRQ)) { - ata_prtdev(adp->device, "timeout starting DMA s=%02x e=%02x\n", - adp->device->channel->status, - adp->device->channel->error); - ad_invalidatequeue(adp, NULL); - return ATA_OP_FINISHED; - } - ata_dmastart(adp->device, request->data, request->bytecount, - request->flags & ADR_F_READ); - return ATA_OP_CONTINUES; - } - return ATA_OP_FINISHED; -} - -static void -ad_free(struct ad_request *request) -{ - crit_enter(); - ata_dmafree(request->softc->device); - request->softc->tags[request->tag] = NULL; - mpipe_free(&request->softc->device->channel->req_mpipe, request); - crit_exit(); -} - -static void -ad_invalidatequeue(struct ad_softc *adp, struct ad_request *request) -{ - /* if tags used invalidate all other tagged transfers */ - if (adp->flags & AD_F_TAG_ENABLED) { - struct ad_request *tmpreq; - int tag; - - ata_prtdev(adp->device, "invalidating queued requests\n"); - for (tag = 0; tag <= adp->num_tags; tag++) { - tmpreq = adp->tags[tag]; - adp->tags[tag] = NULL; - if (tmpreq == request || tmpreq == NULL) - continue; - callout_stop(&request->callout); - ad_requeue(adp->device->channel, tmpreq); - } - if (ata_command(adp->device, ATA_C_NOP, - 0, 0, ATA_C_F_FLUSHQUEUE, ATA_WAIT_READY)) - ata_prtdev(adp->device, "flush queue failed\n"); - adp->outstanding = 0; - } -} - -static int -ad_tagsupported(struct ad_softc *adp) -{ - const char *good[] = {"IBM-DPTA", "IBM-DTLA", NULL}; - int i = 0; - - switch (adp->device->channel->chiptype) { - case 0x4d33105a: /* Promises before TX2 doesn't work with tagged queuing */ - case 0x4d38105a: - case 0x0d30105a: - case 0x4d30105a: - return 0; - } - - /* check that drive does DMA, has tags enabled, and is one we know works */ - if (adp->device->mode >= ATA_DMA && adp->device->param->support.queued && - adp->device->param->enabled.queued) { - while (good[i] != NULL) { - if (!strncmp(adp->device->param->model, good[i], strlen(good[i]))) - return 1; - i++; - } - /* - * check IBM's new obscure way of naming drives - * we want "IC" (IBM CORP) and "AT" or "AV" (ATA interface) - * but doesn't care about the other info (size, capacity etc) - */ - if (!strncmp(adp->device->param->model, "IC", 2) && - (!strncmp(adp->device->param->model + 8, "AT", 2) || - !strncmp(adp->device->param->model + 8, "AV", 2))) - return 1; - } - return 0; -} - -static void -ad_timeout(struct ad_request *request) -{ - struct ad_softc *adp = request->softc; - - adp->device->channel->running = NULL; - ata_prtdev(adp->device, "%s command timeout tag=%d serv=%d - resetting\n", - (request->flags & ADR_F_READ) ? "READ" : "WRITE", - request->tag, request->serv); - - if (request->flags & ADR_F_DMA_USED) { - ata_dmadone(adp->device); - ad_invalidatequeue(adp, request); - if (request->retries == AD_MAX_RETRIES) { - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); - ata_prtdev(adp->device, "trying fallback to PIO mode\n"); - request->retries = 0; - } - } - - /* if retries still permit, reinject this request */ - if (request->retries++ < AD_MAX_RETRIES) { - ad_requeue(adp->device->channel, request); - } - else { - /* retries all used up, return error */ - request->bio->bio_buf->b_error = EIO; - request->bio->bio_buf->b_flags |= B_ERROR; - devstat_end_transaction_buf(&adp->stats, request->bio->bio_buf); - biodone(request->bio); - ad_free(request); - } - ata_reinit(adp->device->channel); -} - -void -ad_reinit(struct ata_device *atadev) -{ - struct ad_softc *adp = atadev->driver; - - /* reinit disk parameters */ - ad_invalidatequeue(atadev->driver, NULL); - ata_command(atadev, ATA_C_SET_MULTI, 0, - adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY); - if (adp->device->mode >= ATA_DMA) - ata_dmainit(atadev, ata_pmode(adp->device->param), - ata_wmode(adp->device->param), - ata_umode(adp->device->param)); - else - ata_dmainit(atadev, ata_pmode(adp->device->param), -1, -1); -} - -void -ad_print(struct ad_softc *adp) -{ - if (bootverbose) { - ata_prtdev(adp->device, "<%.40s/%.8s> ATA-%d disk at ata%d-%s\n", - adp->device->param->model, adp->device->param->revision, - ad_version(adp->device->param->version_major), - device_get_unit(adp->device->channel->dev), - (adp->device->unit == ATA_MASTER) ? "master" : "slave"); - - ata_prtdev(adp->device, - "%lluMB (%llu sectors), %llu C, %u H, %u S, %u B\n", - (unsigned long long)(adp->total_secs / - ((1024L*1024L)/DEV_BSIZE)), - (unsigned long long) adp->total_secs, - (unsigned long long) (adp->total_secs / - (adp->heads * adp->sectors)), - adp->heads, adp->sectors, DEV_BSIZE); - - ata_prtdev(adp->device, "%d secs/int, %d depth queue, %s%s\n", - adp->transfersize / DEV_BSIZE, adp->num_tags + 1, - (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "", - ata_mode2str(adp->device->mode)); - - ata_prtdev(adp->device, "piomode=%d dmamode=%d udmamode=%d cblid=%d\n", - ata_pmode(adp->device->param), ata_wmode(adp->device->param), - ata_umode(adp->device->param), - adp->device->param->hwres_cblid); - - } - else - ata_prtdev(adp->device,"%lluMB <%.40s> [%lld/%d/%d] at ata%d-%s %s%s\n", - (unsigned long long)(adp->total_secs / - ((1024L * 1024L) / DEV_BSIZE)), - adp->device->param->model, - (unsigned long long)(adp->total_secs / - (adp->heads*adp->sectors)), - adp->heads, adp->sectors, - device_get_unit(adp->device->channel->dev), - (adp->device->unit == ATA_MASTER) ? "master" : "slave", - (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "", - ata_mode2str(adp->device->mode)); -} - -static int -ad_version(u_int16_t version) -{ - int bit; - - if (version == 0xffff) - return 0; - for (bit = 15; bit >= 0; bit--) - if (version & (1< - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-disk.h,v 1.22.2.7 2002/03/18 08:37:33 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/ata-disk.h,v 1.8 2007/05/15 20:29:16 dillon Exp $ - */ - -/* structure describing an ATA disk request */ -struct ad_request { - struct ad_softc *softc; /* ptr to parent device */ - u_int64_t blockaddr; /* block number */ - u_int32_t bytecount; /* bytes to transfer */ - u_int32_t donecount; /* bytes transferred */ - u_int32_t currentsize; /* size of current transfer */ - struct callout callout; /* handle for timeout */ - int retries; /* retry count */ - int flags; -#define ADR_F_READ 0x0001 -#define ADR_F_ERROR 0x0002 -#define ADR_F_DMA_USED 0x0004 -#define ADR_F_QUEUED 0x0008 -#define ADR_F_FORCE_PIO 0x0010 - - caddr_t data; /* pointer to data buf */ - struct bio *bio; /* associated bio ptr */ - u_int8_t tag; /* tag ID of this request */ - int serv; /* request had service */ - TAILQ_ENTRY(ad_request) chain; /* list management */ -}; - -/* structure describing an ATA disk */ -struct ad_softc { - struct ata_device *device; /* ptr to device softc */ - int lun; /* logical unit number */ - u_int64_t total_secs; /* total # of sectors (LBA) */ - u_int8_t heads; - u_int8_t sectors; - u_int32_t transfersize; /* size of each transfer */ - int num_tags; /* number of tags supported */ - int flags; /* drive flags */ -#define AD_F_LABELLING 0x0001 -#define AD_F_CHS_USED 0x0002 -#define AD_F_32B_ENABLED 0x0004 -#define AD_F_TAG_ENABLED 0x0008 -#define AD_F_RAID_SUBDISK 0x0010 - - struct ad_request *tags[32]; /* tag array of requests */ - int outstanding; /* tags not serviced yet */ - struct bio_queue_head bio_queue; /* head of request queue */ - struct devstat stats; /* devstat entry */ - struct disk disk; /* disklabel/slice stuff */ - cdev_t dev; /* device place holder */ -}; - -void ad_attach(struct ata_device *, int); -void ad_detach(struct ata_device *, int); -void ad_reinit(struct ata_device *); -void ad_start(struct ata_device *); -int ad_transfer(struct ad_request *); -int ad_interrupt(struct ad_request *); -int ad_service(struct ad_softc *, int); -void ad_print(struct ad_softc *); diff --git a/sys/dev/disk/ata/ata-dma.c b/sys/dev/disk/ata/ata-dma.c deleted file mode 100644 index 8c5e453939..0000000000 --- a/sys/dev/disk/ata/ata-dma.c +++ /dev/null @@ -1,1628 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-dma.c,v 1.35.2.31 2003/05/07 16:46:11 jhb Exp $ - * $DragonFly: src/sys/dev/disk/ata/ata-dma.c,v 1.31 2006/12/12 19:01:31 dillon Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include "ata-all.h" - -/* prototypes */ -static void cyrix_timing(struct ata_device *, int, int); -static void promise_timing(struct ata_device *, int, int); -static void hpt_timing(struct ata_device *, int, int); -static int hpt_cable80(struct ata_device *); - -/* misc defines */ -#define ATAPI_DEVICE(atadev) \ - ((atadev->unit == ATA_MASTER && \ - atadev->channel->devices & ATA_ATAPI_MASTER) || \ - (atadev->unit == ATA_SLAVE && \ - atadev->channel->devices & ATA_ATAPI_SLAVE)) - -int ata_dma_debug = 0; - -int -ata_dmaalloc(struct ata_device *atadev, int flags) -{ - struct ata_channel *ch = atadev->channel; - - if (atadev->dmastate.dmatab != NULL) - return(0); - - KKASSERT(ch->dma_mpipe.max_count != 0); - if (flags & M_RNOWAIT) - atadev->dmastate.dmatab = mpipe_alloc_nowait(&ch->dma_mpipe); - else - atadev->dmastate.dmatab = mpipe_alloc_waitok(&ch->dma_mpipe); - - if (atadev->dmastate.dmatab != NULL) { - KKASSERT(((uintptr_t)atadev->dmastate.dmatab & PAGE_MASK) == 0); - return(0); - } - return(ENOBUFS); -} - -void -ata_dmafree(struct ata_device *atadev) -{ - struct ata_channel *ch = atadev->channel; - - if (atadev->dmastate.dmatab) { - mpipe_free(&ch->dma_mpipe, atadev->dmastate.dmatab); - atadev->dmastate.dmatab = NULL; - } -} - -void -ata_dmafreetags(struct ata_channel *ch) -{ -} - -static void -ata_dmacreate(struct ata_device *atadev, int apiomode, int mode) -{ - atadev->mode = mode; -} - -void -ata_dmainit(struct ata_device *atadev, int apiomode, int wdmamode, int udmamode) -{ - device_t parent = device_get_parent(atadev->channel->dev); - int chiptype = atadev->channel->chiptype; - int chiprev = pci_get_revid(parent); - int channel = atadev->channel->unit; - int device = ATA_DEV(atadev->unit); - int devno = (channel << 1) + device; - int error; - - /* set our most pessimistic default mode */ - atadev->mode = ATA_PIO; - - if (!atadev->channel->r_bmio) - return; - - /* if simplex controller, only allow DMA on primary channel */ - if (channel == 1) { - ATA_OUTB(atadev->channel->r_bmio, ATA_BMSTAT_PORT, - ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE)); - if (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - ATA_BMSTAT_DMA_SIMPLEX) { - ata_prtdev(atadev, "simplex device, DMA on primary only\n"); - return; - } - } - - /* DMA engine address alignment is usually 1 word (2 bytes) */ - atadev->channel->alignment = 0x1; - -#if 1 - if (udmamode > 2 && !atadev->param->hwres_cblid) { - ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n"); - udmamode = 2; - } -#endif - switch (chiptype) { - - case 0x27df8086: /* Intel ICH7 ATA */ - case 0x27c48086: /* Intel ICH7M SATA */ - case 0x269e8086: /* Intel ICH6 SATA */ - case 0x26808086: /* Intel ICH6 SATA */ - case 0x266f8086: /* Intel ICH6 ATA */ - case 0x26528086: /* Intel ICH6R/RW SATA */ - case 0x26538086: /* Intel ICH6M SATA */ - case 0x26518086: /* Intel ICH6/W SATA */ - case 0x24db8086: /* Intel ICH5 */ - case 0x24d18086: /* Intel ICH5 SATA */ - case 0x24ca8086: /* Intel ICH4 mobile */ - case 0x24cb8086: /* Intel ICH4 */ - case 0x248a8086: /* Intel ICH3 mobile */ - case 0x248b8086: /* Intel ICH3 */ - case 0x244a8086: /* Intel ICH2 mobile */ - case 0x244b8086: /* Intel ICH2 */ - if (udmamode >= 5) { - int32_t mask48, new48; - int16_t word54; - - word54 = pci_read_config(parent, 0x54, 2); - if (word54 & (0x10 << devno)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER,ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - mask48 = (1 << devno) + (3 << (16 + (devno << 2))); - new48 = (1 << devno) + (1 << (16 + (devno << 2))); - pci_write_config(parent, 0x48, - (pci_read_config(parent, 0x48, 4) & - ~mask48) | new48, 4); - pci_write_config(parent, 0x54, word54 | (0x1000<= 4) { - int32_t mask48, new48; - int16_t word54; - - word54 = pci_read_config(parent, 0x54, 2); - if (word54 & (0x10 << devno)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - mask48 = (1 << devno) + (3 << (16 + (devno << 2))); - new48 = (1 << devno) + (2 << (16 + (devno << 2))); - pci_write_config(parent, 0x48, - (pci_read_config(parent, 0x48, 4) & - ~mask48) | new48, 4); - pci_write_config(parent, 0x54, word54 | (1 << devno), 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - } - /* make sure eventual ATA66 mode from the BIOS is disabled */ - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 2) & ~(1 << devno), 2); - /* FALLTHROUGH */ - - case 0x71118086: /* Intel PIIX4 */ - case 0x84CA8086: /* Intel PIIX4 */ - case 0x71998086: /* Intel PIIX4e */ - case 0x24218086: /* Intel ICH0 */ - if (udmamode >= 2) { - int32_t mask48, new48; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - mask48 = (1 << devno) + (3 << (16 + (devno << 2))); - new48 = (1 << devno) + (2 << (16 + (devno << 2))); - pci_write_config(parent, 0x48, - (pci_read_config(parent, 0x48, 4) & - ~mask48) | new48, 4); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - /* make sure eventual ATA33 mode from the BIOS is disabled */ - pci_write_config(parent, 0x48, - pci_read_config(parent, 0x48, 4) & ~(1 << devno), 4); - /* FALLTHROUGH */ - - case 0x70108086: /* Intel PIIX3 */ - if (wdmamode >= 2 && apiomode >= 4) { - int32_t mask40, new40, mask44, new44; - - /* if SITRE not set doit for both channels */ - if (!((pci_read_config(parent,0x40,4)>>(channel<<8))&0x4000)) { - new40 = pci_read_config(parent, 0x40, 4); - new44 = pci_read_config(parent, 0x44, 4); - if (!(new40 & 0x00004000)) { - new44 &= ~0x0000000f; - new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8); - } - if (!(new40 & 0x40000000)) { - new44 &= ~0x000000f0; - new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20); - } - new40 |= 0x40004000; - pci_write_config(parent, 0x40, new40, 4); - pci_write_config(parent, 0x44, new44, 4); - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - if (device == ATA_MASTER) { - mask40 = 0x0000330f; - new40 = 0x00002307; - mask44 = 0; - new44 = 0; - } - else { - mask40 = 0x000000f0; - new40 = 0x00000070; - mask44 = 0x0000000f; - new44 = 0x0000000b; - } - if (channel) { - mask40 <<= 16; - new40 <<= 16; - mask44 <<= 4; - new44 <<= 4; - } - pci_write_config(parent, 0x40, - (pci_read_config(parent, 0x40, 4) & ~mask40)| - new40, 4); - pci_write_config(parent, 0x44, - (pci_read_config(parent, 0x44, 4) & ~mask44)| - new44, 4); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x12308086: /* Intel PIIX */ - if (wdmamode >= 2 && apiomode >= 4) { - int32_t word40; - - word40 = pci_read_config(parent, 0x40, 4); - word40 >>= channel * 16; - - /* Check for timing config usable for DMA on controller */ - if (!((word40 & 0x3300) == 0x2300 && - ((word40 >> (device ? 4 : 0)) & 1) == 1)) - break; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - break; - - case 0x522910b9: /* AcerLabs Aladdin IV/V */ - /* the older Aladdin doesn't support ATAPI DMA on both master & slave */ - if (chiprev < 0xc2 && - atadev->channel->devices & ATA_ATAPI_MASTER && - atadev->channel->devices & ATA_ATAPI_SLAVE) { - ata_prtdev(atadev, "two atapi devices on this channel, no DMA\n"); - break; - } -#if !defined(NO_ATANG) - pci_write_config(parent, 0x58 + (channel << 2), 0x00310001, 4); -#endif - if (udmamode >= 5 && chiprev >= 0xc4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - - pci_write_config(parent, 0x4b, - pci_read_config(parent, 0x4b, 1) | 0x01, 1); - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x000f0005 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4 && chiprev >= 0xc2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - - pci_write_config(parent, 0x4b, - pci_read_config(parent, 0x4b, 1) | 0x01, 1); - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x00080005 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2 && chiprev >= 0x20) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x000a0005 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - atadev->channel->flags |= ATA_ATAPI_DMA_RO; - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - - /* make sure eventual UDMA mode from the BIOS is disabled */ - pci_write_config(parent, 0x56, pci_read_config(parent, 0x56, 2) & - ~(0x0008 << (devno << 2)), 2); - - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - atadev->channel->flags |= ATA_ATAPI_DMA_RO; - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - pci_write_config(parent, 0x53, - (pci_read_config(parent, 0x53, 1) & ~0x01) | 0x02, 1); -#if !defined(NO_ATANG) - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on Acer chip\n", - (error) ? "failed" : "success", - (apiomode >= 0) ? apiomode : 0); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - int32_t timing; - - switch(ATA_PIO0 + apiomode) { - case ATA_PIO0: timing = 0x006d0003; break; - case ATA_PIO1: timing = 0x00580002; break; - case ATA_PIO2: timing = 0x00440001; break; - case ATA_PIO3: timing = 0x00330001; break; - case ATA_PIO4: timing = 0x00310001; break; - default: timing = 0x006d0003; break; - } - pci_write_config(parent, 0x58 + (channel << 2), timing, 4); - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x00000004 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - atadev->mode = ATA_PIO0 + apiomode; - return; - } -#endif - break; - - case 0x31491106: /* VIA 8237 SATA part */ - if (udmamode) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA + udmamode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA%d on VIA chip\n", - (error) ? "failed" : "success", udmamode); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA + udmamode); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x01bc10de: /* NVIDIA nForce1 */ - case 0x006510de: /* NVIDIA nForce2 */ - case 0x00d510de: /* NVIDIA nForce3 */ - case 0x00e310de: /* NVIDIA nForce3 PRO S1 */ - case 0x00e510de: /* NVIDIA nForce3 PRO */ - case 0x74691022: /* AMD 8111 */ - case 0x74411022: /* AMD 768 */ - case 0x74111022: /* AMD 766 */ - case 0x74091022: /* AMD 756 */ - case 0x05711106: /* VIA 82C571, 82C586, 82C596, 82C686, 8231,8233,8235 */ - { - int via_modes[][7] = { - { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */ - { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */ - { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */ - { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */ - { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }}; /* AMD/NVIDIA */ - int *reg_val = NULL; - int reg_off = 0x53; - char *chip = "VIA"; - - if (ata_find_dev(parent, 0x31471106, 0) || /* 8233a */ - ata_find_dev(parent, 0x31771106, 0) || /* 8235 */ - ata_find_dev(parent, 0x31491106, 0)) { /* 8237 */ - udmamode = imin(udmamode, 6); - reg_val = via_modes[3]; - } - else if (ata_find_dev(parent, 0x06861106, 0x40) || /* 82C686b */ - ata_find_dev(parent, 0x82311106, 0) || /* 8231 */ - ata_find_dev(parent, 0x30741106, 0) || /* 8233 */ - ata_find_dev(parent, 0x31091106, 0)) { /* 8233c */ - udmamode = imin(udmamode, 5); - reg_val = via_modes[2]; - } - else if (ata_find_dev(parent, 0x06861106, 0x10) || /* 82C686a */ - ata_find_dev(parent, 0x05961106, 0x12)) { /* 82C596b */ - udmamode = imin(udmamode, 4); - reg_val = via_modes[1]; - } - else if (ata_find_dev(parent, 0x06861106, 0)) { /* 82C686 */ - udmamode = imin(udmamode, 2); - reg_val = via_modes[1]; - } - else if (ata_find_dev(parent, 0x05961106, 0) || /* 82C596a */ - ata_find_dev(parent, 0x05861106, 0x03)) { /* 82C586b */ - udmamode = imin(udmamode, 2); - reg_val = via_modes[0]; - } - else if (chiptype == 0x74691022 || /* AMD 8111 */ - chiptype == 0x74411022 || /* AMD 768 */ - chiptype == 0x74111022) { /* AMD 766 */ - udmamode = imin(udmamode, 5); - reg_val = via_modes[4]; - chip = "AMD"; - } - else if (chiptype == 0x74091022) { /* AMD 756 */ - udmamode = imin(udmamode, 4); - reg_val = via_modes[4]; - chip = "AMD"; - } - else if (chiptype == 0x01bc10de) { /* nForce1 */ - udmamode = imin(udmamode, 5); - reg_val = via_modes[4]; -#if !defined(NO_ATANG) - reg_off += 0x10; -#endif - chip = "nVIDIA"; - } - else if (chiptype == 0x006510de || /* nForce2 */ - chiptype == 0x00d510de || /* nForce3 */ - chiptype == 0x00e310de || /* nForce3 PRO S1 */ - chiptype == 0x00e510de) { /* nForce3 PRO */ - udmamode = imin(udmamode, 6); - reg_val = via_modes[4]; -#if !defined(NO_ATANG) - reg_off += 0x10; -#endif - chip = "nVIDIA"; - } - else - udmamode = 0; - - reg_off -= devno; - - if (udmamode >= 6) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg_off, reg_val[6], 1); - pci_write_config(parent, reg_off - 8, 0x20, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - if (udmamode >= 5) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg_off, reg_val[5], 1); - pci_write_config(parent, reg_off - 8, 0x20, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg_off, reg_val[4], 1); - pci_write_config(parent, reg_off - 8, 0x20, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg_off, reg_val[2], 1); - pci_write_config(parent, reg_off - 8, 0x20, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg_off, 0x0b, 1); - pci_write_config(parent, reg_off - 8, 0x20, 1); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - pci_write_config(parent, reg_off, 0x8b, 1); - switch(apiomode) { - case 0: - pci_write_config(parent, reg_off - 8, 0xa8, 1); - break; - case 1: - pci_write_config(parent, reg_off - 8, 0x65, 1); - break; - case 2: - pci_write_config(parent, reg_off - 8, 0x42, 1); - break; - case 3: - pci_write_config(parent, reg_off - 8, 0x22, 1); - break; - case 4: - pci_write_config(parent, reg_off - 8, 0x20, 1); - break; - } - } - break; - - case 0x55131039: /* SiS 5591 */ - if (ata_find_dev(parent, 0x06301039, 0x30) || /* SiS 630 */ - ata_find_dev(parent, 0x06331039, 0) || /* SiS 633 */ - ata_find_dev(parent, 0x06351039, 0) || /* SiS 635 */ - ata_find_dev(parent, 0x06401039, 0) || /* SiS 640 */ - ata_find_dev(parent, 0x06451039, 0) || /* SiS 645 */ - ata_find_dev(parent, 0x06461039, 0) || /* SiS 645DX */ - ata_find_dev(parent, 0x06481039, 0) || /* SiS 648 */ - ata_find_dev(parent, 0x06501039, 0) || /* SiS 650 */ - ata_find_dev(parent, 0x07301039, 0) || /* SiS 730 */ - ata_find_dev(parent, 0x07331039, 0) || /* SiS 733 */ - ata_find_dev(parent, 0x07351039, 0) || /* SiS 735 */ - ata_find_dev(parent, 0x07401039, 0) || /* SiS 740 */ - ata_find_dev(parent, 0x07451039, 0) || /* SiS 745 */ - ata_find_dev(parent, 0x07461039, 0) || /* SiS 746 */ - ata_find_dev(parent, 0x07501039, 0)) { /* SiS 750 */ - int8_t reg = 0x40 + (devno << 1); - int16_t val = pci_read_config(parent, reg, 2) & 0x0fff; - - if (udmamode >= 5) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0x8000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0x9000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0xb000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - } else if (ata_find_dev(parent, 0x05301039, 0) || /* SiS 530 */ - ata_find_dev(parent, 0x05401039, 0) || /* SiS 540 */ - ata_find_dev(parent, 0x06201039, 0) || /* SiS 620 */ - ata_find_dev(parent, 0x06301039, 0)) { /* SiS 630 */ - int8_t reg = 0x40 + (devno << 1); - int16_t val = pci_read_config(parent, reg, 2) & 0x0fff; - - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0x9000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0xa000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - } else if (udmamode >= 2 && chiprev > 0xc1) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, 0x40 + (devno << 1), 0xa301, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >=2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x35121095: /* SiI 3512 SATA controller */ - /* EXPERIMENTAL! Works with FN85 AMD 64 3200+ motherboard */ - /* FALLTHROUGH */ - case 0x31241095: /* SiI 3124 SATA controller */ - case 0x31141095: /* SiI 3114 SATA controller */ - case 0x31121095: /* SiI 3112 SATA controller */ - case 0x06801095: /* SiI 0680 ATA133 controller */ - { - u_int8_t ureg = 0xac + (device * 0x02) + (channel * 0x10); - u_int8_t uval = pci_read_config(parent, ureg, 1); - u_int8_t mreg = channel ? 0x84 : 0x80; - u_int8_t mask = device ? 0x30 : 0x03; - u_int8_t mode = pci_read_config(parent, mreg, 1); - - /* enable UDMA mode */ - pci_write_config(parent, mreg, - (mode & ~mask) | (device ? 0x30 : 0x03), 1); - if (udmamode >= 6) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on SiI chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & ~0x3f) | 0x01, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - if (udmamode >= 5) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on SiI chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & ~0x3f) | 0x02, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on SiI chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & ~0x3f) | 0x03, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on SiI chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & ~0x3f) | 0x07, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - - /* disable UDMA mode and enable WDMA mode */ - pci_write_config(parent, mreg, - (mode & ~mask) | (device ? 0x20 : 0x02), 1); - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on SiI chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg - 0x4, 0x10c1, 2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - - /* restore PIO mode */ - pci_write_config(parent, mreg, mode, 1); - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x06491095: /* CMD 649 ATA100 controller */ - if (udmamode >= 5) { - u_int8_t umode; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on CMD chip\n", - (error) ? "failed" : "success"); - if (!error) { - umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1); - umode &= ~(device ? 0xca : 0x35); - umode |= (device ? 0x0a : 0x05); - pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - /* FALLTHROUGH */ - - case 0x06481095: /* CMD 648 ATA66 controller */ - if (udmamode >= 4) { - u_int8_t umode; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on CMD chip\n", - (error) ? "failed" : "success"); - if (!error) { - umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1); - umode &= ~(device ? 0xca : 0x35); - umode |= (device ? 0x4a : 0x15); - pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - u_int8_t umode; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on CMD chip\n", - (error) ? "failed" : "success"); - if (!error) { - umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1); - umode &= ~(device ? 0xca : 0x35); - umode |= (device ? 0x42 : 0x11); - pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - /* make sure eventual UDMA mode from the BIOS is disabled */ - pci_write_config(parent, channel ? 0x7b : 0x73, - pci_read_config(parent, channel ? 0x7b : 0x73, 1)& -#if !defined(NO_ATANG) - ~(device ? 0xca : 0x53), 1); -#else - ~(device ? 0xca : 0x35), 1); -#endif - /* FALLTHROUGH */ - - case 0x06461095: /* CMD 646 ATA controller */ - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on CMD chip\n", - error ? "failed" : "success"); - if (!error) { - int32_t offset = (devno < 3) ? (devno << 1) : 7; - - pci_write_config(parent, 0x54 + offset, 0x3f, 1); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0xc6931080: /* Cypress 82c693 ATA controller */ - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Cypress chip\n", - error ? "failed" : "success"); - if (!error) { - pci_write_config(atadev->channel->dev, - channel ? 0x4e:0x4c, 0x2020, 2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x01021078: /* Cyrix 5530 ATA33 controller */ - atadev->channel->alignment = 0xf; /* DMA engine requires 16 byte alignment */ - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Cyrix chip\n", - (error) ? "failed" : "success"); - if (!error) { - cyrix_timing(atadev, devno, ATA_UDMA2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Cyrix chip\n", - (error) ? "failed" : "success"); - if (!error) { - cyrix_timing(atadev, devno, ATA_WDMA2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, ATA_C_F_SETXFER, - ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting %s on Cyrix chip\n", - (error) ? "failed" : "success", - ata_mode2str(ATA_PIO0 + apiomode)); - cyrix_timing(atadev, devno, ATA_PIO0 + apiomode); - atadev->mode = ATA_PIO0 + apiomode; - return; - -#if !defined(NO_ATANG) - case 0x02131166: /* ServerWorks CSB6 ATA 100 controller (chan 0+1) */ -#endif - case 0x02121166: /* ServerWorks CSB5 ATA66/100 controller */ -#if !defined(NO_ATANG) - if (udmamode >= 5 && (chiptype == 0x02131166 || - (chiptype == 0x02121166 && - chiprev >= 0x92))) { -#else - if (udmamode >= 5 && chiprev >= 0x92) { -#endif - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg56; - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) | - (0x01 << devno), 1); - reg56 = pci_read_config(parent, 0x56, 2); - reg56 &= ~(0xf << (devno * 4)); - reg56 |= (0x5 << (devno * 4)); - pci_write_config(parent, 0x56, reg56, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } -#if !defined(NO_ATANG) - /* FALLTHROUGH */ - case 0x02171166: /* Server Works CSB6 ATA 66 controller chan 2 */ -#endif - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg56; - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) | - (0x01 << devno), 1); - reg56 = pci_read_config(parent, 0x56, 2); - reg56 &= ~(0xf << (devno * 4)); - reg56 |= (0x4 << (devno * 4)); - pci_write_config(parent, 0x56, reg56, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - /* FALLTHROUGH */ - - case 0x02111166: /* ServerWorks ROSB4 ATA33 controller */ - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg56; - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) | - (0x01 << devno), 1); - reg56 = pci_read_config(parent, 0x56, 2); - reg56 &= ~(0xf << (devno * 4)); - reg56 |= (0x2 << (devno * 4)); - pci_write_config(parent, 0x56, reg56, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - int offset = devno ^ 0x01; /* (chan*2) + (dev==ATA_MASTER)*/ - int word44 = pci_read_config(parent, 0x44, 4); - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) & - ~(0x01 << devno), 1); - word44 &= ~(0xff << (offset << 8)); - word44 |= (0x20 << (offset << 8)); - pci_write_config(parent, 0x44, 0x20, 4); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x4d69105a: /* Promise TX2 ATA133 controllers */ - case 0x5275105a: /* Promise TX2 ATA133 controllers */ - case 0x6269105a: /* Promise TX2 ATA133 controllers */ - case 0x7275105a: /* Promise TX2 ATA133 controllers */ - ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 6 && - !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - /* FALLTHROUGH */ - - case 0x4d68105a: /* Promise TX2 ATA100 controllers */ - case 0x6268105a: /* Promise TX2 ATA100 controllers */ - ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 5 && - !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 4 && - !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - break; - - case 0x0d30105a: /* Promise OEM ATA100 controllers */ - case 0x4d30105a: /* Promise Ultra/FastTrak 100 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 5 && - !(pci_read_config(parent, 0x50, 2)&(channel ? 1<<11 : 1<<10))){ - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_UDMA5); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - /* FALLTHROUGH */ - - case 0x0d38105a: /* Promise FastTrak 66 controllers */ - case 0x4d38105a: /* Promise Ultra/FastTrak 66 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 4 && - !(pci_read_config(parent, 0x50, 2)&(channel ? 1<<11 : 1<<10))){ - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_UDMA4); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - /* FALLTHROUGH */ - - case 0x4d33105a: /* Promise Ultra/FastTrak 33 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_UDMA2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (!ATAPI_DEVICE(atadev) && wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_WDMA2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on Promise chip\n", - (error) ? "failed" : "success", - (apiomode >= 0) ? apiomode : 0); - promise_timing(atadev, devno, ATA_PIO0 + apiomode); - atadev->mode = ATA_PIO0 + apiomode; - return; - - case 0x00041103: /* HighPoint HPT366/368/370/372 controllers */ - case 0x00051103: /* HighPoint HPT372 controllers */ - case 0x00081103: /* HighPoint HPT374 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 6 && hpt_cable80(atadev) && - ((chiptype == 0x00041103 && chiprev >= 0x05) || - (chiptype == 0x00051103 && chiprev >= 0x01) || - (chiptype == 0x00081103 && chiprev >= 0x07))) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA6); - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - if (!ATAPI_DEVICE(atadev) && udmamode >= 5 && hpt_cable80(atadev) && - ((chiptype == 0x00041103 && chiprev >= 0x03) || - (chiptype == 0x00051103 && chiprev >= 0x01) || - (chiptype == 0x00081103 && chiprev >= 0x07))) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA5); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (!ATAPI_DEVICE(atadev) && udmamode >= 4 && hpt_cable80(atadev)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA4); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (!ATAPI_DEVICE(atadev) && udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (!ATAPI_DEVICE(atadev) && wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_WDMA2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on HighPoint chip\n", - (error) ? "failed" : "success", - (apiomode >= 0) ? apiomode : 0); - hpt_timing(atadev, devno, ATA_PIO0 + apiomode); - atadev->mode = ATA_PIO0 + apiomode; - return; - - case 0x000116ca: /* Cenatek Rocket Drive controller */ - if (wdmamode >= 0 && - (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - (device ? ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) - ata_dmacreate(atadev, apiomode, ATA_DMA); - else - atadev->mode = ATA_PIO; - return; - - default: /* unknown controller chip */ - /* better not try generic DMA on ATAPI devices it almost never works */ - if (ATAPI_DEVICE(atadev)) - break; - - /* if controller says its setup for DMA take the easy way out */ - /* the downside is we dont know what DMA mode we are in */ - if ((udmamode >= 0 || wdmamode >= 2) && - (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - (device ? ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) { - ata_dmacreate(atadev, apiomode, ATA_DMA); - return; - } - - /* well, we have no support for this, but try anyways */ - if ((wdmamode >= 2 && apiomode >= 4) && atadev->channel->r_bmio) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on generic chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on generic chip\n", - (error) ? "failed" : "success", apiomode < 0 ? 0 : apiomode); - if (!error) - atadev->mode = ATA_PIO0 + apiomode; - else { - if (bootverbose) - ata_prtdev(atadev, "using PIO mode set by BIOS\n"); - atadev->mode = ATA_PIO; - } -} - -int -ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count) -{ - struct ata_channel *ch = atadev->channel; - struct ata_dmastate *ds = &atadev->dmastate; - u_int32_t dma_count, dma_base; - int i = 0; - - if (((uintptr_t)data & ch->alignment) || (count & ch->alignment)) { - ata_prtdev(atadev, "non aligned DMA transfer attempted\n"); - return -1; - } - - if (!count) { - ata_prtdev(atadev, "zero length DMA transfer attempted\n"); - return -1; - } - - dma_base = vtophys(data); - dma_count = imin(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK))); - data += dma_count; - count -= dma_count; - - while (count) { - ds->dmatab[i].base = dma_base; - ds->dmatab[i].count = (dma_count & 0xffff); - i++; - if (i >= ATA_DMA_ENTRIES) { - ata_prtdev(atadev, "too many segments in DMA table\n"); - return -1; - } - dma_base = vtophys(data); - dma_count = imin(count, PAGE_SIZE); - data += imin(count, PAGE_SIZE); - count -= imin(count, PAGE_SIZE); - } - ds->dmatab[i].base = dma_base; - ds->dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; - return 0; -} - -int -ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir) -{ - struct ata_channel *ch = atadev->channel; - struct ata_dmastate *ds = &atadev->dmastate; - - ch->flags |= ATA_DMA_ACTIVE; - ATA_OUTL(ch->r_bmio, ATA_BMDTP_PORT, vtophys(ds->dmatab)); - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, dir ? ATA_BMCMD_WRITE_READ : 0); - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - (ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) | - (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, - ATA_INB(ch->r_bmio, ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); - return(0); -} - -int -ata_dmadone(struct ata_device *atadev) -{ - struct ata_channel *ch; - struct ata_dmastate *ds; - int error; - - ch = atadev->channel; - ds = &atadev->dmastate; - - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, - ATA_INB(ch->r_bmio, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); - error = ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT); - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - error | ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); - ch->flags &= ~ATA_DMA_ACTIVE; - ds->flags = 0; - return error & ATA_BMSTAT_MASK; -} - -int -ata_dmastatus(struct ata_channel *ch) -{ - return ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; -} - -static void -cyrix_timing(struct ata_device *atadev, int devno, int mode) -{ - u_int32_t reg20 = 0x0000e132; - u_int32_t reg24 = 0x00017771; - - switch (mode) { - case ATA_PIO0: reg20 = 0x0000e132; break; - case ATA_PIO1: reg20 = 0x00018121; break; - case ATA_PIO2: reg20 = 0x00024020; break; - case ATA_PIO3: reg20 = 0x00032010; break; - case ATA_PIO4: reg20 = 0x00040010; break; - case ATA_WDMA2: reg24 = 0x00002020; break; - case ATA_UDMA2: reg24 = 0x00911030; break; - } - ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x20, reg20); - ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24, reg24); -} - -static void -promise_timing(struct ata_device *atadev, int devno, int mode) -{ - u_int32_t timing = 0; - /* XXX: Endianess */ - struct promise_timing { - u_int8_t pa:4; - u_int8_t prefetch:1; - u_int8_t iordy:1; - u_int8_t errdy:1; - u_int8_t syncin:1; - u_int8_t pb:5; - u_int8_t mb:3; - u_int8_t mc:4; - u_int8_t dmaw:1; - u_int8_t dmar:1; - u_int8_t iordyp:1; - u_int8_t dmarqp:1; - u_int8_t reserved:8; - } *t = (struct promise_timing*)&timing; - - t->iordy = 1; t->iordyp = 1; - if (mode >= ATA_DMA) { - t->prefetch = 1; t->errdy = 1; t->syncin = 1; - } - - switch (atadev->channel->chiptype) { - case 0x4d33105a: /* Promise Ultra/Fasttrak 33 */ - switch (mode) { - default: - case ATA_PIO0: t->pa = 9; t->pb = 19; t->mb = 7; t->mc = 15; break; - case ATA_PIO1: t->pa = 5; t->pb = 12; t->mb = 7; t->mc = 15; break; - case ATA_PIO2: t->pa = 3; t->pb = 8; t->mb = 7; t->mc = 15; break; - case ATA_PIO3: t->pa = 2; t->pb = 6; t->mb = 7; t->mc = 15; break; - case ATA_PIO4: t->pa = 1; t->pb = 4; t->mb = 7; t->mc = 15; break; - case ATA_WDMA2: t->pa = 3; t->pb = 7; t->mb = 3; t->mc = 3; break; - case ATA_UDMA2: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; - } - break; - - case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */ - case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */ - case 0x0d30105a: /* Promise OEM ATA 100 */ - switch (mode) { - default: - case ATA_PIO0: t->pa = 15; t->pb = 31; t->mb = 7; t->mc = 15; break; - case ATA_PIO1: t->pa = 10; t->pb = 24; t->mb = 7; t->mc = 15; break; - case ATA_PIO2: t->pa = 6; t->pb = 16; t->mb = 7; t->mc = 15; break; - case ATA_PIO3: t->pa = 4; t->pb = 12; t->mb = 7; t->mc = 15; break; - case ATA_PIO4: t->pa = 2; t->pb = 8; t->mb = 7; t->mc = 15; break; - case ATA_WDMA2: t->pa = 6; t->pb = 14; t->mb = 6; t->mc = 6; break; - case ATA_UDMA2: t->pa = 6; t->pb = 14; t->mb = 2; t->mc = 2; break; - case ATA_UDMA4: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; - case ATA_UDMA5: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; - } - break; - } - pci_write_config(device_get_parent(atadev->channel->dev), - 0x60 + (devno<<2), timing, 4); -} - -static void -hpt_timing(struct ata_device *atadev, int devno, int mode) -{ - device_t parent = device_get_parent(atadev->channel->dev); - u_int32_t chiptype = atadev->channel->chiptype; - int chiprev = pci_get_revid(parent); - u_int32_t timing; - - if (chiptype == 0x00081103 && chiprev >= 0x07) { - switch (mode) { /* HPT374 */ - case ATA_PIO0: timing = 0x0ac1f48a; break; - case ATA_PIO1: timing = 0x0ac1f465; break; - case ATA_PIO2: timing = 0x0a81f454; break; - case ATA_PIO3: timing = 0x0a81f443; break; - case ATA_PIO4: timing = 0x0a81f442; break; - case ATA_WDMA2: timing = 0x22808242; break; - case ATA_UDMA2: timing = 0x120c8242; break; - case ATA_UDMA4: timing = 0x12ac8242; break; - case ATA_UDMA5: timing = 0x12848242; break; - case ATA_UDMA6: timing = 0x12808242; break; - default: timing = 0x0d029d5e; - } - } - else if ((chiptype == 0x00041103 && chiprev >= 0x05) || - (chiptype == 0x00051103 && chiprev >= 0x01)) { - switch (mode) { /* HPT372 */ - case ATA_PIO0: timing = 0x0d029d5e; break; - case ATA_PIO1: timing = 0x0d029d26; break; - case ATA_PIO2: timing = 0x0c829ca6; break; - case ATA_PIO3: timing = 0x0c829c84; break; - case ATA_PIO4: timing = 0x0c829c62; break; - case ATA_WDMA2: timing = 0x2c829262; break; - case ATA_UDMA2: timing = 0x1c91dc62; break; - case ATA_UDMA4: timing = 0x1c8ddc62; break; - case ATA_UDMA5: timing = 0x1c6ddc62; break; - case ATA_UDMA6: timing = 0x1c81dc62; break; - default: timing = 0x0d029d5e; - } - } - else if (chiptype == 0x00041103 && chiprev >= 0x03) { - switch (mode) { /* HPT370 */ - case ATA_PIO0: timing = 0x06914e57; break; - case ATA_PIO1: timing = 0x06914e43; break; - case ATA_PIO2: timing = 0x06514e33; break; - case ATA_PIO3: timing = 0x06514e22; break; - case ATA_PIO4: timing = 0x06514e21; break; - case ATA_WDMA2: timing = 0x26514e21; break; - case ATA_UDMA2: timing = 0x16494e31; break; - case ATA_UDMA4: timing = 0x16454e31; break; - case ATA_UDMA5: timing = 0x16454e31; break; - default: timing = 0x06514e57; - } - pci_write_config(parent, 0x40 + (devno << 2) , timing, 4); - } - else { /* HPT36[68] */ - switch (pci_read_config(parent, 0x41 + (devno << 2), 1)) { - case 0x85: /* 25Mhz */ - switch (mode) { - case ATA_PIO0: timing = 0x40d08585; break; - case ATA_PIO1: timing = 0x40d08572; break; - case ATA_PIO2: timing = 0x40ca8542; break; - case ATA_PIO3: timing = 0x40ca8532; break; - case ATA_PIO4: timing = 0x40ca8521; break; - case ATA_WDMA2: timing = 0x20ca8521; break; - case ATA_UDMA2: timing = 0x10cf8521; break; - case ATA_UDMA4: timing = 0x10c98521; break; - default: timing = 0x01208585; - } - break; - default: - case 0xa7: /* 33MHz */ - switch (mode) { - case ATA_PIO0: timing = 0x40d0a7aa; break; - case ATA_PIO1: timing = 0x40d0a7a3; break; - case ATA_PIO2: timing = 0x40d0a753; break; - case ATA_PIO3: timing = 0x40c8a742; break; - case ATA_PIO4: timing = 0x40c8a731; break; - case ATA_WDMA2: timing = 0x20c8a731; break; - case ATA_UDMA2: timing = 0x10caa731; break; - case ATA_UDMA4: timing = 0x10c9a731; break; - default: timing = 0x0120a7a7; - } - break; - case 0xd9: /* 40Mhz */ - switch (mode) { - case ATA_PIO0: timing = 0x4018d9d9; break; - case ATA_PIO1: timing = 0x4010d9c7; break; - case ATA_PIO2: timing = 0x4010d997; break; - case ATA_PIO3: timing = 0x4010d974; break; - case ATA_PIO4: timing = 0x4008d963; break; - case ATA_WDMA2: timing = 0x2008d943; break; - case ATA_UDMA2: timing = 0x100bd943; break; - case ATA_UDMA4: timing = 0x100fd943; break; - default: timing = 0x0120d9d9; - } - } - } - pci_write_config(parent, 0x40 + (devno << 2) , timing, 4); -} - -static int -hpt_cable80(struct ata_device *atadev) -{ - device_t parent = device_get_parent(atadev->channel->dev); - u_int8_t reg, val, res; - - if (atadev->channel->chiptype == 0x00081103 && pci_get_function(parent) == 1) { - reg = atadev->channel->unit ? 0x57 : 0x53; - val = pci_read_config(parent, reg, 1); - pci_write_config(parent, reg, val | 0x80, 1); - } - else { - reg = 0x5b; - val = pci_read_config(parent, reg, 1); - pci_write_config(parent, reg, val & 0xfe, 1); - } - res = pci_read_config(parent, 0x5a, 1) & (atadev->channel->unit ? 0x01 : 0x02); - pci_write_config(parent, reg, val, 1); - return !res; -} diff --git a/sys/dev/disk/ata/ata-isa.c b/sys/dev/disk/ata/ata-isa.c deleted file mode 100644 index 05781c15f6..0000000000 --- a/sys/dev/disk/ata/ata-isa.c +++ /dev/null @@ -1,155 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-isa.c,v 1.4.2.1 2002/03/18 08:37:33 sos Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include "ata-all.h" - -/* local vars */ -static struct isa_pnp_id ata_ids[] = { - {0x0006d041, "Generic ESDI/IDE/ATA controller"}, /* PNP0600 */ - {0x0106d041, "Plus Hardcard II"}, /* PNP0601 */ - {0x0206d041, "Plus Hardcard IIXL/EZ"}, /* PNP0602 */ - {0x0306d041, "Generic ATA"}, /* PNP0603 */ - {0} -}; - -static int -ata_isa_probe(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - struct resource *io; - u_long tmp; - int rid; - - /* check isapnp ids */ - if (ISA_PNP_PROBE(device_get_parent(dev), dev, ata_ids) == ENXIO) - return ENXIO; - - /* allocate the io port range to get the start address */ - rid = ATA_IOADDR_RID; - io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, - ATA_IOSIZE, RF_ACTIVE); - if (!io) - return ENOMEM; - - /* set the altport range */ - if (bus_get_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, &tmp, &tmp)) { - bus_set_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, - rman_get_start(io) + ATA_ALTOFFSET, ATA_ALTIOSIZE, -1); - } - - bus_release_resource(dev, SYS_RES_IOPORT, rid, io); - ch->unit = 0; - ch->flags |= ATA_USE_16BIT; - return ata_probe(dev); -} - -static device_method_t ata_isa_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, ata_isa_probe), - DEVMETHOD(device_attach, ata_attach), - DEVMETHOD(device_resume, ata_resume), - DEVMETHOD(device_suspend, ata_suspend), - { 0, 0 } -}; - -static driver_t ata_isa_driver = { - "ata", - ata_isa_methods, - sizeof(struct ata_channel), -}; - -DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, NULL, NULL); - -/* - * the following is a bandaid to get ISA only setups to link, - * since these are getting rare the ugliness is kept here - */ -#include "use_pci.h" -#if NPCI == 0 -int -ata_dmaalloc(struct ata_device *ch, int flags) -{ - return 0; -} - -void -ata_dmafree(struct ata_device *atadev) -{ -} - -void -ata_dmafreetags(struct ata_channel *ch) -{ -} - -void -ata_dmainit(struct ata_device *atadev, int piomode, int wdmamode, int udmamode) -{ -} - -int -ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count) -{ - return -1; -} - -int -ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir) -{ - return -1; -} - -int -ata_dmadone(struct ata_device *atadev) -{ - return -1; -} - -int -ata_dmastatus(struct ata_channel *ch) -{ - return -1; -} -#endif diff --git a/sys/dev/disk/ata/ata-pci.c b/sys/dev/disk/ata/ata-pci.c deleted file mode 100644 index 7dfb2d7c04..0000000000 --- a/sys/dev/disk/ata/ata-pci.c +++ /dev/null @@ -1,987 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-pci.c,v 1.32.2.15 2003/06/06 13:27:05 fjoe Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include "ata-all.h" - -/* device structures */ -struct ata_pci_controller { - struct resource *bmio; - int bmaddr; - struct resource *irq; - int irqcnt; -}; - -/* misc defines */ -#define IOMASK 0xfffffffc -#define GRANDPARENT(dev) device_get_parent(device_get_parent(dev)) -#define ATA_MASTERDEV(dev) ((pci_get_progif(dev) & 0x80) && \ - (pci_get_progif(dev) & 0x05) != 0x05) - -int -ata_find_dev(device_t dev, u_int32_t devid, u_int32_t revid) -{ - device_t *children; - int nchildren, i; - - if (device_get_children(device_get_parent(dev), &children, &nchildren)) - return 0; - - for (i = 0; i < nchildren; i++) { - if (pci_get_devid(children[i]) == devid && - pci_get_revid(children[i]) >= revid) { - kfree(children, M_TEMP); - return 1; - } - } - kfree(children, M_TEMP); - return 0; -} - -static void -ata_via_southbridge_fixup(device_t dev) -{ - device_t *children; - int nchildren, i; - - if (device_get_children(device_get_parent(dev), &children, &nchildren)) - return; - - for (i = 0; i < nchildren; i++) { - if (pci_get_devid(children[i]) == 0x03051106 || /* VIA VT8363 */ - pci_get_devid(children[i]) == 0x03911106 || /* VIA VT8371 */ - pci_get_devid(children[i]) == 0x31021106 || /* VIA VT8662 */ - pci_get_devid(children[i]) == 0x31121106) { /* VIA VT8361 */ - u_int8_t reg76 = pci_read_config(children[i], 0x76, 1); - - if ((reg76 & 0xf0) != 0xd0) { - device_printf(dev, - "Correcting VIA config for southbridge data corruption bug\n"); - pci_write_config(children[i], 0x75, 0x80, 1); - pci_write_config(children[i], 0x76, (reg76 & 0x0f) | 0xd0, 1); - } - break; - } - } - kfree(children, M_TEMP); -} - -static const char * -ata_pci_match(device_t dev) -{ - if (pci_get_class(dev) != PCIC_STORAGE) - return NULL; - - switch (pci_get_devid(dev)) { - /* supported chipsets */ - case 0x12308086: - return "Intel PIIX ATA controller"; - - case 0x70108086: - return "Intel PIIX3 ATA controller"; - - case 0x71118086: - case 0x71998086: - case 0x84ca8086: - return "Intel PIIX4 ATA33 controller"; - - case 0x24218086: - return "Intel ICH0 ATA33 controller"; - - case 0x24118086: - case 0x76018086: - return "Intel ICH ATA66 controller"; - - case 0x244a8086: - case 0x244b8086: - return "Intel ICH2 ATA100 controller"; - - case 0x248a8086: - case 0x248b8086: - return "Intel ICH3 ATA100 controller"; - - case 0x24ca8086: - case 0x24cb8086: - return "Intel ICH4 ATA100 controller"; - - case 0x24d18086: - return "Intel ICH5 SATA150 controller"; - - case 0x24db8086: - return "Intel ICH5 ATA100 controller"; - - case 0x269e8086: - case 0x26808086: - return "Intel ICH6 SATA300 controller"; - - case 0x26518086: - return "Intel ICH6/W SATA150 controller"; - - case 0x26528086: - return "Intel ICH6R/RW SATA150 controller"; - - case 0x26538086: - return "Intel ICH6M SATA150 controller"; - - case 0x266f8086: - return "Intel ICH6R/RW ATA100 controller"; - - case 0x27df8086: - return "Intel ICH7 ATA controller"; - - case 0x27c48086: - return "Intel ICH7M SATA controller"; - - case 0x522910b9: - if (pci_get_revid(dev) >= 0xc4) - return "AcerLabs Aladdin ATA100 controller"; - else if (pci_get_revid(dev) >= 0xc2) - return "AcerLabs Aladdin ATA66 controller"; - else if (pci_get_revid(dev) >= 0x20) - return "AcerLabs Aladdin ATA33 controller"; - else - return "AcerLabs Aladdin ATA controller"; - - case 0x05711106: - if (ata_find_dev(dev, 0x05861106, 0x02)) - return "VIA 82C586 ATA33 controller"; - if (ata_find_dev(dev, 0x05861106, 0)) - return "VIA 82C586 ATA controller"; - if (ata_find_dev(dev, 0x05961106, 0x12)) - return "VIA 82C596 ATA66 controller"; - if (ata_find_dev(dev, 0x05961106, 0)) - return "VIA 82C596 ATA33 controller"; - if (ata_find_dev(dev, 0x06861106, 0x40)) - return "VIA 82C686 ATA100 controller"; - if (ata_find_dev(dev, 0x06861106, 0x10)) - return "VIA 82C686 ATA66 controller"; - if (ata_find_dev(dev, 0x06861106, 0)) - return "VIA 82C686 ATA33 controller"; - if (ata_find_dev(dev, 0x82311106, 0)) - return "VIA 8231 ATA100 controller"; - if (ata_find_dev(dev, 0x30741106, 0) || - ata_find_dev(dev, 0x31091106, 0)) - return "VIA 8233 ATA100 controller"; - if (ata_find_dev(dev, 0x31471106, 0)) - return "VIA 8233 ATA133 controller"; - if (ata_find_dev(dev, 0x31771106, 0)) - return "VIA 8235 ATA133 controller"; - if (ata_find_dev(dev, 0x31491106, 0)) - return "VIA 8237 ATA133 controller"; - return "VIA Apollo ATA controller"; - - case 0x31491106: - return "VIA 8237 SATA 150 controller"; - - case 0x55131039: - if (ata_find_dev(dev, 0x07461039, 0)) - return "SiS 5591 ATA133 controller"; - if (ata_find_dev(dev, 0x06301039, 0x30) || - ata_find_dev(dev, 0x06331039, 0) || - ata_find_dev(dev, 0x06351039, 0) || - ata_find_dev(dev, 0x06401039, 0) || - ata_find_dev(dev, 0x06451039, 0) || - ata_find_dev(dev, 0x06461039, 0) || - ata_find_dev(dev, 0x06481039, 0) || - ata_find_dev(dev, 0x06501039, 0) || - ata_find_dev(dev, 0x07301039, 0) || - ata_find_dev(dev, 0x07331039, 0) || - ata_find_dev(dev, 0x07351039, 0) || - ata_find_dev(dev, 0x07401039, 0) || - ata_find_dev(dev, 0x07451039, 0) || - ata_find_dev(dev, 0x07501039, 0)) - return "SiS 5591 ATA100 controller"; - else if (ata_find_dev(dev, 0x05301039, 0) || - ata_find_dev(dev, 0x05401039, 0) || - ata_find_dev(dev, 0x06201039, 0) || - ata_find_dev(dev, 0x06301039, 0)) - return "SiS 5591 ATA66 controller"; - else - return "SiS 5591 ATA33 controller"; - - case 0x35121095: - return "SiI 3512 SATA controller"; - - case 0x31121095: - return "SiI 3112 SATA controller"; - - case 0x31141095: - return "SiI 3114 SATA controller"; - - case 0x31241095: - return "SiI 3124 SATA controller"; - - case 0x06801095: - return "SiI 0680 ATA133 controller"; - - case 0x06491095: - return "CMD 649 ATA100 controller"; - - case 0x06481095: - return "CMD 648 ATA66 controller"; - - case 0x06461095: - return "CMD 646 ATA controller"; - - case 0xc6931080: - if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) - return "Cypress 82C693 ATA controller"; - return NULL; - - case 0x01021078: - return "Cyrix 5530 ATA33 controller"; - - case 0x74091022: - return "AMD 756 ATA66 controller"; - - case 0x74111022: - return "AMD 766 ATA100 controller"; - - case 0x74411022: - return "AMD 768 ATA100 controller"; - - case 0x74691022: - return "AMD 8111 UltraATA/133 controller"; - - case 0x01bc10de: - return "nVIDIA nForce1 ATA100 controller"; - - case 0x006510de: - return "nVIDIA nForce2 ATA133 controller"; - - case 0x00d510de: - return "nVIDIA nForce3 ATA133 controller"; - - case 0x00e310de: - return "nVIDIA nForce3 PRO S1 controller"; - - case 0x00e510de: - return "nVIDIA nForce3 PRO controller"; - - case 0x02111166: - return "ServerWorks ROSB4 ATA33 controller"; - - case 0x02121166: - if (pci_get_revid(dev) >= 0x92) - return "ServerWorks CSB5 ATA100 controller"; - else - return "ServerWorks CSB5 ATA66 controller"; - - case 0x02131166: - return "ServerWorks CSB6 ATA100 controller (channel 0+1)"; - - case 0x02171166: - return "ServerWorks CSB6 ATA66 controller (channel 2)"; - - case 0x4d33105a: - return "Promise ATA33 controller"; - - case 0x0d38105a: - case 0x4d38105a: - return "Promise ATA66 controller"; - - case 0x0d30105a: - case 0x4d30105a: - return "Promise ATA100 controller"; - - case 0x4d68105a: - case 0x6268105a: - if (pci_get_devid(GRANDPARENT(dev)) == 0x00221011 && - pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE) { - static long start = 0, end = 0; - - /* we belive we are on a TX4, now do our (simple) magic */ - if (pci_get_slot(dev) == 1) { - bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &end); - return "Promise TX4 ATA100 controller (channel 0+1)"; - } - else if (pci_get_slot(dev) == 2 && start && end) { - bus_set_resource(dev, SYS_RES_IRQ, 0, start, end, - machintr_legacy_intr_cpuid(start)); - start = end = 0; - return "Promise TX4 ATA100 controller (channel 2+3)"; - } - else - start = end = 0; - } - return "Promise TX2 ATA100 controller"; - - case 0x4d69105a: - case 0x5275105a: - case 0x6269105a: - case 0x7275105a: - return "Promise TX2 ATA133 controller"; - - case 0x00041103: - switch (pci_get_revid(dev)) { - case 0x00: - case 0x01: - return "HighPoint HPT366 ATA66 controller"; - case 0x02: - return "HighPoint HPT368 ATA66 controller"; - case 0x03: - case 0x04: - return "HighPoint HPT370 ATA100 controller"; - case 0x05: - return "HighPoint HPT372 ATA133 controller"; - } - return NULL; - - case 0x00051103: - switch (pci_get_revid(dev)) { - case 0x01: - case 0x02: - return "HighPoint HPT372 ATA133 controller"; - } - return NULL; - - case 0x00081103: - switch (pci_get_revid(dev)) { - case 0x07: - return "HighPoint HPT374 ATA133 controller"; - } - return NULL; - - case 0x000116ca: - return "Cenatek Rocket Drive controller"; - - /* unsupported but known chipsets, generic DMA only */ - case 0x10001042: - case 0x10011042: - return "RZ 100? ATA controller !WARNING! buggy chip data loss possible"; - - case 0x06401095: - return "CMD 640 ATA controller !WARNING! buggy chip data loss possible"; - - /* unknown chipsets, try generic DMA if it seems possible */ - default: - if (pci_get_class(dev) == PCIC_STORAGE && - (pci_get_subclass(dev) == PCIS_STORAGE_IDE)) - return "Generic PCI ATA controller"; - } - return NULL; -} - -static int -ata_pci_probe(device_t dev) -{ - const char *desc = ata_pci_match(dev); - - if (desc) { - device_set_desc(dev, desc); - device_set_async_attach(dev, TRUE); - return 0; - } else { - return ENXIO; - } -} - -static int -ata_pci_add_child(device_t dev, int unit) -{ - device_t child; - - /* check if this is located at one of the std addresses */ - if (ATA_MASTERDEV(dev)) { - if (!(child = device_add_child(dev, "ata", unit))) - return ENOMEM; - } - else { - if (!(child = device_add_child(dev, "ata", 2))) - return ENOMEM; - } - return 0; -} - -static int -ata_pci_attach(device_t dev) -{ - struct ata_pci_controller *controller = device_get_softc(dev); - u_int8_t class, subclass; - u_int32_t type, cmd; - int rid; - int flags; - - /* set up vendor-specific stuff */ - type = pci_get_devid(dev); - class = pci_get_class(dev); - subclass = pci_get_subclass(dev); - cmd = pci_read_config(dev, PCIR_COMMAND, 4); - - if (!(cmd & PCIM_CMD_PORTEN)) { - device_printf(dev, "ATA channel disabled by BIOS\n"); - return 0; - } - - /* is busmastering supported ? */ - if ((cmd & (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) == - (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) { - - /* is there a valid port range to connect to ? */ - rid = 0x20; - controller->bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, 1, RF_ACTIVE); - if (!controller->bmio) - device_printf(dev, "Busmastering DMA not configured\n"); - } - else - device_printf(dev, "Busmastering DMA not supported\n"); - - /* do extra chipset specific setups */ - flags = 0; - - switch (type) { - case 0x522910b9: /* Aladdin need to activate the ATAPI FIFO */ - pci_write_config(dev, 0x53, - (pci_read_config(dev, 0x53, 1) & ~0x01) | 0x02, 1); - break; - - case 0x4d38105a: /* Promise 66 & 100 (before TX2) need the clock changed */ - case 0x4d30105a: - case 0x0d30105a: - ATA_OUTB(controller->bmio, 0x11, ATA_INB(controller->bmio, 0x11)|0x0a); - /* FALLTHROUGH */ - - case 0x4d33105a: /* Promise (before TX2) need burst mode turned on */ - ATA_OUTB(controller->bmio, 0x1f, ATA_INB(controller->bmio, 0x1f)|0x01); - break; - - case 0x00041103: /* HighPoint HPT366/368/370/372 */ - if (pci_get_revid(dev) < 2) { /* HPT 366 */ - /* turn off interrupt prediction */ - pci_write_config(dev, 0x51, - (pci_read_config(dev, 0x51, 1) & ~0x80), 1); - break; - } - if (pci_get_revid(dev) < 5) { /* HPT368/370 */ - /* turn off interrupt prediction */ - pci_write_config(dev, 0x51, - (pci_read_config(dev, 0x51, 1) & ~0x03), 1); - pci_write_config(dev, 0x55, - (pci_read_config(dev, 0x55, 1) & ~0x03), 1); - - /* turn on interrupts */ - pci_write_config(dev, 0x5a, - (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); - - /* set clocks etc */ - pci_write_config(dev, 0x5b, 0x22, 1); - break; - } - /* FALLTHROUGH */ - - case 0x00051103: /* HighPoint HPT372 */ - case 0x00081103: /* HighPoint HPT374 */ - /* turn off interrupt prediction */ - pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1); - pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1); - - /* turn on interrupts */ - pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); - - /* set clocks etc */ - pci_write_config(dev, 0x5b, - (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1); - break; - - case 0x05711106: /* VIA 82C586, '596, '686 default setup */ - /* prepare for ATA-66 on the 82C686a and 82C596b */ - if ((ata_find_dev(dev, 0x06861106, 0x10) && - !ata_find_dev(dev, 0x06861106, 0x40)) || - ata_find_dev(dev, 0x05961106, 0x12)) - pci_write_config(dev, 0x50, 0x030b030b, 4); - - /* the southbridge might need the data corruption fix */ - if (ata_find_dev(dev, 0x06861106, 0x40) || - ata_find_dev(dev, 0x82311106, 0x10)) - ata_via_southbridge_fixup(dev); - - /* set fifo configuration half'n'half */ - pci_write_config(dev, 0x43, - (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1); - - /* set status register read retry */ - pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1); - - /* set DMA read & end-of-sector fifo flush */ - pci_write_config(dev, 0x46, - (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1); - - /* set sector size */ - pci_write_config(dev, 0x60, DEV_BSIZE, 2); - pci_write_config(dev, 0x68, DEV_BSIZE, 2); - break; - case 0x74111022: /* AMD 766 default setup */ - flags = 1; /* bugged */ - /* fall through */ - case 0x74091022: /* AMD 756 default setup */ - case 0x74411022: /* AMD 768 default setup */ - case 0x746d1022: /* AMD 8111 default setup */ - if (flags) { - pci_write_config(dev, 0x41, - pci_read_config(dev, 0x41, 1) & 0x0f, 1); - } else { - pci_write_config(dev, 0x41, - pci_read_config(dev, 0x41, 1) | 0xf0, 1); - } - break; - case 0x01bc10de: /* NVIDIA nForce1 default setup */ - case 0x006510de: /* NVIDIA nForce2 default setup */ - flags = 1; - /* fall through */ - case 0x00d510de: /* NVIDIA nForce3 default setup */ - if (flags) { - pci_write_config(dev, 0x51, - pci_read_config(dev, 0x51, 1) & 0x0f, 1); - } else { - pci_write_config(dev, 0x51, - pci_read_config(dev, 0x51, 1) | 0xf0, 1); - } - break; - - case 0x02111166: /* ServerWorks ROSB4 enable UDMA33 */ - pci_write_config(dev, 0x64, - (pci_read_config(dev, 0x64, 4) & ~0x00002000) | - 0x00004000, 4); - break; - - case 0x02121166: /* ServerWorks CSB5 enable UDMA66/100 depending on rev */ - pci_write_config(dev, 0x5a, - (pci_read_config(dev, 0x5a, 1) & ~0x40) | - (pci_get_revid(dev) >= 0x92) ? 0x03 : 0x02, 1); - break; - - case 0x06801095: /* SiI 0680 set ATA reference clock speed */ - if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) - pci_write_config(dev, 0x8a, - (pci_read_config(dev, 0x8a, 1) & 0x0F) | 0x10, 1); - if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) - device_printf(dev, "SiI 0680 could not set clock\n"); - break; - - case 0x06491095: - case 0x06481095: - case 0x06461095: /* CMD 646 enable interrupts, set DMA read mode */ - pci_write_config(dev, 0x71, 0x01, 1); - break; - - case 0x10001042: /* RZ 100? known bad, no DMA */ - case 0x10011042: - case 0x06401095: /* CMD 640 known bad, no DMA */ - controller->bmio = NULL; - device_printf(dev, "Busmastering DMA disabled\n"); - } - - if (controller->bmio) { - controller->bmaddr = rman_get_start(controller->bmio); - BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, rid, controller->bmio); - controller->bmio = NULL; - } - - /* - * the Cypress chip is a mess, it contains two ATA functions, but - * both channels are visible on the first one. - * simply ignore the second function for now, as the right - * solution (ignoring the second channel on the first function) - * doesn't work with the crappy ATA interrupt setup on the alpha. - */ - if (pci_get_devid(dev) == 0xc6931080 && pci_get_function(dev) > 1) - return 0; - - ata_pci_add_child(dev, 0); - - if (ATA_MASTERDEV(dev) || pci_read_config(dev, 0x18, 4) & IOMASK) - ata_pci_add_child(dev, 1); - - return bus_generic_attach(dev); -} - -static int -ata_pci_intr(struct ata_channel *ch) -{ - u_int8_t dmastat; - - /* - * since we might share the IRQ with another device, and in some - * cases with our twin channel, we only want to process interrupts - * that we know this channel generated. - */ - switch (ch->chiptype) { - case 0x00041103: /* HighPoint HPT366/368/370/372 */ - case 0x00051103: /* HighPoint HPT372 */ - case 0x00081103: /* HighPoint HPT374 */ - if (((dmastat = ata_dmastatus(ch)) & - (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != ATA_BMSTAT_INTERRUPT) - return 1; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); - DELAY(1); - return 0; - - case 0x06481095: /* CMD 648 */ - case 0x06491095: /* CMD 649 */ - if (!(pci_read_config(device_get_parent(ch->dev), 0x71, 1) & - (ch->unit ? 0x08 : 0x04))) - return 1; -#if !defined(NO_ATANG) - pci_write_config(device_get_parent(ch->dev), 0x71, - pci_read_config(device_get_parent(ch->dev), 0x71, 1) & - ~(ch->unit ? 0x04 : 0x08), 1); - break; -#endif - - case 0x06801095: /* SiI 680 */ - if (!(pci_read_config(device_get_parent(ch->dev), - (ch->unit ? 0xb1 : 0xa1), 1) & 0x08)) - return 1; - break; - - case 0x4d33105a: /* Promise Ultra/Fasttrak 33 */ - case 0x0d38105a: /* Promise Fasttrak 66 */ - case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */ - case 0x0d30105a: /* Promise OEM ATA100 */ - case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */ - if (!(ATA_INL(ch->r_bmio, (ch->unit ? 0x14 : 0x1c)) & - (ch->unit ? 0x00004000 : 0x00000400))) - return 1; - break; - - case 0x4d68105a: /* Promise TX2 ATA100 */ - case 0x6268105a: /* Promise TX2 ATA100 */ - case 0x4d69105a: /* Promise TX2 ATA133 */ - case 0x5275105a: /* Promise TX2 ATA133 */ - case 0x6269105a: /* Promise TX2 ATA133 */ - case 0x7275105a: /* Promise TX2 ATA133 */ - ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (!(ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x20)) - return 1; - break; - - case 0x24d18086: /* Intel ICH5 SATA150 */ - case 0x24db8086: /* Intel ICH5 ATA100 */ - case 0x26518086: /* Intel ICH6 SATA150 */ - case 0x26528086: /* Intel ICH6R SATA150 */ - case 0x26808086: /* Intel ICH6R SATA150 */ - case 0x260e8086: /* Intel ICH6 SATA300 */ - dmastat = ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT); - if ((dmastat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != - ATA_BMSTAT_INTERRUPT) - return 1; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat & - ~(ATA_BMSTAT_DMA_SIMPLEX | ATA_BMSTAT_ERROR)); - DELAY(1); - return 0; - - } - - if (ch->flags & ATA_DMA_ACTIVE) { - if (!((dmastat = ata_dmastatus(ch)) & ATA_BMSTAT_INTERRUPT)) - return 1; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); - DELAY(1); - } - return 0; -} - -static int -ata_pci_print_child(device_t dev, device_t child) -{ - struct ata_channel *ch = device_get_softc(child); - int retval = 0; - - retval += bus_print_child_header(dev, child); - retval += kprintf(": at 0x%lx", rman_get_start(ch->r_io)); - - if (ATA_MASTERDEV(dev)) - retval += kprintf(" irq %d", 14 + ch->unit); - - retval += bus_print_child_footer(dev, child); - - return retval; -} - -static struct resource * -ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, - u_long start, u_long end, u_long count, u_int flags, int cpuid) -{ - struct ata_pci_controller *controller = device_get_softc(dev); - struct resource *res = NULL; - int unit = ((struct ata_channel *)device_get_softc(child))->unit; - int myrid; - - if (type == SYS_RES_IOPORT) { - switch (*rid) { - case ATA_IOADDR_RID: - if (ATA_MASTERDEV(dev)) { - myrid = 0; - start = (unit ? ATA_SECONDARY : ATA_PRIMARY); - end = start + ATA_IOSIZE - 1; - count = ATA_IOSIZE; - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, &myrid, - start, end, count, flags, cpuid); - } - else { - myrid = 0x10 + 8 * unit; - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, &myrid, - start, end, count, flags, cpuid); - } - break; - - case ATA_ALTADDR_RID: - if (ATA_MASTERDEV(dev)) { - myrid = 0; - start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_ALTOFFSET; - end = start + ATA_ALTIOSIZE - 1; - count = ATA_ALTIOSIZE; - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, &myrid, - start, end, count, flags, cpuid); - } - else { - myrid = 0x14 + 8 * unit; - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, &myrid, - start, end, count, flags, cpuid); - if (res) { - start = rman_get_start(res) + 2; - end = start + ATA_ALTIOSIZE - 1; - count = ATA_ALTIOSIZE; - BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, myrid, res); - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, &myrid, - start, end, count, flags, - cpuid); - } - } - break; - - case ATA_BMADDR_RID: - if (controller->bmaddr) { - myrid = 0x20; - start = (unit == 0 ? - controller->bmaddr : controller->bmaddr+ATA_BMIOSIZE); - end = start + ATA_BMIOSIZE - 1; - count = ATA_BMIOSIZE; - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, &myrid, - start, end, count, flags, cpuid); - } - } - return res; - } - - if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) { - if (ATA_MASTERDEV(dev)) { - int irq = (unit == 0 ? 14 : 15); - - cpuid = machintr_legacy_intr_cpuid(irq); - return BUS_ALLOC_RESOURCE(device_get_parent(dev), child, - SYS_RES_IRQ, rid, irq, irq, 1, flags, - cpuid); - } - else { - /* primary and secondary channels share interrupt, keep track */ - if (!controller->irq) { - controller->irq = BUS_ALLOC_RESOURCE(device_get_parent(dev), - dev, SYS_RES_IRQ, - rid, 0, ~0, 1, flags, - cpuid); - } - controller->irqcnt++; - return controller->irq; - } - } - return 0; -} - -static int -ata_pci_release_resource(device_t dev, device_t child, int type, int rid, - struct resource *r) -{ - struct ata_pci_controller *controller = device_get_softc(dev); - int unit = ((struct ata_channel *)device_get_softc(child))->unit; - - if (type == SYS_RES_IOPORT) { - switch (rid) { - case ATA_IOADDR_RID: - if (ATA_MASTERDEV(dev)) - return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, 0x0, r); - else - return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, 0x10 + 8 * unit, r); - break; - - case ATA_ALTADDR_RID: - if (ATA_MASTERDEV(dev)) - return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, 0x0, r); - else - return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, 0x14 + 8 * unit, r); - break; - - case ATA_BMADDR_RID: - return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - SYS_RES_IOPORT, 0x20, r); - default: - return ENOENT; - } - } - if (type == SYS_RES_IRQ) { - if (rid != ATA_IRQ_RID) - return ENOENT; - - if (ATA_MASTERDEV(dev)) { - return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, - SYS_RES_IRQ, rid, r); - } - else { - /* primary and secondary channels share interrupt, keep track */ - if (--controller->irqcnt) - return 0; - controller->irq = NULL; - return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, rid, r); - } - } - return EINVAL; -} - -static int -ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, - int flags, driver_intr_t *intr, void *arg, - void **cookiep, lwkt_serialize_t serializer) -{ - if (ATA_MASTERDEV(dev)) { - return BUS_SETUP_INTR(device_get_parent(dev), child, irq, - flags, intr, arg, cookiep, serializer); - } - else - return BUS_SETUP_INTR(device_get_parent(dev), dev, irq, - flags, intr, arg, cookiep, serializer); -} - -static int -ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, - void *cookie) -{ - if (ATA_MASTERDEV(dev)) { - return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie); - } - else - return BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie); -} - -static device_method_t ata_pci_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, ata_pci_probe), - DEVMETHOD(device_attach, ata_pci_attach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* bus methods */ - DEVMETHOD(bus_print_child, ata_pci_print_child), - DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), - DEVMETHOD(bus_release_resource, ata_pci_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), - DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), - { 0, 0 } -}; - -static driver_t ata_pci_driver = { - "atapci", - ata_pci_methods, - sizeof(struct ata_pci_controller), -}; - -static devclass_t ata_pci_devclass; - -DRIVER_MODULE(atapci, pci, ata_pci_driver, ata_pci_devclass, NULL, NULL); - -static int -ata_pcisub_probe(device_t dev) -{ - struct ata_channel *ch = device_get_softc(dev); - device_t *children; - int count, i; - - /* find channel number on this controller */ - device_get_children(device_get_parent(dev), &children, &count); - for (i = 0; i < count; i++) { - if (children[i] == dev) - ch->unit = i; - } - kfree(children, M_TEMP); - ch->chiptype = pci_get_devid(device_get_parent(dev)); - ch->intr_func = ata_pci_intr; - return ata_probe(dev); -} - -static device_method_t ata_pcisub_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, ata_pcisub_probe), - DEVMETHOD(device_attach, ata_attach), - DEVMETHOD(device_detach, ata_detach), - DEVMETHOD(device_resume, ata_resume), - DEVMETHOD(device_suspend, ata_suspend), - { 0, 0 } -}; - -static driver_t ata_pcisub_driver = { - "ata", - ata_pcisub_methods, - sizeof(struct ata_channel), -}; - -DRIVER_MODULE(ata, atapci, ata_pcisub_driver, ata_devclass, NULL, NULL); diff --git a/sys/dev/disk/ata/ata-raid.c b/sys/dev/disk/ata/ata-raid.c deleted file mode 100644 index 954a5a5d9d..0000000000 --- a/sys/dev/disk/ata/ata-raid.c +++ /dev/null @@ -1,1470 +0,0 @@ -/*- - * Copyright (c) 2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-raid.c,v 1.3.2.19 2003/01/30 07:19:59 sos Exp $ - */ - -#include "opt_ata.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ata-all.h" -#include "ata-disk.h" -#include "ata-raid.h" - -/* device structures */ -static d_open_t aropen; -static d_strategy_t arstrategy; - -static struct dev_ops ar_ops = { - { "ar", 0, D_DISK }, - .d_open = aropen, - .d_close = nullclose, - .d_read = physread, - .d_write = physwrite, - .d_strategy = arstrategy, -}; - -/* prototypes */ -static void ar_attach_raid(struct ar_softc *, int); -static void ar_done(struct bio *); -static void ar_config_changed(struct ar_softc *, int); -static int ar_rebuild(struct ar_softc *); -static int ar_highpoint_read_conf(struct ad_softc *, struct ar_softc **); -static int ar_highpoint_write_conf(struct ar_softc *); -static int ar_promise_read_conf(struct ad_softc *, struct ar_softc **, int); -static int ar_promise_write_conf(struct ar_softc *); -static int ar_rw(struct ad_softc *, u_int32_t, int, caddr_t, int); -static struct ata_device *ar_locate_disk(int); - -/* internal vars */ -static struct ar_softc **ar_table = NULL; -static MALLOC_DEFINE(M_AR, "AR driver", "ATA RAID driver"); - -int -ata_raiddisk_attach(struct ad_softc *adp) -{ - struct ar_softc *rdp; - int array, disk; - - if (ar_table) { - for (array = 0; array < MAX_ARRAYS; array++) { - if (!(rdp = ar_table[array]) || !rdp->flags) - continue; - - for (disk = 0; disk < rdp->total_disks; disk++) { - if ((rdp->disks[disk].flags & AR_DF_ASSIGNED) && - rdp->disks[disk].device == adp->device) { - ata_prtdev(rdp->disks[disk].device, - "inserted into ar%d disk%d as spare\n", - array, disk); - rdp->disks[disk].flags |= (AR_DF_PRESENT | AR_DF_SPARE); - AD_SOFTC(rdp->disks[disk])->flags = AD_F_RAID_SUBDISK; - ar_config_changed(rdp, 1); - return 1; - } - } - } - } - - if (!ar_table) { - ar_table = kmalloc(sizeof(struct ar_soft *) * MAX_ARRAYS, - M_AR, M_WAITOK | M_ZERO); - } - - switch(adp->device->channel->chiptype) { - case 0x4d33105a: case 0x4d38105a: case 0x4d30105a: - case 0x0d30105a: case 0x4d68105a: case 0x6268105a: - case 0x4d69105a: case 0x5275105a: case 0x6269105a: - case 0x7275105a: - /* test RAID bit in PCI reg XXX */ - return (ar_promise_read_conf(adp, ar_table, 0)); - - case 0x00041103: case 0x00051103: case 0x00081103: - return (ar_highpoint_read_conf(adp, ar_table)); - - default: - return (ar_promise_read_conf(adp, ar_table, 1)); - } - return 0; -} - -int -ata_raiddisk_detach(struct ad_softc *adp) -{ - struct ar_softc *rdp; - int array, disk; - - if (ar_table) { - for (array = 0; array < MAX_ARRAYS; array++) { - if (!(rdp = ar_table[array]) || !rdp->flags) - continue; - for (disk = 0; disk < rdp->total_disks; disk++) { - if (rdp->disks[disk].device == adp->device) { - ata_prtdev(rdp->disks[disk].device, - "deleted from ar%d disk%d\n", array, disk); - rdp->disks[disk].flags &= ~(AR_DF_PRESENT | AR_DF_ONLINE); - AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK; - ar_config_changed(rdp, 1); - return 1; - } - } - } - } - return 0; -} - -void -ata_raid_attach() -{ - struct ar_softc *rdp; - int array; - - if (!ar_table) - return; - - for (array = 0; array < MAX_ARRAYS; array++) { - if (!(rdp = ar_table[array]) || !rdp->flags) - continue; - ar_attach_raid(rdp, 0); - } -} - -static void -ar_attach_raid(struct ar_softc *rdp, int update) -{ - struct disk_info info; - cdev_t dev; - int disk; - - ar_config_changed(rdp, update); - dev = disk_create(rdp->lun, &rdp->disk, &ar_ops); - dev->si_drv1 = rdp; - dev->si_iosize_max = 256 * DEV_BSIZE; - rdp->dev = dev; - - /* - * Set disk info, as it appears that all needed data is available already. - * Setting the disk info will also cause the probing to start. - */ - bzero(&info, sizeof(info)); - info.d_media_blksize = DEV_BSIZE; /* mandatory */ - info.d_media_blocks = rdp->total_sectors; - - info.d_secpertrack = rdp->sectors; /* optional */ - info.d_nheads = rdp->heads; - info.d_ncylinders = rdp->cylinders; - info.d_secpercyl = rdp->sectors * rdp->heads; - - kprintf("ar%d: %lluMB lun, (unsigned long long) - (rdp->total_sectors / ((1024L * 1024L) / DEV_BSIZE))); - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_RAID0: - kprintf("RAID0 "); break; - case AR_F_RAID1: - kprintf("RAID1 "); break; - case AR_F_SPAN: - kprintf("SPAN "); break; - case (AR_F_RAID0 | AR_F_RAID1): - kprintf("RAID0+1 "); break; - default: - kprintf("unknown 0x%x> ", rdp->flags); - return; - } - kprintf("array> [%d/%d/%d] status: ", - rdp->cylinders, rdp->heads, rdp->sectors); - switch (rdp->flags & (AR_F_DEGRADED | AR_F_READY)) { - case AR_F_READY: - kprintf("READY"); - break; - case (AR_F_DEGRADED | AR_F_READY): - kprintf("DEGRADED"); - break; - default: - kprintf("BROKEN"); - break; - } - kprintf(" subdisks:\n"); - for (disk = 0; disk < rdp->total_disks; disk++) { - if (rdp->disks[disk].flags & AR_DF_PRESENT) { - if (rdp->disks[disk].flags & AR_DF_ONLINE) - kprintf(" %d READY ", disk); - else if (rdp->disks[disk].flags & AR_DF_SPARE) - kprintf(" %d SPARE ", disk); - else - kprintf(" %d FREE ", disk); - ad_print(AD_SOFTC(rdp->disks[disk])); - kprintf(" "); - ata_enclosure_print(AD_SOFTC(rdp->disks[disk])->device); - } - else if (rdp->disks[disk].flags & AR_DF_ASSIGNED) - kprintf(" %d DOWN\n", disk); - else - kprintf(" %d INVALID no RAID config info on this disk\n", disk); - } - disk_setdiskinfo(&rdp->disk, &info); -} - -int -ata_raid_create(struct raid_setup *setup) -{ - struct ata_device *atadev; - struct ar_softc *rdp; - int array, disk; - int ctlr = 0, disk_size = 0, total_disks = 0; - - if (!ar_table) { - ar_table = kmalloc(sizeof(struct ar_soft *) * MAX_ARRAYS, - M_AR, M_WAITOK | M_ZERO); - } - for (array = 0; array < MAX_ARRAYS; array++) { - if (!ar_table[array]) - break; - } - if (array >= MAX_ARRAYS) - return ENOSPC; - - rdp = kmalloc(sizeof(struct ar_softc), M_AR, M_WAITOK | M_ZERO); - - for (disk = 0; disk < setup->total_disks; disk++) { - if ((atadev = ar_locate_disk(setup->disks[disk]))) { - rdp->disks[disk].device = atadev; - if (AD_SOFTC(rdp->disks[disk])->flags & AD_F_RAID_SUBDISK) { - setup->disks[disk] = -1; - kfree(rdp, M_AR); - return EBUSY; - } - - switch (rdp->disks[disk].device->channel->chiptype & 0xffff) { - case 0x1103: - ctlr |= AR_F_HIGHPOINT_RAID; - rdp->disks[disk].disk_sectors = - AD_SOFTC(rdp->disks[disk])->total_secs; - break; - - default: - ctlr |= AR_F_FREEBSD_RAID; - /* FALLTHROUGH */ - - case 0x105a: - ctlr |= AR_F_PROMISE_RAID; - rdp->disks[disk].disk_sectors = - PR_LBA(AD_SOFTC(rdp->disks[disk])); - break; - } - if ((rdp->flags & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID)) && - (rdp->flags & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID)) != - (ctlr & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID))) { - kfree(rdp, M_AR); - return EXDEV; - } - else - rdp->flags |= ctlr; - - if (disk_size) - disk_size = min(rdp->disks[disk].disk_sectors, disk_size); - else - disk_size = rdp->disks[disk].disk_sectors; - rdp->disks[disk].flags = - (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE); - - total_disks++; - } - else { - setup->disks[disk] = -1; - kfree(rdp, M_AR); - return ENXIO; - } - } - if (!total_disks) { - kfree(rdp, M_AR); - return ENODEV; - } - - switch (setup->type) { - case 1: - rdp->flags |= AR_F_RAID0; - break; - case 2: - rdp->flags |= AR_F_RAID1; - if (total_disks != 2) { - kfree(rdp, M_AR); - return EPERM; - } - break; - case 3: - rdp->flags |= (AR_F_RAID0 | AR_F_RAID1); - if (total_disks % 2 != 0) { - kfree(rdp, M_AR); - return EPERM; - } - break; - case 4: - rdp->flags |= AR_F_SPAN; - break; - } - - for (disk = 0; disk < total_disks; disk++) - AD_SOFTC(rdp->disks[disk])->flags = AD_F_RAID_SUBDISK; - - rdp->lun = array; - if (rdp->flags & AR_F_RAID0) { - int bit = 0; - - while (setup->interleave >>= 1) - bit++; - if (rdp->flags & AR_F_PROMISE_RAID) - rdp->interleave = min(max(2, 1 << bit), 2048); - if (rdp->flags & AR_F_HIGHPOINT_RAID) - rdp->interleave = min(max(32, 1 << bit), 128); - } - rdp->total_disks = total_disks; - rdp->width = total_disks / ((rdp->flags & AR_F_RAID1) ? 2 : 1); - rdp->total_sectors = disk_size * rdp->width; - rdp->heads = 255; - rdp->sectors = 63; - rdp->cylinders = rdp->total_sectors / (255 * 63); - if (rdp->flags & AR_F_PROMISE_RAID) { - rdp->offset = 0; - rdp->reserved = 63; - } - if (rdp->flags & AR_F_HIGHPOINT_RAID) { - rdp->offset = HPT_LBA + 1; - rdp->reserved = HPT_LBA + 1; - } - rdp->lock_start = rdp->lock_end = 0xffffffff; - rdp->flags |= AR_F_READY; - - ar_table[array] = rdp; - ar_attach_raid(rdp, 1); - setup->unit = array; - return 0; -} - -int -ata_raid_delete(int array) -{ - struct ar_softc *rdp; - int disk; - - if (!ar_table) { - kprintf("ar: no memory for ATA raid array\n"); - return 0; - } - if (!(rdp = ar_table[array])) - return ENXIO; - - rdp->flags &= ~AR_F_READY; - for (disk = 0; disk < rdp->total_disks; disk++) { - if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) { - AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK; - ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN); - rdp->disks[disk].flags = 0; - } - } - if (rdp->flags & AR_F_PROMISE_RAID) - ar_promise_write_conf(rdp); - else - ar_highpoint_write_conf(rdp); - disk_invalidate(&rdp->disk); - disk_destroy(&rdp->disk); - kfree(rdp, M_AR); - ar_table[array] = NULL; - return 0; -} - -int -ata_raid_status(int array, struct raid_status *status) -{ - struct ar_softc *rdp; - int i; - - if (!ar_table || !(rdp = ar_table[array])) - return ENXIO; - - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_RAID0: - status->type = AR_RAID0; - break; - case AR_F_RAID1: - status->type = AR_RAID1; - break; - case AR_F_RAID0 | AR_F_RAID1: - status->type = AR_RAID0 | AR_RAID1; - break; - case AR_F_SPAN: - status->type = AR_SPAN; - break; - } - status->total_disks = rdp->total_disks; - for (i = 0; i < rdp->total_disks; i++ ) { - if ((rdp->disks[i].flags & AR_DF_PRESENT) && rdp->disks[i].device) - status->disks[i] = AD_SOFTC(rdp->disks[i])->lun; - else - status->disks[i] = -1; - } - status->interleave = rdp->interleave; - status->status = 0; - if (rdp->flags & AR_F_READY) - status->status |= AR_READY; - if (rdp->flags & AR_F_DEGRADED) - status->status |= AR_DEGRADED; - if (rdp->flags & AR_F_REBUILDING) { - status->status |= AR_REBUILDING; - status->progress = 100*rdp->lock_start/(rdp->total_sectors/rdp->width); - } - return 0; -} - -int -ata_raid_rebuild(int array) -{ - struct ar_softc *rdp; - - if (!ar_table || !(rdp = ar_table[array])) - return ENXIO; - if (rdp->flags & AR_F_REBUILDING) - return EBUSY; - /* create process here XXX SOS */ - return ar_rebuild(rdp); -} - -static int -aropen(struct dev_open_args *ap) -{ -#if 0 - struct ar_softc *rdp = ap->a_head.a_dev->si_drv1; - struct disk_info info; - - bzero(&info, sizeof(info)); - info.d_media_blksize = DEV_BSIZE; /* mandatory */ - info.d_media_blocks = rdp->total_sectors; - - info.d_secpertrack = rdp->sectors; /* optional */ - info.d_nheads = rdp->heads; - info.d_ncylinders = rdp->cylinders; - info.d_secpercyl = rdp->sectors * rdp->heads; - disk_setdiskinfo(&rdp->disk, &info); - return 0; -#endif -} - -static int -arstrategy(struct dev_strategy_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct bio *bio = ap->a_bio; - struct buf *bp = bio->bio_buf; - struct ar_softc *rdp = dev->si_drv1; - int blkno, count, chunk, lba, lbs, tmplba; - int orig_blkno; - int buf1_blkno; - int drv = 0, change = 0; - caddr_t data; - - if (!(rdp->flags & AR_F_READY)) { - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return(0); - } - - KKASSERT((bio->bio_offset & DEV_BMASK) == 0); - - bp->b_resid = bp->b_bcount; - blkno = (int)(bio->bio_offset >> DEV_BSHIFT); - orig_blkno = blkno; - data = bp->b_data; - - for (count = howmany(bp->b_bcount, DEV_BSIZE); count > 0; - count -= chunk, blkno += chunk, data += (chunk * DEV_BSIZE)) { - struct ar_buf *buf1, *buf2; - - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_SPAN: - lba = blkno; - while (lba >= AD_SOFTC(rdp->disks[drv])->total_secs-rdp->reserved) - lba -= AD_SOFTC(rdp->disks[drv++])->total_secs-rdp->reserved; - chunk = min(AD_SOFTC(rdp->disks[drv])->total_secs-rdp->reserved-lba, - count); - break; - - case AR_F_RAID0: - case AR_F_RAID0 | AR_F_RAID1: - tmplba = blkno / rdp->interleave; - chunk = blkno % rdp->interleave; - if (tmplba == rdp->total_sectors / rdp->interleave) { - lbs = (rdp->total_sectors-(tmplba*rdp->interleave))/rdp->width; - drv = chunk / lbs; - lba = ((tmplba/rdp->width)*rdp->interleave) + chunk%lbs; - chunk = min(count, lbs); - } - else { - drv = tmplba % rdp->width; - lba = ((tmplba / rdp->width) * rdp->interleave) + chunk; - chunk = min(count, rdp->interleave - chunk); - } - break; - - case AR_F_RAID1: - drv = 0; - lba = blkno; - chunk = count; - break; - - default: - kprintf("ar%d: unknown array type in arstrategy\n", rdp->lun); - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return(0); - } - - buf1 = kmalloc(sizeof(struct ar_buf), M_AR, M_INTWAIT | M_ZERO); - initbufbio(&buf1->bp); - BUF_LOCK(&buf1->bp, LK_EXCLUSIVE); - buf1->bp.b_bio1.bio_offset = (off_t)lba << DEV_BSHIFT; - if ((buf1->drive = drv) > 0) - buf1->bp.b_bio1.bio_offset += (off_t)rdp->offset << DEV_BSHIFT; - buf1->bp.b_bio1.bio_caller_info1.ptr = (void *)rdp; - buf1->bp.b_bcount = chunk * DEV_BSIZE; - buf1->bp.b_data = data; - buf1->bp.b_flags = bp->b_flags | B_PAGING; - buf1->bp.b_cmd = bp->b_cmd; - buf1->bp.b_bio1.bio_done = ar_done; - buf1->org = bio; - buf1_blkno = (int)(buf1->bp.b_bio1.bio_offset >> DEV_BSHIFT); - - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_SPAN: - case AR_F_RAID0: - if ((rdp->disks[buf1->drive].flags & - (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) && - !AD_SOFTC(rdp->disks[buf1->drive])->dev) { - rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE; - ar_config_changed(rdp, 1); - BUF_UNLOCK(&buf1->bp); - uninitbufbio(&buf1->bp); - kfree(buf1, M_AR); - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return(0); - } - dev_dstrategy(AD_SOFTC(rdp->disks[buf1->drive])->dev, - &buf1->bp.b_bio1); - break; - - case AR_F_RAID1: - case AR_F_RAID0 | AR_F_RAID1: - if ((rdp->flags & AR_F_REBUILDING) && bp->b_cmd != BUF_CMD_READ) { - if ((orig_blkno >= rdp->lock_start && - orig_blkno < rdp->lock_end) || - ((orig_blkno + chunk) > rdp->lock_start && - (orig_blkno + chunk) <= rdp->lock_end)) { - tsleep(rdp, 0, "arwait", 0); - } - } - if ((rdp->disks[buf1->drive].flags & - (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) && - !AD_SOFTC(rdp->disks[buf1->drive])->dev) { - rdp->disks[buf1->drive].flags &= ~AR_DF_ONLINE; - change = 1; - } - if ((rdp->disks[buf1->drive + rdp->width].flags & - (AR_DF_PRESENT|AR_DF_ONLINE))==(AR_DF_PRESENT|AR_DF_ONLINE) && - !AD_SOFTC(rdp->disks[buf1->drive + rdp->width])->dev) { - rdp->disks[buf1->drive + rdp->width].flags &= ~AR_DF_ONLINE; - change = 1; - } - if (change) - ar_config_changed(rdp, 1); - - if (!(rdp->flags & AR_F_READY)) { - BUF_UNLOCK(&buf1->bp); - uninitbufbio(&buf1->bp); - kfree(buf1, M_AR); - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return(0); - } - if (bp->b_cmd == BUF_CMD_READ) { - if ((buf1_blkno < - (rdp->disks[buf1->drive].last_lba - AR_PROXIMITY) || - buf1_blkno > - (rdp->disks[buf1->drive].last_lba + AR_PROXIMITY) || - !(rdp->disks[buf1->drive].flags & AR_DF_ONLINE)) && - (rdp->disks[buf1->drive+rdp->width].flags & AR_DF_ONLINE)) - buf1->drive = buf1->drive + rdp->width; - } else { - if ((rdp->disks[buf1->drive+rdp->width].flags & AR_DF_ONLINE) || - ((rdp->flags & AR_F_REBUILDING) && - (rdp->disks[buf1->drive+rdp->width].flags & AR_DF_SPARE) && - buf1_blkno < rdp->lock_start)) { - if ((rdp->disks[buf1->drive].flags & AR_DF_ONLINE) || - ((rdp->flags & AR_F_REBUILDING) && - (rdp->disks[buf1->drive].flags & AR_DF_SPARE) && - buf1_blkno < rdp->lock_start)) { - buf2 = kmalloc(sizeof(struct ar_buf), M_AR, M_INTWAIT); - bcopy(buf1, buf2, sizeof(struct ar_buf)); - initbufbio(&buf2->bp); - BUF_LOCK(&buf2->bp, LK_EXCLUSIVE); - buf2->bp.b_bio1.bio_offset = buf1->bp.b_bio1.bio_offset; - buf1->mirror = buf2; - buf2->mirror = buf1; - buf2->drive = buf1->drive + rdp->width; - dev_dstrategy(AD_SOFTC(rdp->disks[buf2->drive])->dev, - &buf2->bp.b_bio1); - rdp->disks[buf2->drive].last_lba = buf1_blkno + chunk; - /* XXX free buf2? */ - } - else - buf1->drive = buf1->drive + rdp->width; - } - } - dev_dstrategy(AD_SOFTC(rdp->disks[buf1->drive])->dev, - &buf1->bp.b_bio1); - rdp->disks[buf1->drive].last_lba = buf1_blkno + chunk; - break; - - default: - kprintf("ar%d: unknown array type in arstrategy\n", rdp->lun); - } - } - return(0); -} - -static void -ar_done(struct bio *bio) -{ - struct ar_softc *rdp = (struct ar_softc *)bio->bio_caller_info1.ptr; - struct ar_buf *buf = (struct ar_buf *)bio->bio_buf; - - get_mplock(); - - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_SPAN: - case AR_F_RAID0: - if (buf->bp.b_flags & B_ERROR) { - rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE; - ar_config_changed(rdp, 1); - buf->org->bio_buf->b_flags |= B_ERROR; - buf->org->bio_buf->b_error = EIO; - biodone(buf->org); - } - else { - buf->org->bio_buf->b_resid -= buf->bp.b_bcount; - if (buf->org->bio_buf->b_resid == 0) - biodone(buf->org); - } - break; - - case AR_F_RAID1: - case AR_F_RAID0 | AR_F_RAID1: - if (buf->bp.b_flags & B_ERROR) { - rdp->disks[buf->drive].flags &= ~AR_DF_ONLINE; - ar_config_changed(rdp, 1); - if (rdp->flags & AR_F_READY) { - if (buf->bp.b_cmd == BUF_CMD_READ) { - if (buf->drive < rdp->width) - buf->drive = buf->drive + rdp->width; - else - buf->drive = buf->drive - rdp->width; - buf->bp.b_flags = buf->org->bio_buf->b_flags | B_PAGING; - buf->bp.b_error = 0; - dev_dstrategy(AD_SOFTC(rdp->disks[buf->drive])->dev, - &buf->bp.b_bio1); - rel_mplock(); - return; - } - else { - if (buf->flags & AB_F_DONE) { - buf->org->bio_buf->b_resid -= buf->bp.b_bcount; - if (buf->org->bio_buf->b_resid == 0) - biodone(buf->org); - } - else - buf->mirror->flags |= AB_F_DONE; - } - } - else { - buf->org->bio_buf->b_flags |= B_ERROR; - buf->org->bio_buf->b_error = EIO; - biodone(buf->org); - } - } - else { - if (buf->bp.b_cmd != BUF_CMD_READ) { - if (buf->mirror && !(buf->flags & AB_F_DONE)){ - buf->mirror->flags |= AB_F_DONE; - break; - } - } - buf->org->bio_buf->b_resid -= buf->bp.b_bcount; - if (buf->org->bio_buf->b_resid == 0) - biodone(buf->org); - } - break; - - default: - kprintf("ar%d: unknown array type in ar_done\n", rdp->lun); - } - BUF_UNLOCK(&buf->bp); - uninitbufbio(&buf->bp); - kfree(buf, M_AR); - rel_mplock(); -} - -static void -ar_config_changed(struct ar_softc *rdp, int writeback) -{ - int disk, flags; - - flags = rdp->flags; - rdp->flags |= AR_F_READY; - rdp->flags &= ~AR_F_DEGRADED; - - for (disk = 0; disk < rdp->total_disks; disk++) - if (!(rdp->disks[disk].flags & AR_DF_PRESENT)) - rdp->disks[disk].flags &= ~AR_DF_ONLINE; - - for (disk = 0; disk < rdp->total_disks; disk++) { - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_SPAN: - case AR_F_RAID0: - if (!(rdp->disks[disk].flags & AR_DF_ONLINE)) { - rdp->flags &= ~AR_F_READY; - kprintf("ar%d: ERROR - array broken\n", rdp->lun); - } - break; - - case AR_F_RAID1: - case AR_F_RAID0 | AR_F_RAID1: - if (disk < rdp->width) { - if (!(rdp->disks[disk].flags & AR_DF_ONLINE) && - !(rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE)) { - rdp->flags &= ~AR_F_READY; - kprintf("ar%d: ERROR - array broken\n", rdp->lun); - } - else if (((rdp->disks[disk].flags & AR_DF_ONLINE) && - !(rdp->disks - [disk + rdp->width].flags & AR_DF_ONLINE))|| - (!(rdp->disks[disk].flags & AR_DF_ONLINE) && - (rdp->disks - [disk + rdp->width].flags & AR_DF_ONLINE))) { - rdp->flags |= AR_F_DEGRADED; - if (!(flags & AR_F_DEGRADED)) - kprintf("ar%d: WARNING - mirror lost\n", rdp->lun); - } - } - break; - } - if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) { - if (rdp->disks[disk].flags & AR_DF_ONLINE) - ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_GREEN); - else - ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_RED); - } - } - if (writeback) { - if (rdp->flags & AR_F_PROMISE_RAID) - ar_promise_write_conf(rdp); - if (rdp->flags & AR_F_HIGHPOINT_RAID) - ar_highpoint_write_conf(rdp); - } -} - -static int -ar_rebuild(struct ar_softc *rdp) -{ - int disk, count = 0, error = 0; - caddr_t buffer; - - if ((rdp->flags & (AR_F_READY|AR_F_DEGRADED)) != (AR_F_READY|AR_F_DEGRADED)) - return EEXIST; - - for (disk = 0; disk < rdp->total_disks; disk++) { - if (((rdp->disks[disk].flags&(AR_DF_PRESENT|AR_DF_ONLINE|AR_DF_SPARE))== - (AR_DF_PRESENT | AR_DF_SPARE)) && rdp->disks[disk].device) { - if (AD_SOFTC(rdp->disks[disk])->total_secs < - rdp->disks[disk].disk_sectors) { - ata_prtdev(rdp->disks[disk].device, - "disk capacity too small for this RAID config\n"); -#if 0 - rdp->disks[disk].flags &= ~AR_DF_SPARE; - AD_SOFTC(rdp->disks[disk])->flags &= ~AD_F_RAID_SUBDISK; -#endif - continue; - } - ata_enclosure_leds(rdp->disks[disk].device, ATA_LED_ORANGE); - count++; - } - } - if (!count) - return ENODEV; - - /* setup start conditions */ - crit_enter(); - rdp->lock_start = 0; - rdp->lock_end = rdp->lock_start + 256; - rdp->flags |= AR_F_REBUILDING; - crit_exit(); - buffer = kmalloc(256 * DEV_BSIZE, M_AR, M_WAITOK | M_ZERO); - - /* now go copy entire disk(s) */ - while (rdp->lock_end < (rdp->total_sectors / rdp->width)) { - int size = min(256, (rdp->total_sectors / rdp->width) - rdp->lock_end); - - for (disk = 0; disk < rdp->width; disk++) { - struct ad_softc *adp; - - if (((rdp->disks[disk].flags & AR_DF_ONLINE) && - (rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE)) || - ((rdp->disks[disk].flags & AR_DF_ONLINE) && - !(rdp->disks[disk + rdp->width].flags & AR_DF_SPARE)) || - ((rdp->disks[disk + rdp->width].flags & AR_DF_ONLINE) && - !(rdp->disks[disk].flags & AR_DF_SPARE))) - continue; - - if (rdp->disks[disk].flags & AR_DF_ONLINE) - adp = AD_SOFTC(rdp->disks[disk]); - else - adp = AD_SOFTC(rdp->disks[disk + rdp->width]); - if ((error = ar_rw(adp, rdp->lock_start, - size * DEV_BSIZE, buffer, AR_READ | AR_WAIT))) - break; - - if (rdp->disks[disk].flags & AR_DF_ONLINE) - adp = AD_SOFTC(rdp->disks[disk + rdp->width]); - else - adp = AD_SOFTC(rdp->disks[disk]); - if ((error = ar_rw(adp, rdp->lock_start, - size * DEV_BSIZE, buffer, AR_WRITE | AR_WAIT))) - break; - } - if (error) { - wakeup(rdp); - kfree(buffer, M_AR); - return error; - } - crit_enter(); - rdp->lock_start = rdp->lock_end; - rdp->lock_end = rdp->lock_start + size; - crit_exit(); - wakeup(rdp); - } - kfree(buffer, M_AR); - for (disk = 0; disk < rdp->total_disks; disk++) { - if ((rdp->disks[disk].flags&(AR_DF_PRESENT|AR_DF_ONLINE|AR_DF_SPARE))== - (AR_DF_PRESENT | AR_DF_SPARE)) { - rdp->disks[disk].flags &= ~AR_DF_SPARE; - rdp->disks[disk].flags |= (AR_DF_ASSIGNED | AR_DF_ONLINE); - } - } - crit_enter(); - rdp->lock_start = 0xffffffff; - rdp->lock_end = 0xffffffff; - rdp->flags &= ~AR_F_REBUILDING; - crit_exit(); - ar_config_changed(rdp, 1); - return 0; -} - -static int -ar_highpoint_read_conf(struct ad_softc *adp, struct ar_softc **raidp) -{ - struct highpoint_raid_conf *info; - struct ar_softc *raid = NULL; - int array, disk_number = 0, retval = 0; - - info = kmalloc(sizeof(struct highpoint_raid_conf), M_AR, M_INTWAIT|M_ZERO); - - if (ar_rw(adp, HPT_LBA, sizeof(struct highpoint_raid_conf), - (caddr_t)info, AR_READ | AR_WAIT)) { - if (bootverbose) - kprintf("ar: HighPoint read conf failed\n"); - goto highpoint_out; - } - - /* check if this is a HighPoint RAID struct */ - if (info->magic != HPT_MAGIC_OK && info->magic != HPT_MAGIC_BAD) { - if (bootverbose) - kprintf("ar: HighPoint check1 failed\n"); - goto highpoint_out; - } - - /* is this disk defined, or an old leftover/spare ? */ - if (!info->magic_0) { - if (bootverbose) - kprintf("ar: HighPoint check2 failed\n"); - goto highpoint_out; - } - - /* now convert HighPoint config info into our generic form */ - for (array = 0; array < MAX_ARRAYS; array++) { - if (!raidp[array]) { - raidp[array] = kmalloc(sizeof(struct ar_softc), M_AR, - M_INTWAIT | M_ZERO); - } - raid = raidp[array]; - if (raid->flags & AR_F_PROMISE_RAID) - continue; - - switch (info->type) { - case HPT_T_RAID0: - if ((info->order & (HPT_O_RAID0|HPT_O_OK))==(HPT_O_RAID0|HPT_O_OK)) - goto highpoint_raid1; - if (info->order & (HPT_O_RAID0 | HPT_O_RAID1)) - goto highpoint_raid01; - if (raid->magic_0 && raid->magic_0 != info->magic_0) - continue; - raid->magic_0 = info->magic_0; - raid->flags |= AR_F_RAID0; - raid->interleave = 1 << info->stripe_shift; - disk_number = info->disk_number; - if (!(info->order & HPT_O_OK)) - info->magic = 0; /* mark bad */ - break; - - case HPT_T_RAID1: -highpoint_raid1: - if (raid->magic_0 && raid->magic_0 != info->magic_0) - continue; - raid->magic_0 = info->magic_0; - raid->flags |= AR_F_RAID1; - disk_number = (info->disk_number > 0); - break; - - case HPT_T_RAID01_RAID0: -highpoint_raid01: - if (info->order & HPT_O_RAID0) { - if ((raid->magic_0 && raid->magic_0 != info->magic_0) || - (raid->magic_1 && raid->magic_1 != info->magic_1)) - continue; - raid->magic_0 = info->magic_0; - raid->magic_1 = info->magic_1; - raid->flags |= (AR_F_RAID0 | AR_F_RAID1); - raid->interleave = 1 << info->stripe_shift; - disk_number = info->disk_number; - } - else { - if (raid->magic_1 && raid->magic_1 != info->magic_1) - continue; - raid->magic_1 = info->magic_1; - raid->flags |= (AR_F_RAID0 | AR_F_RAID1); - raid->interleave = 1 << info->stripe_shift; - disk_number = info->disk_number + info->array_width; - if (!(info->order & HPT_O_RAID1)) - info->magic = 0; /* mark bad */ - } - break; - - case HPT_T_SPAN: - if (raid->magic_0 && raid->magic_0 != info->magic_0) - continue; - raid->magic_0 = info->magic_0; - raid->flags |= AR_F_SPAN; - disk_number = info->disk_number; - break; - - default: - kprintf("ar%d: HighPoint unknown RAID type 0x%02x\n", - array, info->type); - goto highpoint_out; - } - - raid->flags |= AR_F_HIGHPOINT_RAID; - raid->disks[disk_number].device = adp->device; - raid->disks[disk_number].flags = (AR_DF_PRESENT | AR_DF_ASSIGNED); - raid->lun = array; - if (info->magic == HPT_MAGIC_OK) { - raid->disks[disk_number].flags |= AR_DF_ONLINE; - raid->flags |= AR_F_READY; - raid->width = info->array_width; - raid->heads = 255; - raid->sectors = 63; - raid->cylinders = info->total_sectors / (63 * 255); - raid->total_sectors = info->total_sectors; - raid->offset = HPT_LBA + 1; - raid->reserved = HPT_LBA + 1; - raid->lock_start = raid->lock_end = info->rebuild_lba; - raid->disks[disk_number].disk_sectors = - info->total_sectors / info->array_width; - } - else - raid->disks[disk_number].flags &= ~ AR_DF_ONLINE; - - if ((raid->flags & AR_F_RAID0) && (raid->total_disks < raid->width)) - raid->total_disks = raid->width; - if (disk_number >= raid->total_disks) - raid->total_disks = disk_number + 1; - retval = 1; - break; - } -highpoint_out: - kfree(info, M_AR); - return retval; -} - -static int -ar_highpoint_write_conf(struct ar_softc *rdp) -{ - struct highpoint_raid_conf *config; - struct timeval timestamp; - int disk; - - microtime(×tamp); - rdp->magic_0 = timestamp.tv_sec + 2; - rdp->magic_1 = timestamp.tv_sec; - - for (disk = 0; disk < rdp->total_disks; disk++) { - config = kmalloc(sizeof(struct highpoint_raid_conf), - M_AR, M_INTWAIT | M_ZERO); - if ((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) == - (AR_DF_PRESENT | AR_DF_ONLINE)) - config->magic = HPT_MAGIC_OK; - if (rdp->disks[disk].flags & AR_DF_ASSIGNED) { - config->magic_0 = rdp->magic_0; - strcpy(config->name_1, "FreeBSD"); - } - config->disk_number = disk; - - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_RAID0: - config->type = HPT_T_RAID0; - strcpy(config->name_2, "RAID 0"); - if (rdp->disks[disk].flags & AR_DF_ONLINE) - config->order = HPT_O_OK; - break; - - case AR_F_RAID1: - config->type = HPT_T_RAID0; /* bogus but old HPT BIOS need it */ - strcpy(config->name_2, "RAID 1"); - config->disk_number = (disk < rdp->width) ? disk : disk + 5; - config->order = HPT_O_RAID0 | HPT_O_OK; - break; - - case AR_F_RAID0 | AR_F_RAID1: - config->type = HPT_T_RAID01_RAID0; - strcpy(config->name_2, "RAID 0+1"); - if (rdp->disks[disk].flags & AR_DF_ONLINE) { - if (disk < rdp->width) { - config->order = (HPT_O_RAID0 | HPT_O_RAID1); - config->magic_0 = rdp->magic_0 - 1; - } - else { - config->order = HPT_O_RAID1; - config->disk_number -= rdp->width; - } - } - else - config->magic_0 = rdp->magic_0 - 1; - config->magic_1 = rdp->magic_1; - break; - - case AR_F_SPAN: - config->type = HPT_T_SPAN; - strcpy(config->name_2, "SPAN"); - break; - } - - config->array_width = rdp->width; - config->stripe_shift = (rdp->width > 1) ? (ffs(rdp->interleave)-1) : 0; - config->total_sectors = rdp->total_sectors; - config->rebuild_lba = rdp->lock_start; - - if ((rdp->disks[disk].device && rdp->disks[disk].device->driver) && - !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) { - - if (ar_rw(AD_SOFTC(rdp->disks[disk]), HPT_LBA, - sizeof(struct highpoint_raid_conf), - (caddr_t)config, AR_WRITE)) { - kprintf("ar%d: Highpoint write conf failed\n", rdp->lun); - return -1; - } - } - } - return 0; -} - -static int -ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp, int local) -{ - struct promise_raid_conf *info; - struct ar_softc *raid; - u_int32_t magic, cksum, *ckptr; - int array, count, disk, disksum = 0, retval = 0; - - info = kmalloc(sizeof(struct promise_raid_conf), M_AR, M_INTWAIT | M_ZERO); - - if (ar_rw(adp, PR_LBA(adp), sizeof(struct promise_raid_conf), - (caddr_t)info, AR_READ | AR_WAIT)) { - if (bootverbose) - kprintf("ar: %s read conf failed\n", local ? "FreeBSD" : "Promise"); - goto promise_out; - } - - /* check if this is a Promise RAID struct (or our local one) */ - if (local) { - if (strncmp(info->promise_id, ATA_MAGIC, sizeof(ATA_MAGIC))) { - if (bootverbose) - kprintf("ar: FreeBSD check1 failed\n"); - goto promise_out; - } - } - else { - if (strncmp(info->promise_id, PR_MAGIC, sizeof(PR_MAGIC))) { - if (bootverbose) - kprintf("ar: Promise check1 failed\n"); - goto promise_out; - } - } - - /* check if the checksum is OK */ - for (cksum = 0, ckptr = (int32_t *)info, count = 0; count < 511; count++) - cksum += *ckptr++; - if (cksum != *ckptr) { - if (bootverbose) - kprintf("ar: %s check2 failed\n", local ? "FreeBSD" : "Promise"); - goto promise_out; - } - - /* now convert Promise config info into our generic form */ - if (info->raid.integrity != PR_I_VALID) { - if (bootverbose) - kprintf("ar: %s check3 failed\n", local ? "FreeBSD" : "Promise"); - goto promise_out; - } - - for (array = 0; array < MAX_ARRAYS; array++) { - if (!raidp[array]) { - raidp[array] = kmalloc(sizeof(struct ar_softc), M_AR, - M_INTWAIT | M_ZERO); - } - raid = raidp[array]; - if (raid->flags & AR_F_HIGHPOINT_RAID) - continue; - - magic = (adp->device->channel->chiptype >> 16) | - (info->raid.array_number << 16); - - if ((raid->flags & AR_F_PROMISE_RAID) && magic != raid->magic_0) - continue; - - /* update our knowledge about the array config based on generation */ - if (!info->raid.generation || info->raid.generation > raid->generation){ - raid->generation = info->raid.generation; - raid->flags = AR_F_PROMISE_RAID; - if (local) - raid->flags |= AR_F_FREEBSD_RAID; - raid->magic_0 = magic; - raid->lun = array; - if ((info->raid.status & - (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) == - (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY)) { - raid->flags |= AR_F_READY; - if (info->raid.status & PR_S_DEGRADED) - raid->flags |= AR_F_DEGRADED; - } - else - raid->flags &= ~AR_F_READY; - - switch (info->raid.type) { - case PR_T_RAID0: - raid->flags |= AR_F_RAID0; - break; - - case PR_T_RAID1: - raid->flags |= AR_F_RAID1; - if (info->raid.array_width > 1) - raid->flags |= AR_F_RAID0; - break; - - case PR_T_SPAN: - raid->flags |= AR_F_SPAN; - break; - - default: - kprintf("ar%d: %s unknown RAID type 0x%02x\n", - array, local ? "FreeBSD" : "Promise", info->raid.type); - goto promise_out; - } - raid->interleave = 1 << info->raid.stripe_shift; - raid->width = info->raid.array_width; - raid->total_disks = info->raid.total_disks; - raid->heads = info->raid.heads + 1; - raid->sectors = info->raid.sectors; - raid->cylinders = info->raid.cylinders + 1; - raid->total_sectors = info->raid.total_sectors; - raid->offset = 0; - raid->reserved = 63; - raid->lock_start = raid->lock_end = info->raid.rebuild_lba; - - /* convert disk flags to our internal types */ - for (disk = 0; disk < info->raid.total_disks; disk++) { - raid->disks[disk].flags = 0; - disksum += info->raid.disk[disk].flags; - if (info->raid.disk[disk].flags & PR_F_ONLINE) - raid->disks[disk].flags |= AR_DF_ONLINE; - if (info->raid.disk[disk].flags & PR_F_ASSIGNED) - raid->disks[disk].flags |= AR_DF_ASSIGNED; - if (info->raid.disk[disk].flags & PR_F_SPARE) { - raid->disks[disk].flags &= ~AR_DF_ONLINE; - raid->disks[disk].flags |= AR_DF_SPARE; - } - if (info->raid.disk[disk].flags & (PR_F_REDIR | PR_F_DOWN)) - raid->disks[disk].flags &= ~AR_DF_ONLINE; - } - if (!disksum) { - kfree(raidp[array], M_AR); - raidp[array] = NULL; - goto promise_out; - } - } - if (raid->disks[info->raid.disk_number].flags && adp->device) { - raid->disks[info->raid.disk_number].device = adp->device; - raid->disks[info->raid.disk_number].flags |= AR_DF_PRESENT; - raid->disks[info->raid.disk_number].disk_sectors = - info->raid.total_sectors / info->raid.array_width; - /*info->raid.disk_sectors;*/ - retval = 1; - } - break; - } -promise_out: - kfree(info, M_AR); - return retval; -} - -static int -ar_promise_write_conf(struct ar_softc *rdp) -{ - struct promise_raid_conf *config; - struct timeval timestamp; - u_int32_t *ckptr; - int count, disk, drive; - int local = rdp->flags & AR_F_FREEBSD_RAID; - - rdp->generation++; - microtime(×tamp); - - for (disk = 0; disk < rdp->total_disks; disk++) { - config = kmalloc(sizeof(struct promise_raid_conf), M_AR, M_INTWAIT); - for (count = 0; count < sizeof(struct promise_raid_conf); count++) - *(((u_int8_t *)config) + count) = 255 - (count % 256); - - if (local) - bcopy(ATA_MAGIC, config->promise_id, sizeof(ATA_MAGIC)); - else - bcopy(PR_MAGIC, config->promise_id, sizeof(PR_MAGIC)); - config->dummy_0 = 0x00020000; - config->magic_0 = PR_MAGIC0(rdp->disks[disk]) | timestamp.tv_sec; - config->magic_1 = timestamp.tv_sec >> 16; - config->magic_2 = timestamp.tv_sec; - config->raid.integrity = PR_I_VALID; - - config->raid.disk_number = disk; - if ((rdp->disks[disk].flags&AR_DF_PRESENT) && rdp->disks[disk].device) { - config->raid.channel = rdp->disks[disk].device->channel->unit; - config->raid.device = (rdp->disks[disk].device->unit != 0); - if (AD_SOFTC(rdp->disks[disk])->dev) - config->raid.disk_sectors = PR_LBA(AD_SOFTC(rdp->disks[disk])); - /*config->raid.disk_offset*/ - } - config->raid.magic_0 = config->magic_0; - config->raid.rebuild_lba = rdp->lock_start; - config->raid.generation = rdp->generation; - - if (rdp->flags & AR_F_READY) { - config->raid.flags = (PR_F_VALID | PR_F_ASSIGNED | PR_F_ONLINE); - config->raid.status = - (PR_S_VALID | PR_S_ONLINE | PR_S_INITED | PR_S_READY); - if (rdp->flags & AR_F_DEGRADED) - config->raid.status |= PR_S_DEGRADED; - else - config->raid.status |= PR_S_FUNCTIONAL; - } - else { - config->raid.status = 0; - config->raid.flags = PR_F_DOWN; - } - - switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { - case AR_F_RAID0: - config->raid.type = PR_T_RAID0; - break; - case AR_F_RAID1: - config->raid.type = PR_T_RAID1; - break; - case AR_F_RAID0 | AR_F_RAID1: - config->raid.type = PR_T_RAID1; - break; - case AR_F_SPAN: - config->raid.type = PR_T_SPAN; - break; - } - - config->raid.total_disks = rdp->total_disks; - config->raid.stripe_shift = ffs(rdp->interleave) - 1; - config->raid.array_width = rdp->width; - config->raid.array_number = rdp->lun; - config->raid.total_sectors = rdp->total_sectors; - config->raid.cylinders = rdp->cylinders - 1; - config->raid.heads = rdp->heads - 1; - config->raid.sectors = rdp->sectors; - config->raid.magic_1 = (u_int64_t)config->magic_2<<16 | config->magic_1; - - bzero(&config->raid.disk, 8 * 12); - for (drive = 0; drive < rdp->total_disks; drive++) { - config->raid.disk[drive].flags = 0; - if (rdp->disks[drive].flags & AR_DF_PRESENT) - config->raid.disk[drive].flags |= PR_F_VALID; - if (rdp->disks[drive].flags & AR_DF_ASSIGNED) - config->raid.disk[drive].flags |= PR_F_ASSIGNED; - if (rdp->disks[drive].flags & AR_DF_ONLINE) - config->raid.disk[drive].flags |= PR_F_ONLINE; - else - if (rdp->disks[drive].flags & AR_DF_PRESENT) - config->raid.disk[drive].flags = (PR_F_REDIR | PR_F_DOWN); - if (rdp->disks[drive].flags & AR_DF_SPARE) - config->raid.disk[drive].flags |= PR_F_SPARE; - config->raid.disk[drive].dummy_0 = 0x0; - if (rdp->disks[drive].device) { - config->raid.disk[drive].channel = - rdp->disks[drive].device->channel->unit; - config->raid.disk[drive].device = - (rdp->disks[drive].device->unit != 0); - } - config->raid.disk[drive].magic_0 = - PR_MAGIC0(rdp->disks[drive]) | timestamp.tv_sec; - } - - config->checksum = 0; - for (ckptr = (int32_t *)config, count = 0; count < 511; count++) - config->checksum += *ckptr++; - if (rdp->disks[disk].device && rdp->disks[disk].device->driver && - !(rdp->disks[disk].device->flags & ATA_D_DETACHING)) { - if (ar_rw(AD_SOFTC(rdp->disks[disk]), - PR_LBA(AD_SOFTC(rdp->disks[disk])), - sizeof(struct promise_raid_conf), - (caddr_t)config, AR_WRITE)) { - kprintf("ar%d: %s write conf failed\n", - rdp->lun, local ? "FreeBSD" : "Promise"); - return -1; - } - } - } - return 0; -} - -static void -ar_rw_done(struct bio *bio) -{ - struct buf *bp = bio->bio_buf; - - BUF_UNLOCK(bp); - uninitbufbio(bp); - kfree(bp->b_data, M_AR); - kfree(bp, M_AR); -} - -static int -ar_rw(struct ad_softc *adp, u_int32_t lba, int count, caddr_t data, int flags) -{ - struct buf *bp; - int retry = 0, error = 0; - - bp = kmalloc(sizeof(struct buf), M_AR, M_INTWAIT|M_ZERO); - initbufbio(bp); - BUF_LOCK(bp, LK_EXCLUSIVE); - bp->b_data = data; - bp->b_bio1.bio_offset = (off_t)lba << DEV_BSHIFT; - bp->b_bcount = count; - if (flags & AR_WAIT) { - bp->b_bio1.bio_flags |= BIO_SYNC; - bp->b_bio1.bio_done = biodone_sync; - } else { - bp->b_bio1.bio_done = ar_rw_done; - } - if (flags & AR_READ) - bp->b_cmd = BUF_CMD_READ; - if (flags & AR_WRITE) - bp->b_cmd = BUF_CMD_WRITE; - KKASSERT(bp->b_cmd != BUF_CMD_DONE); - - dev_dstrategy(adp->dev, &bp->b_bio1); - - if (flags & AR_WAIT) { - while (retry++ < (15*hz/10)) - error = biowait_timeout(&bp->b_bio1, "arrw", 10); - if (!error && (bp->b_flags & B_ERROR)) - error = bp->b_error; - if (error == EWOULDBLOCK) { - bp->b_bio1.bio_done = ar_rw_done; - } else { - BUF_UNLOCK(bp); - uninitbufbio(bp); - kfree(bp, M_AR); - } - } - return error; -} - -static struct ata_device * -ar_locate_disk(int diskno) -{ - struct ata_channel *ch; - int ctlr; - - for (ctlr = 0; ctlr < devclass_get_maxunit(ata_devclass); ctlr++) { - if (!(ch = devclass_get_softc(ata_devclass, ctlr))) - continue; - if (ch->devices & ATA_ATA_MASTER) - if (ch->device[MASTER].driver && - ((struct ad_softc *)(ch->device[MASTER].driver))->lun == diskno) - return &ch->device[MASTER]; - if (ch->devices & ATA_ATA_SLAVE) - if (ch->device[SLAVE].driver && - ((struct ad_softc *)(ch->device[SLAVE].driver))->lun == diskno) - return &ch->device[SLAVE]; - } - return NULL; -} diff --git a/sys/dev/disk/ata/ata-raid.h b/sys/dev/disk/ata/ata-raid.h deleted file mode 100644 index 3e45423bb6..0000000000 --- a/sys/dev/disk/ata/ata-raid.h +++ /dev/null @@ -1,233 +0,0 @@ -/*- - * Copyright (c) 2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/ata-raid.h,v 1.2.2.8 2002/04/11 09:31:57 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/ata-raid.h,v 1.6 2006/09/10 01:26:33 dillon Exp $ - */ - -/* misc defines */ -#define MAX_ARRAYS 16 -#define MAX_DISKS 16 -#define AR_PROXIMITY 2048 -#define AR_READ 0x01 -#define AR_WRITE 0x02 -#define AR_WAIT 0x04 -#define AD_SOFTC(x) ((struct ad_softc *)(x.device->driver)) -#define ATA_MAGIC "FreeBSD ATA driver RAID " - -struct ar_disk { - struct ata_device *device; - u_int64_t disk_sectors; /* sectors on this disk */ - off_t last_lba; /* last lba used */ - int flags; -#define AR_DF_PRESENT 0x00000001 -#define AR_DF_ASSIGNED 0x00000002 -#define AR_DF_SPARE 0x00000004 -#define AR_DF_ONLINE 0x00000008 -}; - -struct ar_softc { - int lun; - int32_t magic_0; /* ident for this array */ - int32_t magic_1; /* ident for this array */ - int flags; -#define AR_F_RAID0 0x0001 /* STRIPE */ -#define AR_F_RAID1 0x0002 /* MIRROR */ -#define AR_F_SPAN 0x0004 /* SPAN */ -#define AR_F_READY 0x0100 -#define AR_F_DEGRADED 0x0200 -#define AR_F_REBUILDING 0x0400 -#define AR_F_PROMISE_RAID 0x1000 -#define AR_F_HIGHPOINT_RAID 0x2000 -#define AR_F_FREEBSD_RAID 0x4000 - - int total_disks; /* number of disks in this array */ - int generation; /* generation of this array */ - struct ar_disk disks[MAX_DISKS+1]; /* ptr to each disk in array */ - int width; /* array width in disks */ - u_int16_t heads; - u_int16_t sectors; - u_int32_t cylinders; - u_int64_t total_sectors; - int interleave; /* interleave in blocks */ - int reserved; /* sectors that are NOT to be used */ - int offset; /* offset from start of disk */ - u_int64_t lock_start; /* start of locked area for rebuild */ - u_int64_t lock_end; /* end of locked area for rebuild */ - struct disk disk; /* disklabel/slice stuff */ - struct proc *pid; - cdev_t dev; /* device place holder */ -}; - -struct ar_buf { - struct buf bp; /* must be first element! */ - struct bio *org; - struct ar_buf *mirror; - int drive; - int flags; -#define AB_F_DONE 0x01 -}; - -#define HPT_LBA 9 - -struct highpoint_raid_conf { - int8_t filler1[32]; - u_int32_t magic; /* 0x20 */ -#define HPT_MAGIC_OK 0x5a7816f0 -#define HPT_MAGIC_BAD 0x5a7816fd - - u_int32_t magic_0; - u_int32_t magic_1; - u_int32_t order; -#define HPT_O_RAID0 0x01 -#define HPT_O_RAID1 0x02 -#define HPT_O_OK 0x04 - - u_int8_t array_width; - u_int8_t stripe_shift; - u_int8_t type; -#define HPT_T_RAID0 0x00 -#define HPT_T_RAID1 0x01 -#define HPT_T_RAID01_RAID0 0x02 -#define HPT_T_SPAN 0x03 -#define HPT_T_RAID_3 0x04 -#define HPT_T_RAID_5 0x05 -#define HPT_T_SINGLEDISK 0x06 -#define HPT_T_RAID01_RAID1 0x07 - - u_int8_t disk_number; - u_int32_t total_sectors; - u_int32_t disk_mode; - u_int32_t boot_mode; - u_int8_t boot_disk; - u_int8_t boot_protect; - u_int8_t error_log_entries; - u_int8_t error_log_index; - struct { - u_int32_t timestamp; - u_int8_t reason; -#define HPT_R_REMOVED 0xfe -#define HPT_R_BROKEN 0xff - - u_int8_t disk; - u_int8_t status; - u_int8_t sectors; - u_int32_t lba; - } errorlog[32]; - int8_t filler2[16]; - u_int32_t rebuild_lba; - u_int8_t dummy_1; - u_int8_t name_1[15]; - u_int8_t dummy_2; - u_int8_t name_2[15]; - int8_t filler3[8]; -} __attribute__((packed)); - - -#define PR_LBA(adp) \ - (((adp->total_secs / (adp->heads * adp->sectors)) * \ - adp->heads * adp->sectors) - adp->sectors) - -struct promise_raid_conf { - char promise_id[24]; -#define PR_MAGIC "Promise Technology, Inc." - - u_int32_t dummy_0; - u_int64_t magic_0; -#define PR_MAGIC0(x) (x.device ? ((u_int64_t)x.device->channel->unit<<48) | \ - ((u_int64_t)(x.device->unit != 0) << 56) : 0) - u_int16_t magic_1; - u_int32_t magic_2; - u_int8_t filler1[470]; - struct { - u_int32_t integrity; /* 0x200 */ -#define PR_I_VALID 0x00000080 - - u_int8_t flags; -#define PR_F_VALID 0x00000001 -#define PR_F_ONLINE 0x00000002 -#define PR_F_ASSIGNED 0x00000004 -#define PR_F_SPARE 0x00000008 -#define PR_F_DUPLICATE 0x00000010 -#define PR_F_REDIR 0x00000020 -#define PR_F_DOWN 0x00000040 -#define PR_F_READY 0x00000080 - - u_int8_t disk_number; - u_int8_t channel; - u_int8_t device; - u_int64_t magic_0 __attribute__((packed)); - u_int32_t disk_offset; /* 0x210 */ - u_int32_t disk_sectors; - u_int32_t rebuild_lba; - u_int16_t generation; - u_int8_t status; -#define PR_S_VALID 0x01 -#define PR_S_ONLINE 0x02 -#define PR_S_INITED 0x04 -#define PR_S_READY 0x08 -#define PR_S_DEGRADED 0x10 -#define PR_S_MARKED 0x20 -#define PR_S_FUNCTIONAL 0x80 - - u_int8_t type; -#define PR_T_RAID0 0x00 -#define PR_T_RAID1 0x01 -#define PR_T_RAID3 0x02 -#define PR_T_RAID5 0x04 -#define PR_T_SPAN 0x08 - - u_int8_t total_disks; /* 0x220 */ - u_int8_t stripe_shift; - u_int8_t array_width; - u_int8_t array_number; - u_int32_t total_sectors; - u_int16_t cylinders; - u_int8_t heads; - u_int8_t sectors; - int64_t magic_1 __attribute__((packed)); - struct { /* 0x240 */ - u_int8_t flags; - u_int8_t dummy_0; - u_int8_t channel; - u_int8_t device; - u_int64_t magic_0 __attribute__((packed)); - } disk[8]; - } raid; - int32_t filler2[346]; - u_int32_t checksum; -} __attribute__((packed)); - -int ata_raiddisk_probe(struct ad_softc *); -int ata_raiddisk_attach(struct ad_softc *); -int ata_raiddisk_detach(struct ad_softc *); -void ata_raid_attach(void); -int ata_raid_create(struct raid_setup *); -int ata_raid_delete(int); -int ata_raid_status(int array, struct raid_status *); -int ata_raid_rebuild(int); - diff --git a/sys/dev/disk/ata/atapi-all.c b/sys/dev/disk/ata/atapi-all.c deleted file mode 100644 index a3e6258936..0000000000 --- a/sys/dev/disk/ata/atapi-all.c +++ /dev/null @@ -1,741 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-all.c,v 1.46.2.18 2002/10/31 23:10:33 thomas Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-all.c,v 1.20 2006/12/22 23:26:15 swildner Exp $ - */ - -#include "opt_ata.h" -#include "use_atapicd.h" -#include "use_atapifd.h" -#include "use_atapist.h" -#include "use_atapicam.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ata-all.h" -#include "atapi-all.h" - -/* prototypes */ -static void atapi_requeue(struct ata_channel *chan, struct atapi_request *req); -static void atapi_read(struct atapi_request *, int); -static void atapi_write(struct atapi_request *, int); -static void atapi_finish(struct atapi_request *); -static void atapi_timeout(struct atapi_request *); -static char *atapi_cmd2str(u_int8_t); -static char *atapi_skey2str(u_int8_t); - -/* misc defines */ -#define ATAPI_MAX_RETRIES 3 - -/* internal vars */ -static int atapi_dma = 0; -TUNABLE_INT("hw.ata.atapi_dma", &atapi_dma); -static MALLOC_DEFINE(M_ATAPI, "ATAPI generic", "ATAPI driver generic layer"); - -/* systcl vars */ -SYSCTL_DECL(_hw_ata); -SYSCTL_INT(_hw_ata, OID_AUTO, atapi_dma, CTLFLAG_RD, &atapi_dma, 0, - "ATAPI device DMA mode control"); - -void -atapi_attach(struct ata_device *atadev, int alreadylocked) -{ - if (bootverbose) - ata_prtdev(atadev, "piomode=%d dmamode=%d udmamode=%d dmaflag=%d\n", - ata_pmode(atadev->param), ata_wmode(atadev->param), - ata_umode(atadev->param), atadev->param->support_dma); - - if (!alreadylocked) - ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); - if (atapi_dma && !(atadev->param->drq_type == ATAPI_DRQT_INTR)) { - ata_dmainit(atadev, - (ata_pmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 4:0):ata_pmode(atadev->param), - (ata_wmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 2:0):ata_wmode(atadev->param), - ata_umode(atadev->param)); - } - else - ata_dmainit(atadev, - ata_pmode(atadev->param) < 0 ? 0 : ata_pmode(atadev->param), - -1, -1); - ATA_UNLOCK_CH(atadev->channel); - - atadev->result = kmalloc(sizeof(struct atapi_reqsense), M_ATAPI, - M_INTWAIT | M_ZERO); - - switch (atadev->param->type) { -#if NATAPICD > 0 - case ATAPI_TYPE_CDROM: - if (acdattach(atadev)) - return; - break; -#endif -#if NATAPIFD > 0 - case ATAPI_TYPE_DIRECT: - if (afdattach(atadev)) - return; - break; -#endif -#if NATAPIST > 0 - case ATAPI_TYPE_TAPE: - if (astattach(atadev)) - return; - break; -#endif - } -#if NATAPICAM == 0 - ata_prtdev(atadev, "<%.40s/%.8s> - NO DRIVER!\n", - atadev->param->model, atadev->param->revision); - kfree(atadev->result, M_ATAPI); - atadev->driver = NULL; -#endif -} - -void -atapi_detach(struct ata_device *atadev) -{ - struct atapi_request *request; - - atadev->flags |= ATA_D_DETACHING; - ata_prtdev(atadev, "removed from configuration\n"); - switch (atadev->param->type) { -#if NATAPICD > 0 - case ATAPI_TYPE_CDROM: - acddetach(atadev); - break; -#endif -#if NATAPIFD >0 - case ATAPI_TYPE_DIRECT: - afddetach(atadev); - break; -#endif -#if NATAPIST >0 - case ATAPI_TYPE_TAPE: - astdetach(atadev); - break; -#endif - default: - return; - } - TAILQ_FOREACH(request, &atadev->channel->atapi_queue, chain) { - if (request->device != atadev) - continue; - TAILQ_REMOVE(&atadev->channel->atapi_queue, request, chain); - if (request->driver) { - struct bio *bio = (struct bio *) request->driver; - bio->bio_buf->b_flags |= B_ERROR; - bio->bio_buf->b_error = ENXIO; - biodone(bio); - } - ata_dmafree(atadev); - kfree(request, M_ATAPI); - } - kfree(atadev->result, M_ATAPI); - atadev->driver = NULL; - atadev->flags = 0; - -} - -int -atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data, - int count, int flags, int timeout, - atapi_callback_t callback, void *driver) -{ - struct atapi_request *request; - int error; - - request = kmalloc(sizeof(struct atapi_request), M_ATAPI, M_INTWAIT|M_ZERO); - request->device = atadev; - request->data = data; - request->bytecount = count; - request->flags = flags; - request->error = EINPROGRESS; - request->timeout = timeout * hz; - request->ccbsize = atadev->param->packet_size ? 16 : 12; - callout_init(&request->callout); - bcopy(ccb, request->ccb, request->ccbsize); - if (callback) { - request->callback = callback; - request->driver = driver; - } - if (atadev->mode >= ATA_DMA) { - error = ata_dmaalloc(atadev, M_WAITOK); - KKASSERT(error == 0); - } - -#ifdef ATAPI_DEBUG - ata_prtdev(atadev, "queueing %s ", atapi_cmd2str(request->ccb[0])); - atapi_dump("ccb = ", &request->ccb[0], sizeof(request->ccb)); -#endif - /* append onto controller queue and try to start controller */ - crit_enter(); - if (flags & ATPR_F_AT_HEAD) - TAILQ_INSERT_HEAD(&atadev->channel->atapi_queue, request, chain); - else - TAILQ_INSERT_TAIL(&atadev->channel->atapi_queue, request, chain); - ata_start(atadev->channel); - - /* if callback used, then just return, gets called from interrupt context */ - if (callback) { - crit_exit(); - return 0; - } - - /* only sleep when command is in progress */ - if (request->error == EINPROGRESS) - tsleep((caddr_t)request, 0, "atprq", 0); - crit_exit(); - error = request->error; - if (error) - bcopy(&request->sense, atadev->result, sizeof(struct atapi_reqsense)); - kfree(request, M_ATAPI); - return error; -} - -void -atapi_start(struct ata_device *atadev) -{ - switch (atadev->param->type) { -#if NATAPICD > 0 - case ATAPI_TYPE_CDROM: - acd_start(atadev); - break; -#endif -#if NATAPIFD > 0 - case ATAPI_TYPE_DIRECT: - afd_start(atadev); - break; -#endif -#if NATAPIST > 0 - case ATAPI_TYPE_TAPE: - ast_start(atadev); - break; -#endif - default: - return; - } -} - -void -atapi_requeue(struct ata_channel *chan, struct atapi_request *req) -{ - if (req->donecount) { - ata_printf(chan, -1, - "WARNING: atapi resetting donecount %u for retry\n", - req->donecount); - req->bytecount += req->donecount; - req->donecount = 0; - } - TAILQ_INSERT_HEAD(&chan->atapi_queue, req, chain); -} - -int -atapi_transfer(struct atapi_request *request) -{ - struct ata_device *atadev = request->device; - int timout; - u_int8_t reason; - -#ifdef ATAPI_DEBUG - ata_prtdev(atadev, "starting %s ", atapi_cmd2str(request->ccb[0])); - atapi_dump("ccb = ", &request->ccb[0], sizeof(request->ccb)); -#endif - /* is this just a POLL DSC command ? */ - if (request->ccb[0] == ATAPI_POLL_DSC) { - ATA_OUTB(atadev->channel->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); - DELAY(10); - if (ATA_INB(atadev->channel->r_altio, ATA_ALTSTAT) & ATA_S_DSC) - request->error = 0; - else - request->error = EBUSY; - atapi_finish(request); - return ATA_OP_FINISHED; - } - - /* start timeout for this command */ - callout_reset(&request->callout, request->timeout, - (void *)atapi_timeout, request); - - if (!(request->flags & ATPR_F_INTERNAL)) - atadev->cmd = request->ccb[0]; - - /* if DMA enabled setup DMA hardware */ - request->flags &= ~ATPR_F_DMA_USED; - if ((atadev->mode >= ATA_DMA) && - (request->ccb[0] == ATAPI_READ || - request->ccb[0] == ATAPI_READ_BIG || - request->ccb[0] == ATAPI_READ_CD || - ((request->ccb[0] == ATAPI_WRITE || - request->ccb[0] == ATAPI_WRITE_BIG) && - !(atadev->channel->flags & ATA_ATAPI_DMA_RO))) && - !ata_dmasetup(atadev, (void *)request->data, request->bytecount)) { - request->flags |= ATPR_F_DMA_USED; - } - - /* start ATAPI operation */ - if (ata_command(atadev, ATA_C_PACKET_CMD, - min(request->bytecount, 65534) << 8, 0, - (request->flags & ATPR_F_DMA_USED) ? ATA_F_DMA : 0, - ATA_IMMEDIATE)) - ata_prtdev(atadev, "failure to send ATAPI packet command\n"); - - if (request->flags & ATPR_F_DMA_USED) - ata_dmastart(atadev, request->data, request->bytecount, - request->flags & ATPR_F_READ); - - /* command interrupt device ? just return */ - if (atadev->param->drq_type == ATAPI_DRQT_INTR) - return ATA_OP_CONTINUES; - - /* ready to write ATAPI command */ - timout = 5000; /* might be less for fast devices */ - while (timout--) { - reason = ATA_INB(atadev->channel->r_io, ATA_IREASON); - atadev->channel->status = ATA_INB(atadev->channel->r_io, ATA_STATUS); - if (((reason & (ATA_I_CMD | ATA_I_IN)) | - (atadev->channel->status&(ATA_S_DRQ|ATA_S_BUSY)))==ATAPI_P_CMDOUT) - break; - DELAY(20); - } - if (timout <= 0) { - ata_prtdev(atadev, "failure to execute ATAPI packet command\n"); - callout_stop(&request->callout); - request->error = EIO; - atapi_finish(request); - return ATA_OP_FINISHED; - } - - /* this seems to be needed for some (slow) devices */ - DELAY(10); - - /* send actual command */ - ATA_OUTSW(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, - request->ccbsize / sizeof(int16_t)); - return ATA_OP_CONTINUES; -} - -int -atapi_interrupt(struct atapi_request *request) -{ - struct ata_device *atadev = request->device; - int reason, dma_stat = 0; - - reason = (ATA_INB(atadev->channel->r_io, ATA_IREASON)&(ATA_I_CMD|ATA_I_IN))| - (atadev->channel->status & ATA_S_DRQ); - - if (reason == ATAPI_P_CMDOUT) { - if (!(atadev->channel->status & ATA_S_DRQ)) { - ata_prtdev(atadev, "command interrupt without DRQ\n"); - callout_stop(&request->callout); - request->error = EIO; - atapi_finish(request); - return ATA_OP_FINISHED; - } - ATA_OUTSW(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, - request->ccbsize / sizeof(int16_t)); - return ATA_OP_CONTINUES; - } - - if (request->flags & ATPR_F_DMA_USED) { - dma_stat = ata_dmadone(atadev); - if ((atadev->channel->status & (ATA_S_ERROR | ATA_S_DWF)) || - dma_stat & ATA_BMSTAT_ERROR) { - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); - } - else { - request->result = 0; - request->donecount = request->bytecount; - request->bytecount = 0; - } - } - else { - int length = ATA_INB(atadev->channel->r_io, ATA_CYL_LSB) | - ATA_INB(atadev->channel->r_io, ATA_CYL_MSB) << 8; - - switch (reason) { - case ATAPI_P_WRITE: - if (request->flags & ATPR_F_READ) { - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); - ata_prtdev(atadev, "%s trying to write on read buffer\n", - atapi_cmd2str(atadev->cmd)); - break; - } - atapi_write(request, length); - return ATA_OP_CONTINUES; - - case ATAPI_P_READ: - if (!(request->flags & ATPR_F_READ)) { - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); - ata_prtdev(atadev, "%s trying to read on write buffer\n", - atapi_cmd2str(atadev->cmd)); - break; - } - atapi_read(request, length); - return ATA_OP_CONTINUES; - - case ATAPI_P_DONEDRQ: - ata_prtdev(atadev, "%s DONEDRQ\n", atapi_cmd2str(atadev->cmd)); - if (request->flags & ATPR_F_READ) - atapi_read(request, length); - else - atapi_write(request, length); - /* FALLTHROUGH */ - - case ATAPI_P_ABORT: - case ATAPI_P_DONE: - if (atadev->channel->status & (ATA_S_ERROR | ATA_S_DWF)) - request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); - else - if (!(request->flags & ATPR_F_INTERNAL)) - request->result = 0; - break; - - default: - ata_prtdev(atadev, "unknown transfer phase %#x:%#x\n", - ATA_INB(atadev->channel->r_io, ATA_IREASON), reason); - request->result = ATA_S_ERROR; - } - } - callout_stop(&request->callout); - - /* check for error, if valid sense key, queue a request sense cmd */ - if ((request->result & ATAPI_SK_MASK) && - request->ccb[0] != ATAPI_REQUEST_SENSE) { - bzero(request->ccb, request->ccbsize); - request->ccb[0] = ATAPI_REQUEST_SENSE; - request->ccb[4] = sizeof(struct atapi_reqsense); - request->bytecount = sizeof(struct atapi_reqsense); - request->flags &= ATPR_F_QUIET; - request->flags |= ATPR_F_READ | ATPR_F_INTERNAL; - TAILQ_INSERT_HEAD(&atadev->channel->atapi_queue, request, chain); - } - else { - if (request->result) { - switch ((request->result & ATAPI_SK_MASK)) { - case ATAPI_SK_NO_SENSE: - request->error = 0; - break; - - case ATAPI_SK_RECOVERED_ERROR: - ata_prtdev(atadev, "%s - recovered error\n", - atapi_cmd2str(atadev->cmd)); - request->error = 0; - break; - - case ATAPI_SK_NOT_READY: - request->error = EBUSY; - break; - - case ATAPI_SK_UNIT_ATTENTION: - atadev->flags |= ATA_D_MEDIA_CHANGED; - request->error = EIO; - break; - - default: - request->error = EIO; - - if (request->flags & ATPR_F_QUIET) - break; - - ata_prtdev(atadev, "%s - %s asc=0x%02x ascq=0x%02x ", - atapi_cmd2str(atadev->cmd), - atapi_skey2str(request->sense.sense_key), - request->sense.asc, request->sense.ascq); - if (request->sense.sksv) - kprintf("sks=0x%02x 0x%02x 0x%02x ", - request->sense.sk_specific, - request->sense.sk_specific1, - request->sense.sk_specific2); - kprintf("error=0x%02x\n", request->result & ATAPI_E_MASK); - } - } - else - request->error = 0; - atapi_finish(request); - } - return ATA_OP_FINISHED; -} - -void -atapi_reinit(struct ata_device *atadev) -{ - /* reinit device parameters */ - if (atadev->mode >= ATA_DMA) - ata_dmainit(atadev, - (ata_pmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 4:0):ata_pmode(atadev->param), - (ata_wmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 2:0):ata_wmode(atadev->param), - ata_umode(atadev->param)); - else - ata_dmainit(atadev, - ata_pmode(atadev->param)<0 ? 0 : ata_pmode(atadev->param), - -1, -1); -} - -int -atapi_test_ready(struct ata_device *atadev) -{ - int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(atadev, ccb, NULL, 0, 0, 30, NULL, NULL); -} - -int -atapi_wait_dsc(struct ata_device *atadev, int timeout) -{ - int error = 0; - int8_t ccb[16] = { ATAPI_POLL_DSC, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - timeout *= hz; - while (timeout > 0) { - error = atapi_queue_cmd(atadev, ccb, NULL, 0, 0, 0, NULL, NULL); - if (error != EBUSY) - break; - tsleep((caddr_t)&error, 0, "atpwt", hz / 2); - timeout -= (hz / 2); - } - return error; -} - -void -atapi_dump(char *label, void *data, int len) -{ - u_int8_t *p = data; - - kprintf("%s %02x", label, *p++); - while (--len > 0) - kprintf ("-%02x", *p++); - kprintf("\n"); -} - -static void -atapi_read(struct atapi_request *request, int length) -{ - int8_t **buffer = (int8_t **)&request->data; - int size = min(request->bytecount, length); - struct ata_channel *ch = request->device->channel; - int resid; - - if (request->flags & ATPR_F_INTERNAL) - *buffer = (int8_t *)&request->sense; - - if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) - ATA_INSW(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int16_t)); - else - ATA_INSL(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int32_t)); - - if (request->bytecount < length) { - ata_prtdev(request->device, "read data overrun %d/%d\n", - length, request->bytecount); - for (resid=request->bytecount; residr_io, ATA_DATA); - } - *buffer += size; - request->bytecount -= size; - request->donecount += size; -} - -static void -atapi_write(struct atapi_request *request, int length) -{ - int8_t **buffer = (int8_t **)&request->data; - int size = min(request->bytecount, length); - struct ata_channel *ch = request->device->channel; - int resid; - - if (request->flags & ATPR_F_INTERNAL) - *buffer = (int8_t *)&request->sense; - - if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) - ATA_OUTSW(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int16_t)); - else - ATA_OUTSL(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int32_t)); - - if (request->bytecount < length) { - ata_prtdev(request->device, "write data underrun %d/%d\n", - length, request->bytecount); - for (resid=request->bytecount; residr_io, ATA_DATA, 0); - } - *buffer += size; - request->bytecount -= size; - request->donecount += size; -} - -static void -atapi_finish(struct atapi_request *request) -{ -#ifdef ATAPI_DEBUG - ata_prtdev(request->device, "finished %s%s\n", - request->callback ? "callback " : "", - atapi_cmd2str(request->ccb[0])); -#endif - if (request->callback) { - if (!((request->callback)(request))) { - kfree(request, M_ATAPI); - } - } - else - wakeup((caddr_t)request); -} - -static void -atapi_timeout(struct atapi_request *request) -{ - struct ata_device *atadev = request->device; - - atadev->channel->running = NULL; - ata_prtdev(atadev, "%s command timeout - resetting\n", - atapi_cmd2str(request->ccb[0])); - - if (request->flags & ATPR_F_DMA_USED) { - ata_dmadone(atadev); - if (request->retries == ATAPI_MAX_RETRIES) { - ata_dmainit(atadev, - (ata_pmode(atadev->param) < 0) ? 0 : - ata_pmode(atadev->param), -1, -1); - ata_prtdev(atadev, "trying fallback to PIO mode\n"); - request->retries = 0; - } - } - - /* if retries still permit, reinject this request */ - if (request->retries++ < ATAPI_MAX_RETRIES) { - atapi_requeue(atadev->channel, request); - } - else { - /* retries all used up, return error */ - request->error = EIO; - wakeup((caddr_t)request); - } - ata_reinit(atadev->channel); -} - -static char * -atapi_cmd2str(u_int8_t cmd) -{ - switch (cmd) { - case 0x00: return ("TEST_UNIT_READY"); - case 0x01: return ("REZERO"); - case 0x03: return ("REQUEST_SENSE"); - case 0x04: return ("FORMAT_UNIT"); - case 0x08: return ("READ"); - case 0x0a: return ("WRITE"); - case 0x10: return ("WEOF"); - case 0x11: return ("SPACE"); - case 0x15: return ("MODE_SELECT"); - case 0x19: return ("ERASE"); - case 0x1a: return ("MODE_SENSE"); - case 0x1b: return ("START_STOP"); - case 0x1e: return ("PREVENT_ALLOW"); - case 0x25: return ("READ_CAPACITY"); - case 0x28: return ("READ_BIG"); - case 0x2a: return ("WRITE_BIG"); - case 0x2b: return ("LOCATE"); - case 0x34: return ("READ_POSITION"); - case 0x35: return ("SYNCHRONIZE_CACHE"); - case 0x3b: return ("WRITE_BUFFER"); - case 0x3c: return ("READ_BUFFER"); - case 0x42: return ("READ_SUBCHANNEL"); - case 0x43: return ("READ_TOC"); - case 0x45: return ("PLAY_10"); - case 0x47: return ("PLAY_MSF"); - case 0x48: return ("PLAY_TRACK"); - case 0x4b: return ("PAUSE"); - case 0x51: return ("READ_DISK_INFO"); - case 0x52: return ("READ_TRACK_INFO"); - case 0x53: return ("RESERVE_TRACK"); - case 0x54: return ("SEND_OPC_INFO"); - case 0x55: return ("MODE_SELECT_BIG"); - case 0x58: return ("REPAIR_TRACK"); - case 0x59: return ("READ_MASTER_CUE"); - case 0x5a: return ("MODE_SENSE_BIG"); - case 0x5b: return ("CLOSE_TRACK/SESSION"); - case 0x5c: return ("READ_BUFFER_CAPACITY"); - case 0x5d: return ("SEND_CUE_SHEET"); - case 0xa1: return ("BLANK_CMD"); - case 0xa3: return ("SEND_KEY"); - case 0xa4: return ("REPORT_KEY"); - case 0xa5: return ("PLAY_12"); - case 0xa6: return ("LOAD_UNLOAD"); - case 0xad: return ("READ_DVD_STRUCTURE"); - case 0xb4: return ("PLAY_CD"); - case 0xbb: return ("SET_SPEED"); - case 0xbd: return ("MECH_STATUS"); - case 0xbe: return ("READ_CD"); - case 0xff: return ("POLL_DSC"); - default: { - static char buffer[20]; - ksprintf(buffer, "unknown CMD (0x%02x)", cmd); - return buffer; - } - } -} - -static char * -atapi_skey2str(u_int8_t skey) -{ - switch (skey) { - case 0x00: return ("NO SENSE"); - case 0x01: return ("RECOVERED ERROR"); - case 0x02: return ("NOT READY"); - case 0x03: return ("MEDIUM ERROR"); - case 0x04: return ("HARDWARE ERROR"); - case 0x05: return ("ILLEGAL REQUEST"); - case 0x06: return ("UNIT ATTENTION"); - case 0x07: return ("DATA PROTECT"); - case 0x08: return ("BLANK CHECK"); - case 0x09: return ("VENDOR SPECIFIC"); - case 0x0a: return ("COPY ABORTED"); - case 0x0b: return ("ABORTED COMMAND"); - case 0x0c: return ("EQUAL"); - case 0x0d: return ("VOLUME OVERFLOW"); - case 0x0e: return ("MISCOMPARE"); - case 0x0f: return ("RESERVED"); - default: return("UNKNOWN"); - } -} diff --git a/sys/dev/disk/ata/atapi-all.h b/sys/dev/disk/ata/atapi-all.h deleted file mode 100644 index 0cdcafb4a5..0000000000 --- a/sys/dev/disk/ata/atapi-all.h +++ /dev/null @@ -1,199 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-all.h,v 1.22.2.10 2002/10/31 23:10:33 thomas Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-all.h,v 1.6 2005/10/26 13:59:41 sephe Exp $ - */ - -/* ATAPI misc defines */ -#define ATAPI_MAGIC_LSB 0x14 -#define ATAPI_MAGIC_MSB 0xeb -#define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN) -#define ATAPI_P_WRITE (ATA_S_DRQ) -#define ATAPI_P_CMDOUT (ATA_S_DRQ | ATA_I_CMD) -#define ATAPI_P_DONEDRQ (ATA_S_DRQ | ATA_I_CMD | ATA_I_IN) -#define ATAPI_P_DONE (ATA_I_CMD | ATA_I_IN) -#define ATAPI_P_ABORT 0 - -/* error register bits */ -#define ATAPI_E_MASK 0x0f /* error mask */ -#define ATAPI_E_ILI 0x01 /* illegal length indication */ -#define ATAPI_E_EOM 0x02 /* end of media detected */ -#define ATAPI_E_ABRT 0x04 /* command aborted */ -#define ATAPI_E_MCR 0x08 /* media change requested */ -#define ATAPI_SK_MASK 0xf0 /* sense key mask */ -#define ATAPI_SK_NO_SENSE 0x00 /* no specific sense key info */ -#define ATAPI_SK_RECOVERED_ERROR 0x10 /* command OK, data recovered */ -#define ATAPI_SK_NOT_READY 0x20 /* no access to drive */ -#define ATAPI_SK_MEDIUM_ERROR 0x30 /* non-recovered data error */ -#define ATAPI_SK_HARDWARE_ERROR 0x40 /* non-recoverable HW failure */ -#define ATAPI_SK_ILLEGAL_REQUEST 0x50 /* invalid command param(s) */ -#define ATAPI_SK_UNIT_ATTENTION 0x60 /* media changed */ -#define ATAPI_SK_DATA_PROTECT 0x70 /* write protect */ -#define ATAPI_SK_BLANK_CHECK 0x80 /* blank check */ -#define ATAPI_SK_VENDOR_SPECIFIC 0x90 /* vendor specific skey */ -#define ATAPI_SK_COPY_ABORTED 0xa0 /* copy aborted */ -#define ATAPI_SK_ABORTED_COMMAND 0xb0 /* command aborted, try again */ -#define ATAPI_SK_EQUAL 0xc0 /* equal */ -#define ATAPI_SK_VOLUME_OVERFLOW 0xd0 /* volume overflow */ -#define ATAPI_SK_MISCOMPARE 0xe0 /* data dont match the medium */ -#define ATAPI_SK_RESERVED 0xf0 - -/* ATAPI commands */ -#define ATAPI_TEST_UNIT_READY 0x00 /* check if device is ready */ -#define ATAPI_REZERO 0x01 /* rewind */ -#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */ -#define ATAPI_FORMAT 0x04 /* format unit */ -#define ATAPI_READ 0x08 /* read data */ -#define ATAPI_WRITE 0x0a /* write data */ -#define ATAPI_WEOF 0x10 /* write filemark */ -#define WF_WRITE 0x01 -#define ATAPI_SPACE 0x11 /* space command */ -#define SP_FM 0x01 -#define SP_EOD 0x03 -#define ATAPI_MODE_SELECT 0x15 /* mode select */ -#define ATAPI_ERASE 0x19 /* erase */ -#define ATAPI_MODE_SENSE 0x1a /* mode sense */ -#define ATAPI_START_STOP 0x1b /* start/stop unit */ -#define SS_LOAD 0x01 -#define SS_RETENSION 0x02 -#define SS_EJECT 0x04 -#define ATAPI_PREVENT_ALLOW 0x1e /* media removal */ -#define ATAPI_READ_CAPACITY 0x25 /* get volume capacity */ -#define ATAPI_READ_BIG 0x28 /* read data */ -#define ATAPI_WRITE_BIG 0x2a /* write data */ -#define ATAPI_LOCATE 0x2b /* locate to position */ -#define ATAPI_READ_POSITION 0x34 /* read position */ -#define ATAPI_SYNCHRONIZE_CACHE 0x35 /* flush buf, close channel */ -#define ATAPI_WRITE_BUFFER 0x3b /* write device buffer */ -#define ATAPI_READ_BUFFER 0x3c /* read device buffer */ -#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */ -#define ATAPI_READ_TOC 0x43 /* get table of contents */ -#define ATAPI_PLAY_10 0x45 /* play by lba */ -#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */ -#define ATAPI_PLAY_TRACK 0x48 /* play by track number */ -#define ATAPI_PAUSE 0x4b /* pause audio operation */ -#define ATAPI_READ_DISK_INFO 0x51 /* get disk info structure */ -#define ATAPI_READ_TRACK_INFO 0x52 /* get track info structure */ -#define ATAPI_RESERVE_TRACK 0x53 /* reserve track */ -#define ATAPI_SEND_OPC_INFO 0x54 /* send OPC structurek */ -#define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */ -#define ATAPI_REPAIR_TRACK 0x58 /* repair track */ -#define ATAPI_READ_MASTER_CUE 0x59 /* read master CUE info */ -#define ATAPI_MODE_SENSE_BIG 0x5a /* get device parameters */ -#define ATAPI_CLOSE_TRACK 0x5b /* close track/session */ -#define ATAPI_READ_BUFFER_CAPACITY 0x5c /* get buffer capicity */ -#define ATAPI_SEND_CUE_SHEET 0x5d /* send CUE sheet */ -#define ATAPI_BLANK 0xa1 /* blank the media */ -#define ATAPI_SEND_KEY 0xa3 /* send DVD key structure */ -#define ATAPI_REPORT_KEY 0xa4 /* get DVD key structure */ -#define ATAPI_PLAY_12 0xa5 /* play by lba */ -#define ATAPI_LOAD_UNLOAD 0xa6 /* changer control command */ -#define ATAPI_READ_STRUCTURE 0xad /* get DVD structure */ -#define ATAPI_PLAY_CD 0xb4 /* universal play command */ -#define ATAPI_SET_SPEED 0xbb /* set drive speed */ -#define ATAPI_MECH_STATUS 0xbd /* get changer status */ -#define ATAPI_READ_CD 0xbe /* read data */ -#define ATAPI_POLL_DSC 0xff /* poll DSC status bit */ - -struct atapi_request; -struct ata_channel; - -/* ATAPI request sense structure */ -struct atapi_reqsense { - u_int8_t error_code :7; /* current or deferred errors */ - u_int8_t valid :1; /* follows ATAPI spec */ - u_int8_t segment; /* Segment number */ - u_int8_t sense_key :4; /* sense key */ - u_int8_t reserved2_4 :1; /* reserved */ - u_int8_t ili :1; /* incorrect length indicator */ - u_int8_t eom :1; /* end of medium */ - u_int8_t filemark :1; /* filemark */ - /* cmd information */ - u_int32_t cmd_info __attribute__((packed)); - u_int8_t sense_length; /* additional sense len (n-7) */ - /* additional cmd spec info */ - u_int32_t cmd_specific_info __attribute__((packed)); - u_int8_t asc; /* additional sense code */ - u_int8_t ascq; /* additional sense code qual */ - u_int8_t replaceable_unit_code; /* replaceable unit code */ - u_int8_t sk_specific :7; /* sense key specific */ - u_int8_t sksv :1; /* sense key specific info OK */ - u_int8_t sk_specific1; /* sense key specific */ - u_int8_t sk_specific2; /* sense key specific */ -}; - -typedef int atapi_callback_t(struct atapi_request *); - -struct atapi_request { - struct ata_device *device; /* ptr to parent softc */ - u_int8_t ccb[16]; /* command control block */ - int ccbsize; /* size of ccb (12 | 16) */ - u_int32_t bytecount; /* bytes to transfer */ - u_int32_t donecount; /* bytes transferred */ - int timeout; /* timeout for this cmd */ - struct callout callout; - int retries; /* retry count */ - int result; /* result of this cmd */ - int error; /* result translated to errno */ - struct atapi_reqsense sense; /* sense data if error */ - int flags; -#define ATPR_F_READ 0x0001 -#define ATPR_F_DMA_USED 0x0002 -#define ATPR_F_AT_HEAD 0x0004 -#define ATPR_F_INTERNAL 0x0008 -#define ATPR_F_QUIET 0x0010 - - caddr_t data; /* pointer to data buf */ - atapi_callback_t *callback; /* ptr to callback func */ - void *driver; /* driver specific */ - TAILQ_ENTRY(atapi_request) chain; /* list management */ -}; - -void atapi_attach(struct ata_device *, int); -void atapi_cam_attach_bus(struct ata_channel *); -void atapi_detach(struct ata_device *); -void atapi_cam_detach_bus(struct ata_channel *); -void atapi_cam_reinit_bus(struct ata_channel *); -void atapi_reinit(struct ata_device *); -void atapi_start(struct ata_device *); -int atapi_transfer(struct atapi_request *); -int atapi_interrupt(struct atapi_request *); -int atapi_queue_cmd(struct ata_device *, int8_t [], caddr_t, int, int, int, atapi_callback_t, void *); -int atapi_test_ready(struct ata_device *); -int atapi_wait_dsc(struct ata_device *, int); -void atapi_request_sense(struct ata_device *, struct atapi_reqsense *); -void atapi_dump(char *, void *, int); -int acdattach(struct ata_device *); -void acddetach(struct ata_device *); -void acd_start(struct ata_device *); -int afdattach(struct ata_device *); -void afddetach(struct ata_device *); -void afd_start(struct ata_device *); -int astattach(struct ata_device *); -void astdetach(struct ata_device *); -void ast_start(struct ata_device *); diff --git a/sys/dev/disk/ata/atapi-cam.c b/sys/dev/disk/ata/atapi-cam.c deleted file mode 100644 index 70c1bd8418..0000000000 --- a/sys/dev/disk/ata/atapi-cam.c +++ /dev/null @@ -1,735 +0,0 @@ -/*- - * Copyright (c) 2001,2002 Thomas Quinot - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-cam.c,v 1.10.2.3 2003/05/21 09:24:55 thomas Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-cam.c,v 1.15 2008/05/18 20:30:22 pavalos Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "ata-all.h" -#include "atapi-all.h" - -/* hardware command descriptor block */ -struct atapi_hcb { - struct atapi_xpt_softc *softc; - int unit; - int bus; - int target; - int lun; - union ccb *ccb; - u_int8_t cmd[CAM_MAX_CDBLEN]; - int flags; -#define DOING_AUTOSENSE 1 - - char *dxfer_alloc; - TAILQ_ENTRY(atapi_hcb) chain; -}; - -/* private data associated with an ATA bus */ -struct atapi_xpt_softc { - struct ata_channel *ata_ch; - struct cam_path *path; - struct cam_sim *sim; - int flags; -#define BUS_REGISTERED 0x01 -#define RESOURCE_SHORTAGE 0x02 - - TAILQ_HEAD(,atapi_hcb) pending_hcbs; - LIST_ENTRY(atapi_xpt_softc) chain; -}; - -enum reinit_reason { ATTACH, RESET }; - -static LIST_HEAD(,atapi_xpt_softc) all_buses = LIST_HEAD_INITIALIZER(all_buses); - -/* CAM XPT methods */ -static void atapi_action(struct cam_sim *, union ccb *); -static void atapi_poll(struct cam_sim *); -static void atapi_async(void *, u_int32_t, struct cam_path *, void *); -static void atapi_async1(void *, u_int32_t, struct cam_path *, void *); -static int atapi_cb(struct atapi_request *); - -/* internal functions */ -static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason); -static void setup_dev(struct atapi_xpt_softc *, struct ata_device *); -static void setup_async_cb(struct atapi_xpt_softc *, uint32_t); -static void cam_rescan_callback(struct cam_periph *, union ccb *); -static void cam_rescan(struct cam_sim *); -static void free_hcb_and_ccb_done(struct atapi_hcb *, u_int32_t); -static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *, int, int, union ccb *); -static void free_hcb(struct atapi_hcb *hcb); -static void free_softc(struct atapi_xpt_softc *scp); -static struct atapi_xpt_softc *get_softc(struct ata_channel *ata_ch); -static struct ata_device *get_ata_device(struct atapi_xpt_softc *scp, int id); - -static MALLOC_DEFINE(M_ATACAM, "ATA CAM transport", "ATA driver CAM-XPT layer"); - -void -atapi_cam_attach_bus(struct ata_channel *ata_ch) -{ - struct atapi_xpt_softc *scp = NULL; - struct cam_devq *devq = NULL; - struct cam_sim *sim = NULL; - struct cam_path *path = NULL; - int unit; - - LIST_FOREACH(scp, &all_buses, chain) { - if (scp->ata_ch == ata_ch) - return; - } - - scp = kmalloc(sizeof(struct atapi_xpt_softc), M_ATACAM, M_INTWAIT | M_ZERO); - scp->ata_ch = ata_ch; - TAILQ_INIT(&scp->pending_hcbs); - LIST_INSERT_HEAD(&all_buses, scp, chain); - unit = device_get_unit(ata_ch->dev); - - devq = cam_simq_alloc(16); - sim = cam_sim_alloc(atapi_action, atapi_poll, "ata", (void *)scp, - unit, &sim_mplock, 1, 1, devq); - cam_simq_release(devq); - if (sim == NULL) - goto error; - scp->sim = sim; - - if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { - goto error; - } - scp->flags |= BUS_REGISTERED; - - if (xpt_create_path(&path, /*periph*/ NULL, - cam_sim_path(sim), CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - goto error; - } - scp->path = path; - - CAM_DEBUG(path, CAM_DEBUG_TRACE, ("Registered SIM for ata%d\n", unit)); - - setup_async_cb(scp, AC_LOST_DEVICE); - reinit_bus(scp, ATTACH); - return; - -error: - free_softc(scp); -} - -void -atapi_cam_detach_bus(struct ata_channel *ata_ch) -{ - struct atapi_xpt_softc *scp = get_softc(ata_ch); - free_softc(scp); -} - -void -atapi_cam_reinit_bus(struct ata_channel *ata_ch) { - struct atapi_xpt_softc *scp = get_softc(ata_ch); - - /* - * scp might be null if the bus is being reinitialised during - * the boot-up sequence, before the ATAPI bus is registered. - */ - - if (scp != NULL) - reinit_bus(scp, RESET); -} - -static void -reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) { - if (scp->ata_ch->devices & ATA_ATAPI_MASTER) - setup_dev(scp, &scp->ata_ch->device[MASTER]); - if (scp->ata_ch->devices & ATA_ATAPI_SLAVE) - setup_dev(scp, &scp->ata_ch->device[SLAVE]); - - switch (reason) { - case RESET: - xpt_async(AC_BUS_RESET, scp->path, NULL); - /*FALLTHROUGH*/ - case ATTACH: - cam_rescan(scp->sim); - break; - } -} - -static void -setup_dev(struct atapi_xpt_softc *scp, struct ata_device *atp) -{ - if (atp->driver == NULL) { - ata_set_name(atp, "atapicam", - 2 * device_get_unit(atp->channel->dev) + - (atp->unit == ATA_MASTER) ? 0 : 1); - atp->driver = (void *)scp; - } -} - -static void -setup_async_cb(struct atapi_xpt_softc *scp, uint32_t events) -{ - struct ccb_setasync csa; - - xpt_setup_ccb(&csa.ccb_h, scp->path, /*priority*/ 5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = events; - csa.callback = &atapi_async; - csa.callback_arg = scp->sim; - xpt_action((union ccb *) &csa); -} - -static void -atapi_action(struct cam_sim *sim, union ccb *ccb) -{ - struct atapi_xpt_softc *softc = (struct atapi_xpt_softc*)cam_sim_softc(sim); - struct ccb_hdr *ccb_h = &ccb->ccb_h; - struct atapi_hcb *hcb = NULL; - int unit = cam_sim_unit(sim); - int bus = cam_sim_bus(sim); - int len; - char *buf; - - switch (ccb_h->func_code) { - case XPT_PATH_INQ: { - struct ccb_pathinq *cpi = &ccb->cpi; - - cpi->version_num = 1; - cpi->hba_inquiry = 0; - cpi->target_sprt = 0; -#if !defined(NO_ATANG) - cpi->hba_misc = PIM_NO_6_BYTE; -#else - cpi->hba_misc = 0; -#endif - cpi->hba_eng_cnt = 0; - bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags)); - cpi->max_target = 1; - cpi->max_lun = 0; - cpi->async_flags = 0; - cpi->hpath_id = 0; - cpi->initiator_id = 7; - strncpy(cpi->sim_vid, "FreeBSD", sizeof(cpi->sim_vid)); - strncpy(cpi->hba_vid, "ATAPI", sizeof(cpi->hba_vid)); - strncpy(cpi->dev_name, cam_sim_name(sim), sizeof cpi->dev_name); - cpi->unit_number = cam_sim_unit(sim); - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; - cpi->transport = XPORT_ATA; - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - if (softc->ata_ch && ccb_h->target_id != CAM_TARGET_WILDCARD) { - switch (softc->ata_ch->device[ccb_h->target_id].mode) { - case ATA_PIO1: - cpi->base_transfer_speed = 5200; - break; - case ATA_PIO2: - cpi->base_transfer_speed = 7000; - break; - case ATA_PIO3: - cpi->base_transfer_speed = 11000; - break; - case ATA_PIO4: - case ATA_DMA: - case ATA_WDMA2: - cpi->base_transfer_speed = 16000; - break; - case ATA_UDMA2: - cpi->base_transfer_speed = 33000; - break; - case ATA_UDMA4: - cpi->base_transfer_speed = 66000; - break; - case ATA_UDMA5: - cpi->base_transfer_speed = 100000; - break; - case ATA_UDMA6: - cpi->base_transfer_speed = 133000; - break; - default: - break; - } - } - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - return; - } - - case XPT_RESET_DEV: { - int tid = ccb_h->target_id; - struct ata_device *dev = get_ata_device(softc, tid); - - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("dev reset\n")); - atapi_reinit(dev); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - return; - } - - case XPT_RESET_BUS: - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("bus reset\n")); - ata_reinit(softc->ata_ch); - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - return; - - case XPT_SET_TRAN_SETTINGS: - /* ignore these, we're not doing SCSI here */ - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, - ("SET_TRAN_SETTINGS not supported\n")); - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(ccb); - return; - - case XPT_GET_TRAN_SETTINGS: { - struct ccb_trans_settings *cts = &ccb->cts; - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_ATA; - cts->transport_version = XPORT_VERSION_UNSPECIFIED; - cts->proto_specific.valid = 0; - cts->xport_specific.valid = 0; - /* nothing more to do */ - ccb->ccb_h.status = CAM_REQ_CMP; - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("GET_TRAN_SETTINGS\n")); - xpt_done(ccb); - return; - } - - case XPT_CALC_GEOMETRY: { - struct ccb_calc_geometry *ccg; - unsigned int size_mb; - unsigned int secs_per_cylinder; - int extended; - - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("CALC_GEOMETRY\n")); - ccg = &ccb->ccg; - size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); - extended = 1; - - if (size_mb > 1024 && extended) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else { - ccg->heads = 64; - ccg->secs_per_track = 32; - } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - return; - } - - case XPT_SCSI_IO: { - struct ccb_scsiio *csio = &ccb->csio; - int tid = ccb_h->target_id, lid = ccb_h->target_lun; - struct ata_device *dev = get_ata_device(softc, tid); - - CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, ("XPT_SCSI_IO\n")); - - /* check that this request was not aborted already */ - if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { - kprintf("XPT_SCSI_IO received but already in progress?\n"); - xpt_done(ccb); - return; - } - if (dev == NULL) { - CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, - ("SCSI IO received for invalid device\n")); - ccb_h->status = CAM_TID_INVALID; - xpt_done(ccb); - return; - } - if (lid > 0) { - CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, - ("SCSI IO received for invalid lun %d\n", lid)); - ccb_h->status = CAM_LUN_INVALID; - xpt_done(ccb); - return; - } - if ((ccb_h->flags & CAM_SCATTER_VALID)) { - /* scatter-gather not supported */ - xpt_print_path(ccb_h->path); - kprintf("ATAPI-CAM does not support scatter-gather yet!\n"); - break; - } - if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) - goto action_oom; - - ccb_h->status |= CAM_SIM_QUEUED; - - bcopy((ccb_h->flags & CAM_CDB_POINTER) ? - csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes, - hcb->cmd, csio->cdb_len); -#ifdef CAMDEBUG - if (CAM_DEBUGGED(ccb_h->path, CAM_DEBUG_CDB)) { - char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; - - kprintf("atapi_action: hcb@%p: %s\n", hcb, - scsi_cdb_string(hcb->cmd, cdb_str, sizeof(cdb_str))); - } -#endif - - len = csio->dxfer_len; - buf = csio->data_ptr; - - /* some SCSI commands require special processing */ - switch (hcb->cmd[0]) { - case INQUIRY: { - /* - * many ATAPI devices seem to report more than - * SHORT_INQUIRY_LENGTH bytes of available INQUIRY - * information, but respond with some incorrect condition - * when actually asked for it, so we are going to pretend - * that only SHORT_INQUIRY_LENGTH are expected, anyway. - */ - struct scsi_inquiry *inq = (struct scsi_inquiry *) &hcb->cmd[0]; - - if (inq->byte2 == 0 && inq->page_code == 0 && - inq->length > SHORT_INQUIRY_LENGTH) { - bzero(buf, len); - len = inq->length = SHORT_INQUIRY_LENGTH; - } - break; - } -#if defined(NO_ATANG) /* EXITED IN ORIGINAL, DELETED IN ATANG */ - case MODE_SELECT_6: - /* FALLTHROUGH */ - - case MODE_SENSE_6: - /* - * not supported by ATAPI/MMC devices (per SCSI MMC spec) - * translate to _10 equivalent. - * (actually we should do this only if we have tried - * MODE_foo_6 and received ILLEGAL_REQUEST or - * INVALID COMMAND OPERATION CODE) - * alternative fix: behave like a honest CAM transport, - * do not muck with CDB contents, and change scsi_cd to - * always use MODE_SENSE_10 in cdgetmode(), or let scsi_cd - * know that this specific unit is an ATAPI/MMC one, - * and in /that case/ use MODE_SENSE_10 - */ - - CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, - ("Translating %s into _10 equivalent\n", - (hcb->cmd[0] == MODE_SELECT_6) ? - "MODE_SELECT_6" : "MODE_SENSE_6")); - hcb->cmd[0] |= 0x40; - hcb->cmd[6] = 0; - hcb->cmd[7] = 0; - hcb->cmd[8] = hcb->cmd[4]; - hcb->cmd[9] = hcb->cmd[5]; - hcb->cmd[4] = 0; - hcb->cmd[5] = 0; - break; -#endif - - case READ_6: - /* FALLTHROUGH */ - - case WRITE_6: - CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, - ("Translating %s into _10 equivalent\n", - (hcb->cmd[0] == READ_6) ? "READ_6" : "WRITE_6")); - hcb->cmd[0] |= 0x20; - hcb->cmd[9] = hcb->cmd[5]; - hcb->cmd[8] = hcb->cmd[4]; - hcb->cmd[7] = 0; - hcb->cmd[6] = 0; - hcb->cmd[5] = hcb->cmd[3]; - hcb->cmd[4] = hcb->cmd[2]; - hcb->cmd[3] = hcb->cmd[1] & 0x1f; - hcb->cmd[2] = 0; - hcb->cmd[1] = 0; - break; - } - - if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN && (len & 1)) { - /* ATA always transfers an even number of bytes */ - ++len; - buf = hcb->dxfer_alloc = kmalloc(len, M_ATACAM, M_INTWAIT | M_ZERO); - } - crit_enter(); - TAILQ_INSERT_TAIL(&softc->pending_hcbs, hcb, chain); - crit_exit(); - if (atapi_queue_cmd(dev, hcb->cmd, buf, len, - (((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN) ? - ATPR_F_READ : 0) | ATPR_F_QUIET, - ccb_h->timeout, atapi_cb, (void *)hcb) == 0) - return; - break; - } - - default: - CAM_DEBUG(ccb_h->path, CAM_DEBUG_SUBTRACE, - ("unsupported function code 0x%02x\n", ccb_h->func_code)); - ccb_h->status = CAM_REQ_INVALID; - xpt_done(ccb); - return; - } - -action_oom: - if (hcb != NULL) - free_hcb(hcb); - xpt_print_path(ccb_h->path); - kprintf("out of memory, freezing queue.\n"); - softc->flags |= RESOURCE_SHORTAGE; - xpt_freeze_simq(sim, /*count*/ 1); - ccb_h->status = CAM_REQUEUE_REQ; - xpt_done(ccb); -} - -static void -atapi_poll(struct cam_sim *sim) -{ - /* do nothing - we do not actually service any interrupts */ - kprintf("atapi_poll called!\n"); -} - -static int -atapi_cb(struct atapi_request *req) -{ - struct atapi_hcb *hcb = (struct atapi_hcb *) req->driver; - struct ccb_scsiio *csio = &hcb->ccb->csio; - int hcb_status = req->result; - - crit_enter(); -#ifdef CAMDEBUG - if (CAM_DEBUGGED(csio->ccb_h.path, CAM_DEBUG_CDB)) { - kprintf("atapi_cb: hcb@%p status = %02x: (sk = %02x%s%s%s)\n", - hcb, hcb_status, hcb_status >> 4, - (hcb_status & 4) ? " ABRT" : "", - (hcb_status & 2) ? " EOM" : "", - (hcb_status & 1) ? " ILI" : ""); - kprintf(" %s: cmd %02x - sk=%02x asc=%02x ascq=%02x\n", - req->device->name, req->ccb[0], req->sense.sense_key, - req->sense.asc, req->sense.ascq); - } -#endif - if (hcb_status != 0) { - csio->scsi_status = SCSI_STATUS_CHECK_COND; - if ((csio->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) { - csio->ccb_h.status |= CAM_AUTOSNS_VALID; - bcopy((void *)&req->sense, (void *)&csio->sense_data, - sizeof(struct atapi_reqsense)); - } - free_hcb_and_ccb_done(hcb, CAM_SCSI_STATUS_ERROR); - } - else { - if (((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) && - hcb->dxfer_alloc != NULL) - bcopy(hcb->dxfer_alloc, csio->data_ptr, csio->dxfer_len); - csio->scsi_status = SCSI_STATUS_OK; - free_hcb_and_ccb_done(hcb, CAM_REQ_CMP); - } - crit_exit(); - return 0; -} - -static void -free_hcb_and_ccb_done(struct atapi_hcb *hcb, u_int32_t status) -{ - struct atapi_xpt_softc *softc = hcb->softc; - union ccb *ccb = hcb->ccb; - - if (hcb != NULL) { - /* we're about to free a hcb, so the shortage has ended */ - if (softc->flags & RESOURCE_SHORTAGE) { - softc->flags &= ~RESOURCE_SHORTAGE; - status |= CAM_RELEASE_SIMQ; - } - free_hcb(hcb); - } - ccb->ccb_h.status = - status | (ccb->ccb_h.status & ~(CAM_STATUS_MASK | CAM_SIM_QUEUED)); - xpt_done(ccb); -} - -static void -atapi_async(void *callback_arg, u_int32_t code, - struct cam_path *path, void *arg) -{ - crit_enter(); - atapi_async1(callback_arg, code, path, arg); - crit_exit(); -} - -static void -atapi_async1(void *callback_arg, u_int32_t code, - struct cam_path* path, void *arg) -{ - struct atapi_xpt_softc *softc; - struct cam_sim *sim; - int targ; - - sim = (struct cam_sim *) callback_arg; - softc = (struct atapi_xpt_softc *) cam_sim_softc(sim); - switch (code) { - case AC_LOST_DEVICE: - targ = xpt_path_target_id(path); - xpt_print_path(path); - if (targ == -1) - kprintf("Lost host adapter\n"); - else - kprintf("Lost target %d???\n", targ); - break; - - default: - break; - } -} - -static void -cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) -{ - if (ccb->ccb_h.status != CAM_REQ_CMP) { - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, - ("Rescan failed, 0x%04x\n", ccb->ccb_h.status)); - } else { - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, - ("Rescan succeeded\n")); - } - xpt_free_path(ccb->ccb_h.path); - kfree(ccb, M_ATACAM); -} - -static void -cam_rescan(struct cam_sim *sim) -{ - struct cam_path *path; - union ccb *ccb = kmalloc(sizeof(union ccb), M_ATACAM, M_INTWAIT | M_ZERO); - - if (xpt_create_path(&path, xpt_periph, cam_sim_path(sim), - CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) - return; - - CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("Rescanning ATAPI bus.\n")); - xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); - ccb->ccb_h.func_code = XPT_SCAN_BUS; - ccb->ccb_h.cbfcnp = cam_rescan_callback; - ccb->crcn.flags = CAM_FLAG_NONE; - xpt_action(ccb); - /* scan is in progress now */ -} - -static struct atapi_hcb * -allocate_hcb(struct atapi_xpt_softc *softc, int unit, int bus, union ccb *ccb) -{ - struct atapi_hcb *hcb; - - hcb = kmalloc(sizeof(struct atapi_hcb), M_ATACAM, M_INTWAIT | M_ZERO); - - if (hcb != NULL) { - hcb->softc = softc; - hcb->unit = unit; - hcb->bus = bus; - hcb->ccb = ccb; - } - return hcb; -} - -static void -free_hcb(struct atapi_hcb *hcb) -{ - TAILQ_REMOVE(&hcb->softc->pending_hcbs, hcb, chain); - if (hcb->dxfer_alloc != NULL) - kfree(hcb->dxfer_alloc, M_ATACAM); - kfree(hcb, M_ATACAM); -} - -static void -free_softc(struct atapi_xpt_softc *scp) -{ - struct atapi_hcb *hcb; - - if (scp != NULL) { - TAILQ_FOREACH(hcb, &scp->pending_hcbs, chain) { - free_hcb_and_ccb_done(hcb, CAM_UNREC_HBA_ERROR); - } - if (scp->path != NULL) { - setup_async_cb(scp, 0); - xpt_free_path(scp->path); - } - if ((scp->flags & BUS_REGISTERED) != 0) { - if (xpt_bus_deregister(cam_sim_path(scp->sim)) == CAM_REQ_CMP) - scp->flags &= ~BUS_REGISTERED; - } - if (scp->sim != NULL) { - if ((scp->flags & BUS_REGISTERED) == 0) - cam_sim_free(scp->sim); - else - kprintf("Can't free %s SIM (still registered)\n", - cam_sim_name(scp->sim)); - } - LIST_REMOVE(scp, chain); - kfree(scp, M_ATACAM); - } -} - -static struct atapi_xpt_softc * -get_softc(struct ata_channel *ata_ch) { - struct atapi_xpt_softc *scp; - LIST_FOREACH(scp, &all_buses, chain) { - if (scp->ata_ch == ata_ch) - return scp; - } - return NULL; -} - -static struct ata_device * -get_ata_device(struct atapi_xpt_softc *scp, int id) -{ - int role = ATA_ATAPI_MASTER; - - switch (id) { - case 1: - role = ATA_ATAPI_SLAVE; - /* FALLTHROUGH */ - - case 0: - if (scp->ata_ch->devices & role) - return &scp->ata_ch->device[id]; - /* FALLTHROUGH */ - - default: - return NULL; - } -} diff --git a/sys/dev/disk/ata/atapi-cd.c b/sys/dev/disk/ata/atapi-cd.c deleted file mode 100644 index bad9ba24e7..0000000000 --- a/sys/dev/disk/ata/atapi-cd.c +++ /dev/null @@ -1,1998 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-cd.c,v 1.48.2.20 2002/11/25 05:30:31 njl Exp $ - */ - -#include "opt_ata.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ata-all.h" -#include "atapi-all.h" -#include "atapi-cd.h" - -/* device structures */ -static d_open_t acdopen; -static d_close_t acdclose; -static d_ioctl_t acdioctl; -static d_strategy_t acdstrategy; - -static struct dev_ops acd_ops = { - { "acd", 117, D_DISK | D_TRACKCLOSE }, - .d_open = acdopen, - .d_close = acdclose, - .d_read = physread, - .d_write = physwrite, - .d_ioctl = acdioctl, - .d_strategy = acdstrategy, -}; - -/* prototypes */ -static struct acd_softc *acd_init_lun(struct ata_device *); -static void acd_make_dev(struct acd_softc *); -static void acd_set_ioparm(struct acd_softc *); -static void acd_describe(struct acd_softc *); -static void lba2msf(u_int32_t, u_int8_t *, u_int8_t *, u_int8_t *); -static u_int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t); -static int acd_done(struct atapi_request *); -static void acd_read_toc(struct acd_softc *); -static int acd_play(struct acd_softc *, int, int); -static int acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t); -static void acd_select_slot(struct acd_softc *); -static int acd_init_writer(struct acd_softc *, int); -static int acd_fixate(struct acd_softc *, int); -static int acd_init_track(struct acd_softc *, struct cdr_track *); -static int acd_flush(struct acd_softc *); -static int acd_read_track_info(struct acd_softc *, int32_t, struct acd_track_info *); -static int acd_get_progress(struct acd_softc *, int *); -static int acd_send_cue(struct acd_softc *, struct cdr_cuesheet *); -static int acd_report_key(struct acd_softc *, struct dvd_authinfo *); -static int acd_send_key(struct acd_softc *, struct dvd_authinfo *); -static int acd_read_structure(struct acd_softc *, struct dvd_struct *); -static int acd_eject(struct acd_softc *, int); -static int acd_blank(struct acd_softc *, int); -static int acd_prevent_allow(struct acd_softc *, int); -static int acd_start_stop(struct acd_softc *, int); -static int acd_pause_resume(struct acd_softc *, int); -static int acd_mode_sense(struct acd_softc *, int, caddr_t, int); -static int acd_mode_select(struct acd_softc *, caddr_t, int); -static int acd_set_speed(struct acd_softc *, int, int); -static void acd_get_cap(struct acd_softc *); - -/* internal vars */ -static u_int32_t acd_lun_map = 0; -static MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers"); - -int -acdattach(struct ata_device *atadev) -{ - struct acd_softc *cdp; - struct changer *chp; - - if ((cdp = acd_init_lun(atadev)) == NULL) { - ata_prtdev(atadev, "acd: out of memory\n"); - return 0; - } - - ata_set_name(atadev, "acd", cdp->lun); - ata_command(atadev, ATA_C_ATAPI_RESET, 0, 0, 0, ATA_IMMEDIATE); - acd_get_cap(cdp); - - /* if this is a changer device, allocate the neeeded lun's */ - if (cdp->cap.mech == MST_MECH_CHANGER) { - int8_t ccb[16] = { ATAPI_MECH_STATUS, 0, 0, 0, 0, 0, 0, 0, - sizeof(struct changer)>>8, sizeof(struct changer), - 0, 0, 0, 0, 0, 0 }; - - chp = kmalloc(sizeof(struct changer), M_ACD, M_WAITOK | M_ZERO); - if (!atapi_queue_cmd(cdp->device, ccb, (caddr_t)chp, - sizeof(struct changer), - ATPR_F_READ, 60, NULL, NULL)) { - struct acd_softc *tmpcdp = cdp; - struct acd_softc **cdparr; - char *name; - int count; - - chp->table_length = htons(chp->table_length); - cdparr = kmalloc(sizeof(struct acd_softc) * chp->slots, - M_ACD, M_WAITOK); - for (count = 0; count < chp->slots; count++) { - if (count > 0) { - tmpcdp = acd_init_lun(atadev); - if (!tmpcdp) { - ata_prtdev(atadev, "out of memory\n"); - break; - } - } - cdparr[count] = tmpcdp; - tmpcdp->driver = cdparr; - tmpcdp->slot = count; - tmpcdp->changer_info = chp; - acd_make_dev(tmpcdp); - devstat_add_entry(tmpcdp->stats, "acd", tmpcdp->lun, DEV_BSIZE, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, - DEVSTAT_PRIORITY_CD); - } - name = kmalloc(strlen(atadev->name) + 2, M_ACD, M_WAITOK); - strcpy(name, atadev->name); - strcat(name, "-"); - ata_free_name(atadev); - ata_set_name(atadev, name, cdp->lun + cdp->changer_info->slots - 1); - kfree(name, M_ACD); - } - } - else { - acd_make_dev(cdp); - devstat_add_entry(cdp->stats, "acd", cdp->lun, DEV_BSIZE, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, - DEVSTAT_PRIORITY_CD); - } - acd_describe(cdp); - atadev->driver = cdp; - return 1; -} - -void -acddetach(struct ata_device *atadev) -{ - struct acd_softc *cdp = atadev->driver; - struct acd_devlist *entry; - struct bio *bio; - int subdev; - - if (cdp->changer_info) { - for (subdev = 0; subdev < cdp->changer_info->slots; subdev++) { - if (cdp->driver[subdev] == cdp) - continue; - while ((bio = bioq_first(&cdp->driver[subdev]->bio_queue))) { - bioq_remove(&cdp->driver[subdev]->bio_queue, bio); - bio->bio_buf->b_flags |= B_ERROR; - bio->bio_buf->b_error = ENXIO; - biodone(bio); - } - release_dev(cdp->driver[subdev]->dev); - while ((entry = TAILQ_FIRST(&cdp->driver[subdev]->dev_list))) { - release_dev(entry->dev); - TAILQ_REMOVE(&cdp->driver[subdev]->dev_list, entry, chain); - kfree(entry, M_ACD); - } - devstat_remove_entry(cdp->driver[subdev]->stats); - kfree(cdp->driver[subdev]->stats, M_ACD); - ata_free_lun(&acd_lun_map, cdp->driver[subdev]->lun); - kfree(cdp->driver[subdev], M_ACD); - } - kfree(cdp->driver, M_ACD); - kfree(cdp->changer_info, M_ACD); - } - while ((bio = bioq_first(&cdp->bio_queue))) { - bio->bio_buf->b_flags |= B_ERROR; - bio->bio_buf->b_error = ENXIO; - biodone(bio); - } - while ((entry = TAILQ_FIRST(&cdp->dev_list))) { - release_dev(entry->dev); - TAILQ_REMOVE(&cdp->dev_list, entry, chain); - kfree(entry, M_ACD); - } - disk_invalidate(&cdp->disk); - disk_destroy(&cdp->disk); - devstat_remove_entry(cdp->stats); - kfree(cdp->stats, M_ACD); - ata_free_name(atadev); - ata_free_lun(&acd_lun_map, cdp->lun); - kfree(cdp, M_ACD); - atadev->driver = NULL; -} - -static struct acd_softc * -acd_init_lun(struct ata_device *atadev) -{ - struct acd_softc *cdp; - - cdp = kmalloc(sizeof(struct acd_softc), M_ACD, M_WAITOK | M_ZERO); - TAILQ_INIT(&cdp->dev_list); - bioq_init(&cdp->bio_queue); - cdp->device = atadev; - cdp->lun = ata_get_lun(&acd_lun_map); - cdp->block_size = 2048; - cdp->slot = -1; - cdp->changer_info = NULL; - cdp->stats = kmalloc(sizeof(struct devstat), M_ACD, M_WAITOK | M_ZERO); - return cdp; -} - -static void -acd_make_dev(struct acd_softc *cdp) -{ - cdev_t dev; - - dev = disk_create(cdp->lun, &cdp->disk, &acd_ops); - dev->si_drv1 = cdp; - cdp->dev = dev; - cdp->device->flags |= ATA_D_MEDIA_CHANGED; - acd_set_ioparm(cdp); -} - -static void -acd_set_ioparm(struct acd_softc *cdp) -{ - struct disk_info info; - - cdp->dev->si_iosize_max = - ((256*DEV_BSIZE)/cdp->block_size)*cdp->block_size; - cdp->dev->si_bsize_phys = cdp->block_size; - bzero(&info, sizeof(info)); - info.d_media_blksize = cdp->block_size; - info.d_media_blocks = cdp->disk_size; - info.d_secpertrack = 100; - info.d_nheads = 1; - info.d_ncylinders = cdp->disk_size / info.d_secpertrack / info.d_nheads + 1; - info.d_secpercyl = info.d_secpertrack * info.d_nheads; - info.d_dsflags = DSO_ONESLICE | DSO_COMPATLABEL | DSO_COMPATPARTA | - DSO_RAWEXTENSIONS; - disk_setdiskinfo(&cdp->disk, &info); -} - -static void -acd_describe(struct acd_softc *cdp) -{ - int comma = 0; - char *mechanism; - - if (bootverbose) { - ata_prtdev(cdp->device, "<%.40s/%.8s> %s drive at ata%d as %s\n", - cdp->device->param->model, cdp->device->param->revision, - (cdp->cap.write_dvdr) ? "DVD-R" : - (cdp->cap.write_dvdram) ? "DVD-RAM" : - (cdp->cap.write_cdrw) ? "CD-RW" : - (cdp->cap.write_cdr) ? "CD-R" : - (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM", - device_get_unit(cdp->device->channel->dev), - (cdp->device->unit == ATA_MASTER) ? "master" : "slave"); - - ata_prtdev(cdp->device, "%s", ""); - if (cdp->cap.cur_read_speed) { - kprintf("read %dKB/s", cdp->cap.cur_read_speed * 1000 / 1024); - if (cdp->cap.max_read_speed) - kprintf(" (%dKB/s)", cdp->cap.max_read_speed * 1000 / 1024); - if ((cdp->cap.cur_write_speed) && - (cdp->cap.write_cdr || cdp->cap.write_cdrw || - cdp->cap.write_dvdr || cdp->cap.write_dvdram)) { - kprintf(" write %dKB/s", cdp->cap.cur_write_speed * 1000 / 1024); - if (cdp->cap.max_write_speed) - kprintf(" (%dKB/s)", cdp->cap.max_write_speed * 1000 / 1024); - } - comma = 1; - } - if (cdp->cap.buf_size) { - kprintf("%s %dKB buffer", comma ? "," : "", cdp->cap.buf_size); - comma = 1; - } - kprintf("%s %s\n", comma ? "," : "", ata_mode2str(cdp->device->mode)); - - ata_prtdev(cdp->device, "Reads:"); - comma = 0; - if (cdp->cap.read_cdr) { - kprintf(" CD-R"); comma = 1; - } - if (cdp->cap.read_cdrw) { - kprintf("%s CD-RW", comma ? "," : ""); comma = 1; - } - if (cdp->cap.cd_da) { - if (cdp->cap.cd_da_stream) - kprintf("%s CD-DA stream", comma ? "," : ""); - else - kprintf("%s CD-DA", comma ? "," : ""); - comma = 1; - } - if (cdp->cap.read_dvdrom) { - kprintf("%s DVD-ROM", comma ? "," : ""); comma = 1; - } - if (cdp->cap.read_dvdr) { - kprintf("%s DVD-R", comma ? "," : ""); comma = 1; - } - if (cdp->cap.read_dvdram) { - kprintf("%s DVD-RAM", comma ? "," : ""); comma = 1; - } - if (cdp->cap.read_packet) - kprintf("%s packet", comma ? "," : ""); - - kprintf("\n"); - ata_prtdev(cdp->device, "Writes:"); - if (cdp->cap.write_cdr || cdp->cap.write_cdrw || - cdp->cap.write_dvdr || cdp->cap.write_dvdram) { - comma = 0; - if (cdp->cap.write_cdr) { - kprintf(" CD-R" ); comma = 1; - } - if (cdp->cap.write_cdrw) { - kprintf("%s CD-RW", comma ? "," : ""); comma = 1; - } - if (cdp->cap.write_dvdr) { - kprintf("%s DVD-R", comma ? "," : ""); comma = 1; - } - if (cdp->cap.write_dvdram) { - kprintf("%s DVD-RAM", comma ? "," : ""); comma = 1; - } - if (cdp->cap.test_write) { - kprintf("%s test write", comma ? "," : ""); comma = 1; - } - if (cdp->cap.burnproof) - kprintf("%s burnproof", comma ? "," : ""); - } - kprintf("\n"); - if (cdp->cap.audio_play) { - ata_prtdev(cdp->device, "Audio: "); - if (cdp->cap.audio_play) - kprintf("play"); - if (cdp->cap.max_vol_levels) - kprintf(", %d volume levels", cdp->cap.max_vol_levels); - kprintf("\n"); - } - ata_prtdev(cdp->device, "Mechanism: "); - switch (cdp->cap.mech) { - case MST_MECH_CADDY: - mechanism = "caddy"; break; - case MST_MECH_TRAY: - mechanism = "tray"; break; - case MST_MECH_POPUP: - mechanism = "popup"; break; - case MST_MECH_CHANGER: - mechanism = "changer"; break; - case MST_MECH_CARTRIDGE: - mechanism = "cartridge"; break; - default: - mechanism = NULL; break; - } - if (mechanism) - kprintf("%s%s", cdp->cap.eject ? "ejectable " : "", mechanism); - else if (cdp->cap.eject) - kprintf("ejectable"); - - if (cdp->cap.lock) - kprintf(cdp->cap.locked ? ", locked" : ", unlocked"); - if (cdp->cap.prevent) - kprintf(", lock protected"); - kprintf("\n"); - - if (cdp->cap.mech != MST_MECH_CHANGER) { - ata_prtdev(cdp->device, "Medium: "); - switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) { - case MST_CDROM: - kprintf("CD-ROM "); break; - case MST_CDR: - kprintf("CD-R "); break; - case MST_CDRW: - kprintf("CD-RW "); break; - case MST_DOOR_OPEN: - kprintf("door open"); break; - case MST_NO_DISC: - kprintf("no/blank disc"); break; - case MST_FMT_ERROR: - kprintf("medium format error"); break; - } - if ((cdp->cap.medium_type & MST_TYPE_MASK_HIGH)cap.medium_type & MST_TYPE_MASK_LOW) { - case MST_DATA_120: - kprintf("120mm data disc"); break; - case MST_AUDIO_120: - kprintf("120mm audio disc"); break; - case MST_COMB_120: - kprintf("120mm data/audio disc"); break; - case MST_PHOTO_120: - kprintf("120mm photo disc"); break; - case MST_DATA_80: - kprintf("80mm data disc"); break; - case MST_AUDIO_80: - kprintf("80mm audio disc"); break; - case MST_COMB_80: - kprintf("80mm data/audio disc"); break; - case MST_PHOTO_80: - kprintf("80mm photo disc"); break; - case MST_FMT_NONE: - switch (cdp->cap.medium_type & MST_TYPE_MASK_HIGH) { - case MST_CDROM: - kprintf("unknown"); break; - case MST_CDR: - case MST_CDRW: - kprintf("blank"); break; - } - break; - default: - kprintf("unknown (0x%x)", cdp->cap.medium_type); break; - } - } - kprintf("\n"); - } - } - else { - ata_prtdev(cdp->device, "%s ", - (cdp->cap.write_dvdr) ? "DVD-R" : - (cdp->cap.write_dvdram) ? "DVD-RAM" : - (cdp->cap.write_cdrw) ? "CD-RW" : - (cdp->cap.write_cdr) ? "CD-R" : - (cdp->cap.read_dvdrom) ? "DVD-ROM" : "CDROM"); - - if (cdp->changer_info) - kprintf("with %d CD changer ", cdp->changer_info->slots); - - kprintf("<%.40s> at ata%d-%s %s\n", cdp->device->param->model, - device_get_unit(cdp->device->channel->dev), - (cdp->device->unit == ATA_MASTER) ? "master" : "slave", - ata_mode2str(cdp->device->mode) ); - } -} - -static __inline void -lba2msf(u_int32_t lba, u_int8_t *m, u_int8_t *s, u_int8_t *f) -{ - lba += 150; - lba &= 0xffffff; - *m = lba / (60 * 75); - lba %= (60 * 75); - *s = lba / 75; - *f = lba % 75; -} - -static __inline u_int32_t -msf2lba(u_int8_t m, u_int8_t s, u_int8_t f) -{ - return (m * 60 + s) * 75 + f - 150; -} - -static int -acdopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct acd_softc *cdp = dev->si_drv1; - int timeout = 60; - - if (!cdp) - return ENXIO; - - if (ap->a_oflags & FWRITE) { - if (count_dev(dev) > 1) - return EBUSY; - } - - /* wait if drive is not finished loading the medium */ - while (timeout--) { - struct atapi_reqsense *sense = cdp->device->result; - - if (!atapi_test_ready(cdp->device)) - break; - if (sense->sense_key == 2 && sense->asc == 4 && sense->ascq == 1) - tsleep(&timeout, 0, "acdld", hz / 2); - else - break; - } - - if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) { - acd_select_slot(cdp); - tsleep(&cdp->changer_info, 0, "acdopn", 0); - } - acd_prevent_allow(cdp, 1); - cdp->flags |= F_LOCKED; - acd_read_toc(cdp); - return 0; -} - -static int -acdclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct acd_softc *cdp = dev->si_drv1; - - if (!cdp) - return ENXIO; - - if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) { - acd_select_slot(cdp); - tsleep(&cdp->changer_info, 0, "acdclo", 0); - } - acd_prevent_allow(cdp, 0); - cdp->flags &= ~F_LOCKED; - return 0; -} - -static int -acdioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct acd_softc *cdp = dev->si_drv1; - int error = 0; - - if (!cdp) - return ENXIO; - - if (cdp->changer_info && cdp->slot != cdp->changer_info->current_slot) { - acd_select_slot(cdp); - tsleep(&cdp->changer_info, 0, "acdctl", 0); - } - if (cdp->device->flags & ATA_D_MEDIA_CHANGED) - switch (ap->a_cmd) { - case CDIOCRESET: - atapi_test_ready(cdp->device); - break; - - default: - acd_read_toc(cdp); - acd_prevent_allow(cdp, 1); - cdp->flags |= F_LOCKED; - break; - } - switch (ap->a_cmd) { - - case CDIOCRESUME: - error = acd_pause_resume(cdp, 1); - break; - - case CDIOCPAUSE: - error = acd_pause_resume(cdp, 0); - break; - - case CDIOCSTART: - error = acd_start_stop(cdp, 1); - break; - - case CDIOCSTOP: - error = acd_start_stop(cdp, 0); - break; - - case CDIOCALLOW: - error = acd_prevent_allow(cdp, 0); - cdp->flags &= ~F_LOCKED; - break; - - case CDIOCPREVENT: - error = acd_prevent_allow(cdp, 1); - cdp->flags |= F_LOCKED; - break; - - case CDIOCRESET: -; /* note: if no proc EPERM will be returned */ - error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0); - if (error) - break; - error = atapi_test_ready(cdp->device); - break; - - case CDIOCEJECT: - if (count_dev(dev) > 1) { - error = EBUSY; - break; - } - error = acd_eject(cdp, 0); - break; - - case CDIOCCLOSE: - if (count_dev(dev) > 1) - break; - error = acd_eject(cdp, 1); - break; - - case CDIOREADTOCHEADER: - if (!cdp->toc.hdr.ending_track) { - error = EIO; - break; - } - bcopy(&cdp->toc.hdr, ap->a_data, sizeof(cdp->toc.hdr)); - break; - - case CDIOREADTOCENTRYS: - { - struct ioc_read_toc_entry *te = (struct ioc_read_toc_entry *)ap->a_data; - struct toc *toc = &cdp->toc; - int starting_track = te->starting_track; - int len; - - if (!toc->hdr.ending_track) { - error = EIO; - break; - } - - if (te->data_len < sizeof(toc->tab[0]) || - (te->data_len % sizeof(toc->tab[0])) != 0 || - (te->address_format != CD_MSF_FORMAT && - te->address_format != CD_LBA_FORMAT)) { - error = EINVAL; - break; - } - - if (!starting_track) - starting_track = toc->hdr.starting_track; - else if (starting_track == 170) - starting_track = toc->hdr.ending_track + 1; - else if (starting_track < toc->hdr.starting_track || - starting_track > toc->hdr.ending_track + 1) { - error = EINVAL; - break; - } - - len = ((toc->hdr.ending_track + 1 - starting_track) + 1) * - sizeof(toc->tab[0]); - if (te->data_len < len) - len = te->data_len; - if (len > sizeof(toc->tab)) { - error = EINVAL; - break; - } - - if (te->address_format == CD_MSF_FORMAT) { - struct cd_toc_entry *entry; - - toc = kmalloc(sizeof(struct toc), M_ACD, M_WAITOK | M_ZERO); - bcopy(&cdp->toc, toc, sizeof(struct toc)); - entry = toc->tab + (toc->hdr.ending_track + 1 - - toc->hdr.starting_track) + 1; - while (--entry >= toc->tab) - lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute, - &entry->addr.msf.second, &entry->addr.msf.frame); - } - error = copyout(toc->tab + starting_track - toc->hdr.starting_track, - te->data, len); - if (te->address_format == CD_MSF_FORMAT) - kfree(toc, M_ACD); - break; - } - case CDIOREADTOCENTRY: - { - struct ioc_read_toc_single_entry *te = - (struct ioc_read_toc_single_entry *)ap->a_data; - struct toc *toc = &cdp->toc; - u_char track = te->track; - - if (!toc->hdr.ending_track) { - error = EIO; - break; - } - - if (te->address_format != CD_MSF_FORMAT && - te->address_format != CD_LBA_FORMAT) { - error = EINVAL; - break; - } - - if (!track) - track = toc->hdr.starting_track; - else if (track == 170) - track = toc->hdr.ending_track + 1; - else if (track < toc->hdr.starting_track || - track > toc->hdr.ending_track + 1) { - error = EINVAL; - break; - } - - if (te->address_format == CD_MSF_FORMAT) { - struct cd_toc_entry *entry; - - toc = kmalloc(sizeof(struct toc), M_ACD, M_WAITOK | M_ZERO); - bcopy(&cdp->toc, toc, sizeof(struct toc)); - - entry = toc->tab + (track - toc->hdr.starting_track); - lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute, - &entry->addr.msf.second, &entry->addr.msf.frame); - } - bcopy(toc->tab + track - toc->hdr.starting_track, - &te->entry, sizeof(struct cd_toc_entry)); - if (te->address_format == CD_MSF_FORMAT) - kfree(toc, M_ACD); - } - break; - - case CDIOCREADSUBCHANNEL: - { - struct ioc_read_subchannel *args = - (struct ioc_read_subchannel *)ap->a_data; - u_int8_t format; - int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0, - sizeof(cdp->subchan)>>8, sizeof(cdp->subchan), - 0, 0, 0, 0, 0, 0, 0 }; - - if (args->data_len > sizeof(struct cd_sub_channel_info) || - args->data_len < sizeof(struct cd_sub_channel_header)) { - error = EINVAL; - break; - } - - format=args->data_format; - if ((format != CD_CURRENT_POSITION) && - (format != CD_MEDIA_CATALOG) && (format != CD_TRACK_INFO)) { - error = EINVAL; - break; - } - - ccb[1] = args->address_format & CD_MSF_FORMAT; - - if ((error = atapi_queue_cmd(cdp->device,ccb,(caddr_t)&cdp->subchan, - sizeof(cdp->subchan), ATPR_F_READ, 10, - NULL, NULL))) - break; - - if ((format == CD_MEDIA_CATALOG) || (format == CD_TRACK_INFO)) { - if (cdp->subchan.header.audio_status == 0x11) { - error = EINVAL; - break; - } - - ccb[3] = format; - if (format == CD_TRACK_INFO) - ccb[6] = args->track; - - if ((error = atapi_queue_cmd(cdp->device, ccb, - (caddr_t)&cdp->subchan, - sizeof(cdp->subchan), ATPR_F_READ, - 10, NULL, NULL))) { - break; - } - } - error = copyout(&cdp->subchan, args->data, args->data_len); - break; - } - - case CDIOCPLAYMSF: - { - struct ioc_play_msf *args = (struct ioc_play_msf *)ap->a_data; - - error = - acd_play(cdp, - msf2lba(args->start_m, args->start_s, args->start_f), - msf2lba(args->end_m, args->end_s, args->end_f)); - break; - } - - case CDIOCPLAYBLOCKS: - { - struct ioc_play_blocks *args = (struct ioc_play_blocks *)ap->a_data; - - error = acd_play(cdp, args->blk, args->blk + args->len); - break; - } - - case CDIOCPLAYTRACKS: - { - struct ioc_play_track *args = (struct ioc_play_track *)ap->a_data; - int t1, t2; - - if (!cdp->toc.hdr.ending_track) { - error = EIO; - break; - } - if (args->end_track < cdp->toc.hdr.ending_track + 1) - ++args->end_track; - if (args->end_track > cdp->toc.hdr.ending_track + 1) - args->end_track = cdp->toc.hdr.ending_track + 1; - t1 = args->start_track - cdp->toc.hdr.starting_track; - t2 = args->end_track - cdp->toc.hdr.starting_track; - if (t1 < 0 || t2 < 0 || - t1 > (cdp->toc.hdr.ending_track-cdp->toc.hdr.starting_track)) { - error = EINVAL; - break; - } - error = acd_play(cdp, ntohl(cdp->toc.tab[t1].addr.lba), - ntohl(cdp->toc.tab[t2].addr.lba)); - break; - } - - case CDIOCREADAUDIO: - { - struct ioc_read_audio *args = (struct ioc_read_audio *)ap->a_data; - int32_t lba; - caddr_t buffer, ubuf = args->buffer; - int8_t ccb[16]; - int frames; - - if (!cdp->toc.hdr.ending_track) { - error = EIO; - break; - } - - if ((frames = args->nframes) < 0) { - error = EINVAL; - break; - } - - if (args->address_format == CD_LBA_FORMAT) - lba = args->address.lba; - else if (args->address_format == CD_MSF_FORMAT) - lba = msf2lba(args->address.msf.minute, - args->address.msf.second, - args->address.msf.frame); - else { - error = EINVAL; - break; - } - -#ifndef CD_BUFFER_BLOCKS -#define CD_BUFFER_BLOCKS 13 -#endif - buffer = kmalloc(CD_BUFFER_BLOCKS * 2352, M_ACD, M_WAITOK); - bzero(ccb, sizeof(ccb)); - while (frames > 0) { - int8_t blocks; - int size; - - blocks = (frames>CD_BUFFER_BLOCKS) ? CD_BUFFER_BLOCKS : frames; - size = blocks * 2352; - - ccb[0] = ATAPI_READ_CD; - ccb[1] = 4; - ccb[2] = lba>>24; - ccb[3] = lba>>16; - ccb[4] = lba>>8; - ccb[5] = lba; - ccb[8] = blocks; - ccb[9] = 0xf0; - if ((error = atapi_queue_cmd(cdp->device, ccb, buffer, size, - ATPR_F_READ, 30, NULL,NULL))) - break; - - if ((error = copyout(buffer, ubuf, size))) - break; - - ubuf += size; - frames -= blocks; - lba += blocks; - } - kfree(buffer, M_ACD); - if (args->address_format == CD_LBA_FORMAT) - args->address.lba = lba; - else if (args->address_format == CD_MSF_FORMAT) - lba2msf(lba, &args->address.msf.minute, - &args->address.msf.second, - &args->address.msf.frame); - break; - } - - case CDIOCGETVOL: - { - struct ioc_vol *arg = (struct ioc_vol *)ap->a_data; - - if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, - (caddr_t)&cdp->au, sizeof(cdp->au)))) - break; - - if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { - error = EIO; - break; - } - arg->vol[0] = cdp->au.port[0].volume; - arg->vol[1] = cdp->au.port[1].volume; - arg->vol[2] = cdp->au.port[2].volume; - arg->vol[3] = cdp->au.port[3].volume; - break; - } - - case CDIOCSETVOL: - { - struct ioc_vol *arg = (struct ioc_vol *)ap->a_data; - - if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, - (caddr_t)&cdp->au, sizeof(cdp->au)))) - break; - if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { - error = EIO; - break; - } - if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK, - (caddr_t)&cdp->aumask, - sizeof(cdp->aumask)))) - break; - cdp->au.data_length = 0; - cdp->au.port[0].channels = CHANNEL_0; - cdp->au.port[1].channels = CHANNEL_1; - cdp->au.port[0].volume = arg->vol[0] & cdp->aumask.port[0].volume; - cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume; - cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume; - cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume; - error = acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au)); - break; - } - case CDIOCSETPATCH: - { - struct ioc_patch *arg = (struct ioc_patch *)ap->a_data; - - error = acd_setchan(cdp, arg->patch[0], arg->patch[1], - arg->patch[2], arg->patch[3]); - break; - } - - case CDIOCSETMONO: - error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0); - break; - - case CDIOCSETSTEREO: - error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0); - break; - - case CDIOCSETMUTE: - error = acd_setchan(cdp, 0, 0, 0, 0); - break; - - case CDIOCSETLEFT: - error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0); - break; - - case CDIOCSETRIGHT: - error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0); - break; - - case CDRIOCBLANK: - error = acd_blank(cdp, (*(int *)ap->a_data)); - break; - - case CDRIOCNEXTWRITEABLEADDR: - { - struct acd_track_info track_info; - - if ((error = acd_read_track_info(cdp, 0xff, &track_info))) - break; - - if (!track_info.nwa_valid) { - error = EINVAL; - break; - } - *(int*)ap->a_data = track_info.next_writeable_addr; - } - break; - - case CDRIOCINITWRITER: - error = acd_init_writer(cdp, (*(int *)ap->a_data)); - break; - - case CDRIOCINITTRACK: - error = acd_init_track(cdp, (struct cdr_track *)ap->a_data); - break; - - case CDRIOCFLUSH: - error = acd_flush(cdp); - break; - - case CDRIOCFIXATE: - error = acd_fixate(cdp, (*(int *)ap->a_data)); - break; - - case CDRIOCREADSPEED: - { - int speed = *(int *)ap->a_data; - - /* Preserve old behavior: units in multiples of CDROM speed */ - if (speed < 177) - speed *= 177; - error = acd_set_speed(cdp, speed, CDR_MAX_SPEED); - } - break; - - case CDRIOCWRITESPEED: - { - int speed = *(int *)ap->a_data; - - if (speed < 177) - speed *= 177; - error = acd_set_speed(cdp, CDR_MAX_SPEED, speed); - } - break; - - case CDRIOCGETBLOCKSIZE: - *(int *)ap->a_data = cdp->block_size; - break; - - case CDRIOCSETBLOCKSIZE: - cdp->block_size = *(int *)ap->a_data; - acd_set_ioparm(cdp); - break; - - case CDRIOCGETPROGRESS: - error = acd_get_progress(cdp, (int *)ap->a_data); - break; - - case CDRIOCSENDCUE: - error = acd_send_cue(cdp, (struct cdr_cuesheet *)ap->a_data); - break; - - case DVDIOCREPORTKEY: - if (!cdp->cap.read_dvdrom) - error = EINVAL; - else - error = acd_report_key(cdp, (struct dvd_authinfo *)ap->a_data); - break; - - case DVDIOCSENDKEY: - if (!cdp->cap.read_dvdrom) - error = EINVAL; - else - error = acd_send_key(cdp, (struct dvd_authinfo *)ap->a_data); - break; - - case DVDIOCREADSTRUCTURE: - if (!cdp->cap.read_dvdrom) - error = EINVAL; - else - error = acd_read_structure(cdp, (struct dvd_struct *)ap->a_data); - break; - - default: - error = ENOTTY; - } - return error; -} - -static int -acdstrategy(struct dev_strategy_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct bio *bio = ap->a_bio; - struct buf *bp = bio->bio_buf; - struct acd_softc *cdp = dev->si_drv1; - - if (cdp->device->flags & ATA_D_DETACHING) { - bp->b_flags |= B_ERROR; - bp->b_error = ENXIO; - biodone(bio); - return(0); - } - - /* if it's a null transfer, return immediatly. */ - if (bp->b_bcount == 0) { - bp->b_resid = 0; - biodone(bio); - return(0); - } - - KKASSERT(bio->bio_offset != NOOFFSET); - bio->bio_driver_info = dev; - bp->b_resid = bp->b_bcount; - - crit_enter(); - bioqdisksort(&cdp->bio_queue, bio); - crit_exit(); - ata_start(cdp->device->channel); - return(0); -} - -void -acd_start(struct ata_device *atadev) -{ - struct acd_softc *cdp = atadev->driver; - struct bio *bio = bioq_first(&cdp->bio_queue); - struct buf *bp; - cdev_t dev; - u_int32_t lba, lastlba, count; - int8_t ccb[16]; - int track, blocksize; - - if (cdp->changer_info) { - int i; - - cdp = cdp->driver[cdp->changer_info->current_slot]; - bio = bioq_first(&cdp->bio_queue); - - /* check for work pending on any other slot */ - for (i = 0; i < cdp->changer_info->slots; i++) { - if (i == cdp->changer_info->current_slot) - continue; - if (bioq_first(&(cdp->driver[i]->bio_queue))) { - if (bio == NULL || time_second > (cdp->timestamp + 10)) { - acd_select_slot(cdp->driver[i]); - return; - } - } - } - } - if (bio == NULL) - return; - bioq_remove(&cdp->bio_queue, bio); - dev = bio->bio_driver_info; - bp = bio->bio_buf; - - /* reject all queued entries if media changed */ - if (cdp->device->flags & ATA_D_MEDIA_CHANGED) { - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return; - } - - /* - * Special track access is via the high 8 bits of bio_offset - * (128-254). The first track is 129. 128 is used for direct - * raw CD device access which bypasses the disk layer entirely - * (so e.g. writes by burncd don't error out in the disk layer). - */ - track = (bio->bio_offset >> 56) & 127; - - if (track) { - if (track > MAXTRK) { - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return; - } - blocksize = (cdp->toc.tab[track - 1].control & 4) ? 2048 : 2352; - lastlba = ntohl(cdp->toc.tab[track].addr.lba); - lba = (bio->bio_offset & 0x00FFFFFFFFFFFFFFULL) / blocksize; - lba += ntohl(cdp->toc.tab[track - 1].addr.lba); - } else { - blocksize = cdp->block_size; - lastlba = cdp->disk_size; - lba = (bio->bio_offset & 0x00FFFFFFFFFFFFFFULL) / blocksize; - } - bzero(ccb, sizeof(ccb)); - - if (bp->b_bcount % blocksize != 0) { - bp->b_flags |= B_ERROR; - bp->b_error = EINVAL; - biodone(bio); - return; - } - count = bp->b_bcount / blocksize; - - if (bp->b_cmd == BUF_CMD_READ) { - /* if transfer goes beyond range adjust it to be within limits */ - if (lba + count > lastlba) { - /* if we are entirely beyond EOM return EOF */ - if (lastlba <= lba) { - bp->b_resid = bp->b_bcount; - biodone(bio); - return; - } - count = lastlba - lba; - } - switch (blocksize) { - case 2048: - ccb[0] = ATAPI_READ_BIG; - break; - - case 2352: - ccb[0] = ATAPI_READ_CD; - ccb[9] = 0xf8; - break; - - default: - ccb[0] = ATAPI_READ_CD; - ccb[9] = 0x10; - } - } - else - ccb[0] = ATAPI_WRITE_BIG; - - ccb[1] = 0; - ccb[2] = lba>>24; - ccb[3] = lba>>16; - ccb[4] = lba>>8; - ccb[5] = lba; - ccb[6] = count>>16; - ccb[7] = count>>8; - ccb[8] = count; - - devstat_start_transaction(cdp->stats); - bio->bio_caller_info1.ptr = cdp; - atapi_queue_cmd(cdp->device, ccb, bp->b_data, count * blocksize, - ((bp->b_cmd == BUF_CMD_READ) ? ATPR_F_READ : 0), - (ccb[0] == ATAPI_WRITE_BIG) ? 60 : 30, acd_done, bio); -} - -static int -acd_done(struct atapi_request *request) -{ - struct bio *bio = request->driver; - struct buf *bp = bio->bio_buf; - struct acd_softc *cdp = bio->bio_caller_info1.ptr; - - if (request->error) { - bp->b_error = request->error; - bp->b_flags |= B_ERROR; - } else { - bp->b_resid = bp->b_bcount - request->donecount; - } - devstat_end_transaction_buf(cdp->stats, bp); - biodone(bio); - return 0; -} - -static void -acd_read_toc(struct acd_softc *cdp) -{ - struct acd_devlist *entry; - int track, ntracks, len; - u_int32_t sizes[2]; - int8_t ccb[16]; - - bzero(&cdp->toc, sizeof(cdp->toc)); - bzero(ccb, sizeof(ccb)); - - if (atapi_test_ready(cdp->device) != 0) - return; - - cdp->device->flags &= ~ATA_D_MEDIA_CHANGED; - - len = sizeof(struct ioc_toc_header) + sizeof(struct cd_toc_entry); - ccb[0] = ATAPI_READ_TOC; - ccb[7] = len>>8; - ccb[8] = len; - if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)&cdp->toc, len, - ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) { - bzero(&cdp->toc, sizeof(cdp->toc)); - return; - } - ntracks = cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1; - if (ntracks <= 0 || ntracks > MAXTRK) { - bzero(&cdp->toc, sizeof(cdp->toc)); - return; - } - - len = sizeof(struct ioc_toc_header)+(ntracks+1)*sizeof(struct cd_toc_entry); - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_READ_TOC; - ccb[7] = len>>8; - ccb[8] = len; - if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)&cdp->toc, len, - ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) { - bzero(&cdp->toc, sizeof(cdp->toc)); - return; - } - cdp->toc.hdr.len = ntohs(cdp->toc.hdr.len); - - cdp->block_size = (cdp->toc.tab[0].control & 4) ? 2048 : 2352; - cdp->disk_size = 0; - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_READ_CAPACITY; - if (atapi_queue_cmd(cdp->device, ccb, (caddr_t)sizes, sizeof(sizes), - ATPR_F_READ | ATPR_F_QUIET, 30, NULL, NULL)) { - bzero(&cdp->toc, sizeof(cdp->toc)); - acd_set_ioparm(cdp); - return; - } - cdp->disk_size = ntohl(sizes[0]) + 1; - acd_set_ioparm(cdp); - - while ((entry = TAILQ_FIRST(&cdp->dev_list))) { - destroy_dev(entry->dev); - TAILQ_REMOVE(&cdp->dev_list, entry, chain); - kfree(entry, M_ACD); - } - for (track = 1; track <= ntracks; track ++) { - char name[16]; - - ksprintf(name, "acd%dt%d", cdp->lun, track); - entry = kmalloc(sizeof(struct acd_devlist), M_ACD, M_WAITOK | M_ZERO); - entry->dev = make_dev(&acd_ops, - dkmakepart(track + 128) | dkmakeunit(cdp->lun) | - dkmakeslice(WHOLE_DISK_SLICE), - 0, 0, 0644, name, NULL); - entry->dev->si_drv1 = cdp->dev->si_drv1; - reference_dev(entry->dev); - TAILQ_INSERT_TAIL(&cdp->dev_list, entry, chain); - } - -#ifdef ACD_DEBUG - if (cdp->disk_size && cdp->toc.hdr.ending_track) { - ata_prtdev(cdp->device, "(%d sectors (%d bytes)), %d tracks ", - cdp->disk_size, cdp->block_size, - cdp->toc.hdr.ending_track - cdp->toc.hdr.starting_track + 1); - if (cdp->toc.tab[0].control & 4) - kprintf("%dMB\n", cdp->disk_size / 512); - else - kprintf("%d:%d audio\n", - cdp->disk_size / 75 / 60, cdp->disk_size / 75 % 60); - } -#endif -} - -static int -acd_play(struct acd_softc *cdp, int start, int end) -{ - int8_t ccb[16]; - - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_PLAY_MSF; - lba2msf(start, &ccb[3], &ccb[4], &ccb[5]); - lba2msf(end, &ccb[6], &ccb[7], &ccb[8]); - return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 10, NULL, NULL); -} - -static int -acd_setchan(struct acd_softc *cdp, - u_int8_t c0, u_int8_t c1, u_int8_t c2, u_int8_t c3) -{ - int error; - - if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, (caddr_t)&cdp->au, - sizeof(cdp->au)))) - return error; - if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) - return EIO; - cdp->au.data_length = 0; - cdp->au.port[0].channels = c0; - cdp->au.port[1].channels = c1; - cdp->au.port[2].channels = c2; - cdp->au.port[3].channels = c3; - return acd_mode_select(cdp, (caddr_t)&cdp->au, sizeof(cdp->au)); -} - -static int -acd_select_done1(struct atapi_request *request) -{ - struct acd_softc *cdp = request->driver; - - cdp->changer_info->current_slot = cdp->slot; - cdp->driver[cdp->changer_info->current_slot]->timestamp = time_second; - wakeup(&cdp->changer_info); - return 0; -} - -static int -acd_select_done(struct atapi_request *request) -{ - struct acd_softc *cdp = request->driver; - int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 3, 0, 0, 0, - cdp->slot, 0, 0, 0, 0, 0, 0, 0 }; - - /* load the wanted slot */ - atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_AT_HEAD, 30, - acd_select_done1, cdp); - return 0; -} - -static void -acd_select_slot(struct acd_softc *cdp) -{ - int8_t ccb[16] = { ATAPI_LOAD_UNLOAD, 0, 0, 0, 2, 0, 0, 0, - cdp->changer_info->current_slot, 0, 0, 0, 0, 0, 0, 0 }; - - /* unload the current media from player */ - atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_AT_HEAD, 30, - acd_select_done, cdp); -} - -static int -acd_init_writer(struct acd_softc *cdp, int test_write) -{ - int8_t ccb[16]; - - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_REZERO; - atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 60, NULL, NULL); - ccb[0] = ATAPI_SEND_OPC_INFO; - ccb[1] = 0x01; - atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 30, NULL, NULL); - return 0; -} - -static int -acd_fixate(struct acd_softc *cdp, int multisession) -{ - int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0x01, 0x02, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - int timeout = 5*60*2; - int error; - struct write_param param; - - if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE, - (caddr_t)¶m, sizeof(param)))) - return error; - - param.data_length = 0; - if (multisession) - param.session_type = CDR_SESS_MULTI; - else - param.session_type = CDR_SESS_NONE; - - if ((error = acd_mode_select(cdp, (caddr_t)¶m, param.page_length + 10))) - return error; - - error = atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); - if (error) - return error; - - /* some drives just return ready, wait for the expected fixate time */ - if ((error = atapi_test_ready(cdp->device)) != EBUSY) { - timeout = timeout / (cdp->cap.cur_write_speed / 177); - tsleep(&error, 0, "acdfix", timeout * hz / 2); - return atapi_test_ready(cdp->device); - } - - while (timeout-- > 0) { - if ((error = atapi_test_ready(cdp->device)) != EBUSY) - return error; - tsleep(&error, 0, "acdcld", hz/2); - } - return EIO; -} - -static int -acd_init_track(struct acd_softc *cdp, struct cdr_track *track) -{ - struct write_param param; - int error; - - if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE, - (caddr_t)¶m, sizeof(param)))) - return error; - - param.data_length = 0; - param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE; - param.page_length = 0x32; - param.test_write = track->test_write ? 1 : 0; - param.write_type = CDR_WTYPE_TRACK; - param.session_type = CDR_SESS_NONE; - param.fp = 0; - param.packet_size = 0; - - if (cdp->cap.burnproof) - param.burnproof = 1; - - switch (track->datablock_type) { - - case CDR_DB_RAW: - if (track->preemp) - param.track_mode = CDR_TMODE_AUDIO_PREEMP; - else - param.track_mode = CDR_TMODE_AUDIO; - cdp->block_size = 2352; - param.datablock_type = CDR_DB_RAW; - param.session_format = CDR_SESS_CDROM; - break; - - case CDR_DB_ROM_MODE1: - cdp->block_size = 2048; - param.track_mode = CDR_TMODE_DATA; - param.datablock_type = CDR_DB_ROM_MODE1; - param.session_format = CDR_SESS_CDROM; - break; - - case CDR_DB_ROM_MODE2: - cdp->block_size = 2336; - param.track_mode = CDR_TMODE_DATA; - param.datablock_type = CDR_DB_ROM_MODE2; - param.session_format = CDR_SESS_CDROM; - break; - - case CDR_DB_XA_MODE1: - cdp->block_size = 2048; - param.track_mode = CDR_TMODE_DATA; - param.datablock_type = CDR_DB_XA_MODE1; - param.session_format = CDR_SESS_CDROM_XA; - break; - - case CDR_DB_XA_MODE2_F1: - cdp->block_size = 2056; - param.track_mode = CDR_TMODE_DATA; - param.datablock_type = CDR_DB_XA_MODE2_F1; - param.session_format = CDR_SESS_CDROM_XA; - break; - - case CDR_DB_XA_MODE2_F2: - cdp->block_size = 2324; - param.track_mode = CDR_TMODE_DATA; - param.datablock_type = CDR_DB_XA_MODE2_F2; - param.session_format = CDR_SESS_CDROM_XA; - break; - - case CDR_DB_XA_MODE2_MIX: - cdp->block_size = 2332; - param.track_mode = CDR_TMODE_DATA; - param.datablock_type = CDR_DB_XA_MODE2_MIX; - param.session_format = CDR_SESS_CDROM_XA; - break; - } - acd_set_ioparm(cdp); - return acd_mode_select(cdp, (caddr_t)¶m, param.page_length + 10); -} - -static int -acd_flush(struct acd_softc *cdp) -{ - int8_t ccb[16] = { ATAPI_SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->device, ccb, NULL, 0, ATPR_F_QUIET, 60, - NULL, NULL); -} - -static int -acd_read_track_info(struct acd_softc *cdp, - int32_t lba, struct acd_track_info *info) -{ - int8_t ccb[16] = { ATAPI_READ_TRACK_INFO, 1, - lba>>24, lba>>16, lba>>8, lba, - 0, - sizeof(*info)>>8, sizeof(*info), - 0, 0, 0, 0, 0, 0, 0 }; - int error; - - if ((error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)info, sizeof(*info), - ATPR_F_READ, 30, NULL, NULL))) - return error; - info->track_start_addr = ntohl(info->track_start_addr); - info->next_writeable_addr = ntohl(info->next_writeable_addr); - info->free_blocks = ntohl(info->free_blocks); - info->fixed_packet_size = ntohl(info->fixed_packet_size); - info->track_length = ntohl(info->track_length); - return 0; -} - -static int -acd_get_progress(struct acd_softc *cdp, int *finished) -{ - int8_t ccb[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - struct atapi_reqsense *sense = cdp->device->result; - char tmp[8]; - - if (atapi_test_ready(cdp->device) != EBUSY) { - if (atapi_queue_cmd(cdp->device, ccb, tmp, sizeof(tmp), - ATPR_F_READ, 30, NULL, NULL) != EBUSY) { - *finished = 100; - return 0; - } - } - if (sense->sksv) - *finished = - ((sense->sk_specific2 | (sense->sk_specific1 << 8)) * 100) / 65535; - else - *finished = 0; - return 0; -} - -static int -acd_send_cue(struct acd_softc *cdp, struct cdr_cuesheet *cuesheet) -{ - struct write_param param; - int8_t ccb[16] = { ATAPI_SEND_CUE_SHEET, 0, 0, 0, 0, 0, - cuesheet->len>>16, cuesheet->len>>8, cuesheet->len, - 0, 0, 0, 0, 0, 0, 0 }; - int8_t *buffer; - int32_t error; -#ifdef ACD_DEBUG - int i; -#endif - - if ((error = acd_mode_sense(cdp, ATAPI_CDROM_WRITE_PARAMETERS_PAGE, - (caddr_t)¶m, sizeof(param)))) - return error; - param.data_length = 0; - param.page_code = ATAPI_CDROM_WRITE_PARAMETERS_PAGE; - param.page_length = 0x32; - param.test_write = cuesheet->test_write ? 1 : 0; - param.write_type = CDR_WTYPE_SESSION; - param.session_type = cuesheet->session_type; - param.fp = 0; - param.packet_size = 0; - param.track_mode = CDR_TMODE_AUDIO; - param.datablock_type = CDR_DB_RAW; - param.session_format = cuesheet->session_format; - if (cdp->cap.burnproof) - param.burnproof = 1; - if ((error = acd_mode_select(cdp, (caddr_t)¶m, param.page_length + 10))) - return error; - - buffer = kmalloc(cuesheet->len, M_ACD, M_WAITOK); - if ((error = copyin(cuesheet->entries, buffer, cuesheet->len))) - return error; -#ifdef ACD_DEBUG - kprintf("acd: cuesheet lenght = %d\n", cuesheet->len); - for (i=0; ilen; i++) - if (i%8) - kprintf(" %02x", buffer[i]); - else - kprintf("\n%02x", buffer[i]); - kprintf("\n"); -#endif - error = atapi_queue_cmd(cdp->device, ccb, buffer, cuesheet->len, 0, - 30, NULL, NULL); - kfree(buffer, M_ACD); - return error; -} - -static int -acd_report_key(struct acd_softc *cdp, struct dvd_authinfo *ai) -{ - struct dvd_miscauth *d; - u_int32_t lba = 0; - int16_t length; - int8_t ccb[16]; - int error; - - /* this is common even for ai->format == DVD_INVALIDATE_AGID */ - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_REPORT_KEY; - ccb[2] = (lba >> 24) & 0xff; - ccb[3] = (lba >> 16) & 0xff; - ccb[4] = (lba >> 8) & 0xff; - ccb[5] = lba & 0xff; - ccb[10] = (ai->agid << 6) | ai->format; - - switch (ai->format) { - case DVD_REPORT_AGID: - case DVD_REPORT_ASF: - case DVD_REPORT_RPC: - length = 8; - break; - case DVD_REPORT_KEY1: - length = 12; - break; - case DVD_REPORT_TITLE_KEY: - length = 12; - lba = ai->lba; - break; - case DVD_REPORT_CHALLENGE: - length = 16; - break; - case DVD_INVALIDATE_AGID: - return(atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 10, NULL, NULL)); - default: - return EINVAL; - } - - ccb[8] = (length >> 8) & 0xff; - ccb[9] = length & 0xff; - - d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO); - d->length = htons(length - 2); - - error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length, - ATPR_F_READ, 10, NULL, NULL); - if (error) { - kfree(d, M_ACD); - return(error); - } - - switch (ai->format) { - case DVD_REPORT_AGID: - ai->agid = d->data[3] >> 6; - break; - - case DVD_REPORT_CHALLENGE: - bcopy(&d->data[0], &ai->keychal[0], 10); - break; - - case DVD_REPORT_KEY1: - bcopy(&d->data[0], &ai->keychal[0], 5); - break; - - case DVD_REPORT_TITLE_KEY: - ai->cpm = (d->data[0] >> 7); - ai->cp_sec = (d->data[0] >> 6) & 0x1; - ai->cgms = (d->data[0] >> 4) & 0x3; - bcopy(&d->data[1], &ai->keychal[0], 5); - break; - - case DVD_REPORT_ASF: - ai->asf = d->data[3] & 1; - break; - - case DVD_REPORT_RPC: - ai->reg_type = (d->data[0] >> 6); - ai->vend_rsts = (d->data[0] >> 3) & 0x7; - ai->user_rsts = d->data[0] & 0x7; - ai->region = d->data[1]; - ai->rpc_scheme = d->data[2]; - break; - - case DVD_INVALIDATE_AGID: - /* not reached */ - break; - - default: - error = EINVAL; - } - kfree(d, M_ACD); - return error; -} - -static int -acd_send_key(struct acd_softc *cdp, struct dvd_authinfo *ai) -{ - struct dvd_miscauth *d; - int16_t length; - int8_t ccb[16]; - int error; - - switch (ai->format) { - case DVD_SEND_CHALLENGE: - length = 16; - d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO); - bcopy(ai->keychal, &d->data[0], 10); - break; - - case DVD_SEND_KEY2: - length = 12; - d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO); - bcopy(&ai->keychal[0], &d->data[0], 5); - break; - - case DVD_SEND_RPC: - length = 8; - d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO); - d->data[0] = ai->region; - break; - - default: - return EINVAL; - } - - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_SEND_KEY; - ccb[8] = (length >> 8) & 0xff; - ccb[9] = length & 0xff; - ccb[10] = (ai->agid << 6) | ai->format; - d->length = htons(length - 2); - error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length, 0, - 10, NULL, NULL); - kfree(d, M_ACD); - return error; -} - -static int -acd_read_structure(struct acd_softc *cdp, struct dvd_struct *s) -{ - struct dvd_miscauth *d; - u_int16_t length; - int8_t ccb[16]; - int error = 0; - - switch(s->format) { - case DVD_STRUCT_PHYSICAL: - length = 21; - break; - - case DVD_STRUCT_COPYRIGHT: - length = 8; - break; - - case DVD_STRUCT_DISCKEY: - length = 2052; - break; - - case DVD_STRUCT_BCA: - length = 192; - break; - - case DVD_STRUCT_MANUFACT: - length = 2052; - break; - - case DVD_STRUCT_DDS: - case DVD_STRUCT_PRERECORDED: - case DVD_STRUCT_UNIQUEID: - case DVD_STRUCT_LIST: - case DVD_STRUCT_CMI: - case DVD_STRUCT_RMD_LAST: - case DVD_STRUCT_RMD_RMA: - case DVD_STRUCT_DCB: - return ENOSYS; - - default: - return EINVAL; - } - - d = kmalloc(length, M_ACD, M_WAITOK | M_ZERO); - d->length = htons(length - 2); - - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_READ_STRUCTURE; - ccb[6] = s->layer_num; - ccb[7] = s->format; - ccb[8] = (length >> 8) & 0xff; - ccb[9] = length & 0xff; - ccb[10] = s->agid << 6; - error = atapi_queue_cmd(cdp->device, ccb, (caddr_t)d, length, ATPR_F_READ, - 30, NULL, NULL); - if (error) { - kfree(d, M_ACD); - return error; - } - - switch (s->format) { - case DVD_STRUCT_PHYSICAL: { - struct dvd_layer *layer = (struct dvd_layer *)&s->data[0]; - - layer->book_type = d->data[0] >> 4; - layer->book_version = d->data[0] & 0xf; - layer->disc_size = d->data[1] >> 4; - layer->max_rate = d->data[1] & 0xf; - layer->nlayers = (d->data[2] >> 5) & 3; - layer->track_path = (d->data[2] >> 4) & 1; - layer->layer_type = d->data[2] & 0xf; - layer->linear_density = d->data[3] >> 4; - layer->track_density = d->data[3] & 0xf; - layer->start_sector = d->data[5] << 16 | d->data[6] << 8 | d->data[7]; - layer->end_sector = d->data[9] << 16 | d->data[10] << 8 | d->data[11]; - layer->end_sector_l0 = d->data[13] << 16 | d->data[14] << 8|d->data[15]; - layer->bca = d->data[16] >> 7; - break; - } - - case DVD_STRUCT_COPYRIGHT: - s->cpst = d->data[0]; - s->rmi = d->data[0]; - break; - - case DVD_STRUCT_DISCKEY: - bcopy(&d->data[0], &s->data[0], 2048); - break; - - case DVD_STRUCT_BCA: - s->length = ntohs(d->length); - bcopy(&d->data[0], &s->data[0], s->length); - break; - - case DVD_STRUCT_MANUFACT: - s->length = ntohs(d->length); - bcopy(&d->data[0], &s->data[0], s->length); - break; - - default: - error = EINVAL; - } - kfree(d, M_ACD); - return error; -} - -static int -acd_eject(struct acd_softc *cdp, int close) -{ - int error; - - if ((error = acd_start_stop(cdp, 0)) == EBUSY) { - if (!close) - return 0; - if ((error = acd_start_stop(cdp, 3))) - return error; - acd_read_toc(cdp); - acd_prevent_allow(cdp, 1); - cdp->flags |= F_LOCKED; - return 0; - } - if (error) - return error; - if (close) - return 0; - acd_prevent_allow(cdp, 0); - cdp->flags &= ~F_LOCKED; - cdp->device->flags |= ATA_D_MEDIA_CHANGED; - return acd_start_stop(cdp, 2); -} - -static int -acd_blank(struct acd_softc *cdp, int blanktype) -{ - int8_t ccb[16] = { ATAPI_BLANK, 0x10 | (blanktype & 0x7), 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - - cdp->device->flags |= ATA_D_MEDIA_CHANGED; - return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); -} - -static int -acd_prevent_allow(struct acd_softc *cdp, int lock) -{ - int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); -} - -static int -acd_start_stop(struct acd_softc *cdp, int start) -{ - int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); -} - -static int -acd_pause_resume(struct acd_softc *cdp, int pause) -{ - int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause, - 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); -} - -static int -acd_mode_sense(struct acd_softc *cdp, int page, caddr_t pagebuf, int pagesize) -{ - int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, page, 0, 0, 0, 0, - pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - error = atapi_queue_cmd(cdp->device, ccb, pagebuf, pagesize, ATPR_F_READ, - 10, NULL, NULL); -#ifdef ACD_DEBUG - atapi_dump("acd: mode sense ", pagebuf, pagesize); -#endif - return error; -} - -static int -acd_mode_select(struct acd_softc *cdp, caddr_t pagebuf, int pagesize) -{ - int8_t ccb[16] = { ATAPI_MODE_SELECT_BIG, 0x10, 0, 0, 0, 0, 0, - pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 }; - -#ifdef ACD_DEBUG - ata_prtdev(cdp->device, - "modeselect pagesize=%d\n", pagesize); - atapi_dump("mode select ", pagebuf, pagesize); -#endif - return atapi_queue_cmd(cdp->device, ccb, pagebuf, pagesize, 0, - 30, NULL, NULL); -} - -static int -acd_set_speed(struct acd_softc *cdp, int rdspeed, int wrspeed) -{ - int8_t ccb[16] = { ATAPI_SET_SPEED, 0, rdspeed >> 8, rdspeed, - wrspeed >> 8, wrspeed, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - error = atapi_queue_cmd(cdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); - if (!error) - acd_get_cap(cdp); - return error; -} - -static void -acd_get_cap(struct acd_softc *cdp) -{ - int retry = 5; - - /* get drive capabilities, some drives needs this repeated */ - while (retry-- && acd_mode_sense(cdp, ATAPI_CDROM_CAP_PAGE, - (caddr_t)&cdp->cap, sizeof(cdp->cap))) - - cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed); - cdp->cap.cur_read_speed = ntohs(cdp->cap.cur_read_speed); - cdp->cap.max_write_speed = ntohs(cdp->cap.max_write_speed); - cdp->cap.cur_write_speed = max(ntohs(cdp->cap.cur_write_speed), 177); - cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels); - cdp->cap.buf_size = ntohs(cdp->cap.buf_size); -} diff --git a/sys/dev/disk/ata/atapi-cd.h b/sys/dev/disk/ata/atapi-cd.h deleted file mode 100644 index 4972a0a8ca..0000000000 --- a/sys/dev/disk/ata/atapi-cd.h +++ /dev/null @@ -1,330 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-cd.h,v 1.15.2.9 2002/03/18 08:37:34 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-cd.h,v 1.5 2007/05/17 17:44:27 dillon Exp $ - */ - -/* CDROM Table Of Contents */ -#define MAXTRK 99 -struct toc { - struct ioc_toc_header hdr; - struct cd_toc_entry tab[MAXTRK + 1]; -}; - -/* DVD CSS authentication */ -struct dvd_miscauth { - u_int16_t length; - u_int16_t reserved; - u_int8_t data[2048]; -}; - -/* CDROM Audio Control Parameters Page */ -struct audiopage { - /* mode page data header */ - u_int16_t data_length; - u_int8_t medium_type; - u_int8_t dev_spec; - u_int8_t unused[2]; - u_int16_t blk_desc_len; - - /* audio control page */ - u_int8_t page_code; -#define ATAPI_CDROM_AUDIO_PAGE 0x0e -#define ATAPI_CDROM_AUDIO_PAGE_MASK 0x4e - - u_int8_t param_len; - u_int8_t flags; -#define CD_PA_SOTC 0x02 -#define CD_PA_IMMED 0x04 - - u_int8_t reserved3; - u_int8_t reserved4; - u_int8_t reserved5; - u_int16_t lb_per_sec; - struct port_control { - u_int8_t channels:4; -#define CHANNEL_0 1 -#define CHANNEL_1 2 -#define CHANNEL_2 4 -#define CHANNEL_3 8 - - u_int8_t volume; - } port[4]; -}; - -/* CDROM Capabilities and Mechanical Status Page */ -struct cappage { - /* mode page data header */ - u_int16_t data_length; - u_int8_t medium_type; -#define MST_TYPE_MASK_LOW 0x0f -#define MST_FMT_NONE 0x00 -#define MST_DATA_120 0x01 -#define MST_AUDIO_120 0x02 -#define MST_COMB_120 0x03 -#define MST_PHOTO_120 0x04 -#define MST_DATA_80 0x05 -#define MST_AUDIO_80 0x06 -#define MST_COMB_80 0x07 -#define MST_PHOTO_80 0x08 - -#define MST_TYPE_MASK_HIGH 0x70 -#define MST_CDROM 0x00 -#define MST_CDR 0x10 -#define MST_CDRW 0x20 - -#define MST_NO_DISC 0x70 -#define MST_DOOR_OPEN 0x71 -#define MST_FMT_ERROR 0x72 - - u_int8_t dev_spec; - u_int8_t unused[2]; - u_int16_t blk_desc_len; - - /* capabilities page */ - u_int8_t page_code; -#define ATAPI_CDROM_CAP_PAGE 0x2a - - u_int8_t param_len; - u_int8_t read_cdr :1; /* supports CD-R read */ - u_int8_t read_cdrw :1; /* supports CD-RW read */ - u_int8_t read_packet :1; /* supports reading packet tracks */ - u_int8_t read_dvdrom :1; /* supports DVD-ROM read */ - u_int8_t read_dvdr :1; /* supports DVD-R read */ - u_int8_t read_dvdram :1; /* supports DVD-RAM read */ - u_int8_t reserved2_67 :2; - u_int8_t write_cdr :1; /* supports CD-R write */ - u_int8_t write_cdrw :1; /* supports CD-RW write */ - u_int8_t test_write :1; /* supports test writing */ - u_int8_t reserved3_3 :1; - u_int8_t write_dvdr :1; /* supports DVD-R write */ - u_int8_t write_dvdram :1; /* supports DVD-RAM write */ - u_int8_t reserved3_67 :2; - u_int8_t audio_play :1; /* audio play supported */ - u_int8_t composite :1; /* composite audio/video supported */ - u_int8_t dport1 :1; /* digital audio on port 1 */ - u_int8_t dport2 :1; /* digital audio on port 2 */ - u_int8_t mode2_form1 :1; /* mode 2 form 1 (XA) read */ - u_int8_t mode2_form2 :1; /* mode 2 form 2 format */ - u_int8_t multisession :1; /* multi-session photo-CD */ - u_int8_t burnproof :1; /* supports burnproof */ - u_int8_t cd_da :1; /* audio-CD read supported */ - u_int8_t cd_da_stream :1; /* CD-DA streaming */ - u_int8_t rw :1; /* combined R-W subchannels */ - u_int8_t rw_corr :1; /* R-W subchannel data corrected */ - u_int8_t c2 :1; /* C2 error pointers supported */ - u_int8_t isrc :1; /* can return the ISRC info */ - u_int8_t upc :1; /* can return the catalog number UPC */ - u_int8_t :1; - u_int8_t lock :1; /* can be locked */ - u_int8_t locked :1; /* current lock state */ - u_int8_t prevent :1; /* prevent jumper installed */ - u_int8_t eject :1; /* can eject */ - u_int8_t :1; - u_int8_t mech :3; /* loading mechanism type */ -#define MST_MECH_CADDY 0 -#define MST_MECH_TRAY 1 -#define MST_MECH_POPUP 2 -#define MST_MECH_CHANGER 4 -#define MST_MECH_CARTRIDGE 5 - - u_int8_t sep_vol :1; /* independent volume of channels */ - u_int8_t sep_mute :1; /* independent mute of channels */ - u_int8_t:6; - - u_int16_t max_read_speed; /* max raw data rate in bytes/1000 */ - u_int16_t max_vol_levels; /* number of discrete volume levels */ - u_int16_t buf_size; /* internal buffer size in bytes/1024 */ - u_int16_t cur_read_speed; /* current data rate in bytes/1000 */ - - u_int8_t reserved3; - u_int8_t bckf :1; /* data valid on failing edge of BCK */ - u_int8_t rch :1; /* high LRCK indicates left channel */ - u_int8_t lsbf :1; /* set if LSB first */ - u_int8_t dlen :2; -#define MST_DLEN_32 0 -#define MST_DLEN_16 1 -#define MST_DLEN_24 2 -#define MST_DLEN_24_I2S 3 - - u_int8_t :3; - u_int16_t max_write_speed; /* max raw data rate in bytes/1000 */ - u_int16_t cur_write_speed; /* current data rate in bytes/1000 */ - u_int16_t copy_protect_rev; - u_int16_t reserved4; -}; - -/* CDROM Changer mechanism status structure */ -struct changer { - u_int8_t current_slot :5; /* active changer slot */ - u_int8_t mech_state :2; /* current changer state */ -#define CH_READY 0 -#define CH_LOADING 1 -#define CH_UNLOADING 2 -#define CH_INITIALIZING 3 - - u_int8_t fault :1; /* fault in last operation */ - u_int8_t reserved0 :5; - u_int8_t cd_state :3; /* current mechanism state */ -#define CD_IDLE 0 -#define CD_AUDIO_ACTIVE 1 -#define CD_AUDIO_SCAN 2 -#define CD_HOST_ACTIVE 3 -#define CD_NO_STATE 7 - - u_int8_t current_lba[3]; /* current LBA */ - u_int8_t slots; /* number of available slots */ - u_int16_t table_length; /* slot table length */ - struct { - u_int8_t changed :1; /* media has changed in this slot */ - u_int8_t unused :6; - u_int8_t present :1; /* slot has a CD present */ - u_int8_t reserved0; - u_int8_t reserved1; - u_int8_t reserved2; - } slot[32]; -}; - -/* CDROM Write Parameters Mode Page (Burners ONLY) */ -struct write_param { - /* mode page data header */ - u_int16_t data_length; - u_int8_t medium_type; - u_int8_t dev_spec; - u_int8_t unused[2]; - u_int16_t blk_desc_len; - - /* write parameters page */ - u_int8_t page_code; -#define ATAPI_CDROM_WRITE_PARAMETERS_PAGE 0x05 - - u_int8_t page_length; /* 0x32 */ - u_int8_t write_type :4; /* write stream type */ -#define CDR_WTYPE_PACKET 0x00 -#define CDR_WTYPE_TRACK 0x01 -#define CDR_WTYPE_SESSION 0x02 -#define CDR_WTYPE_RAW 0x03 - - u_int8_t test_write :1; /* test write enable */ - u_int8_t reserved2_5 :1; - u_int8_t burnproof :1; /* BurnProof enable */ - u_int8_t reserved2_7 :1; - u_int8_t track_mode :4; /* track mode */ -#define CDR_TMODE_AUDIO 0x00 -#define CDR_TMODE_AUDIO_PREEMP 0x01 -#define CDR_TMODE_ALLOW_COPY 0x02 -#define CDR_TMODE_DATA 0x04 -#define CDR_TMODE_QUAD_AUDIO 0x08 - - u_int8_t copy :1; /* generation stamp */ - u_int8_t fp :1; /* fixed packet type */ - u_int8_t session_type :2; /* session type */ -#define CDR_SESS_NONE 0x00 -#define CDR_SESS_FINAL 0x01 -#define CDR_SESS_RESERVED 0x02 -#define CDR_SESS_MULTI 0x03 - - u_int8_t datablock_type :4; /* data type code (see cdrio.h) */ - u_int8_t reserved4_4567 :4; - u_int8_t reserved5; - u_int8_t reserved6; - u_int8_t host_app_code :6; /* host application code */ - u_int8_t reserved7_67 :2; - u_int8_t session_format; /* session format */ -#define CDR_SESS_CDROM 0x00 -#define CDR_SESS_CDI 0x10 -#define CDR_SESS_CDROM_XA 0x20 - - u_int8_t reserved9; - u_int32_t packet_size; /* packet size in bytes */ - u_int16_t audio_pause_length; /* audio pause length in secs */ - u_int8_t media_catalog_number[16]; - u_int8_t isr_code[16]; - u_int8_t sub_hdr_byte0; - u_int8_t sub_hdr_byte1; - u_int8_t sub_hdr_byte2; - u_int8_t sub_hdr_byte3; - u_int8_t vendor_specific_byte0; - u_int8_t vendor_specific_byte1; - u_int8_t vendor_specific_byte2; - u_int8_t vendor_specific_byte3; -} __attribute__((packed)); - -/* CDROM Read Track Information structure */ -struct acd_track_info { - u_int16_t data_length; - u_int8_t track_number; /* current track number */ - u_int8_t session_number; /* current session number */ - u_int8_t reserved4; - u_int8_t track_mode :4; /* mode of this track */ - u_int8_t copy :1; /* generation stamp */ - u_int8_t damage :1; /* damaged track */ - u_int8_t reserved5_67 :2; - u_int8_t data_mode :4; /* data mode of this disc */ - u_int8_t fp :1; /* fixed packet */ - u_int8_t packet :1; /* packet track */ - u_int8_t blank :1; /* blank (empty) track */ - u_int8_t rt :1; /* reserved track */ - u_int8_t nwa_valid :1; /* next_writeable_addr field valid */ - u_int8_t reserved7_17 :7; - u_int track_start_addr; /* start of this track */ - u_int next_writeable_addr; /* next writeable addr on this disc */ - u_int free_blocks; /* free block on this disc */ - u_int fixed_packet_size; /* size of packets on this track */ - u_int track_length; /* length of this track */ -}; - -struct acd_devlist { - cdev_t dev; - TAILQ_ENTRY(acd_devlist) chain; /* list management */ -}; - -/* Structure describing an ATAPI CDROM device */ -struct acd_softc { - struct ata_device *device; /* device softc */ - int lun; /* logical device unit */ - int flags; /* device state flags */ -#define F_LOCKED 0x0001 /* this unit is locked */ - - struct bio_queue_head bio_queue; /* queue of i/o requests */ - TAILQ_HEAD(, acd_devlist) dev_list; /* list of "track" devices */ - struct toc toc; /* table of disc contents */ - struct audiopage au; /* audio page info */ - struct audiopage aumask; /* audio page mask */ - struct cappage cap; /* capabilities page info */ - struct cd_sub_channel_info subchan; /* subchannel info */ - struct changer *changer_info; /* changer info */ - struct acd_softc **driver; /* softc's of changer slots */ - int slot; /* this instance slot number */ - time_t timestamp; /* this instance timestamp */ - int disk_size; /* size of current media */ - int block_size; /* blocksize currently used */ - struct disk disk; /* disk management */ - struct devstat *stats; /* devstat entry */ - cdev_t dev; /* device place holders */ -}; diff --git a/sys/dev/disk/ata/atapi-fd.c b/sys/dev/disk/ata/atapi-fd.c deleted file mode 100644 index 6b10cdfe8c..0000000000 --- a/sys/dev/disk/ata/atapi-fd.c +++ /dev/null @@ -1,430 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-fd.c,v 1.44.2.9 2002/07/31 11:19:26 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-fd.c,v 1.22 2008/01/06 16:55:49 swildner Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ata-all.h" -#include "atapi-all.h" -#include "atapi-fd.h" - -/* device structures */ -static d_open_t afdopen; -static d_close_t afdclose; -static d_ioctl_t afdioctl; -static d_strategy_t afdstrategy; - -static struct dev_ops afd_ops = { - { "afd", 118, D_DISK | D_TRACKCLOSE }, - .d_open = afdopen, - .d_close = afdclose, - .d_read = physread, - .d_write = physwrite, - .d_ioctl = afdioctl, - .d_strategy = afdstrategy, -}; - -/* prototypes */ -static int afd_sense(struct afd_softc *); -static void afd_describe(struct afd_softc *); -static int afd_done(struct atapi_request *); -static int afd_eject(struct afd_softc *, int); -static int afd_start_stop(struct afd_softc *, int); -static int afd_prevent_allow(struct afd_softc *, int); - -/* internal vars */ -static u_int32_t afd_lun_map = 0; -static MALLOC_DEFINE(M_AFD, "AFD driver", "ATAPI floppy driver buffers"); - -int -afdattach(struct ata_device *atadev) -{ - struct afd_softc *fdp; - cdev_t dev; - - fdp = kmalloc(sizeof(struct afd_softc), M_AFD, M_WAITOK | M_ZERO); - - fdp->device = atadev; - fdp->lun = ata_get_lun(&afd_lun_map); - ata_set_name(atadev, "afd", fdp->lun); - bioq_init(&fdp->bio_queue); - - if (afd_sense(fdp)) { - kfree(fdp, M_AFD); - return 0; - } - - devstat_add_entry(&fdp->stats, "afd", fdp->lun, DEV_BSIZE, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE, - DEVSTAT_PRIORITY_WFD); - dev = disk_create(fdp->lun, &fdp->disk, &afd_ops); - dev->si_drv1 = fdp; - fdp->dev = dev; - - if (!strncmp(atadev->param->model, "IOMEGA ZIP", 10) || - !strncmp(atadev->param->model, "IOMEGA Clik!", 12)) - fdp->dev->si_iosize_max = 64 * DEV_BSIZE; - else - fdp->dev->si_iosize_max = 252 * DEV_BSIZE; - - afd_describe(fdp); - atadev->flags |= ATA_D_MEDIA_CHANGED; - atadev->driver = fdp; - return 1; -} - -void -afddetach(struct ata_device *atadev) -{ - struct afd_softc *fdp = atadev->driver; - struct bio *bio; - struct buf *bp; - - while ((bio = bioq_first(&fdp->bio_queue))) { - bioq_remove(&fdp->bio_queue, bio); - bp = bio->bio_buf; - bp->b_flags |= B_ERROR; - bp->b_error = ENXIO; - biodone(bio); - } - disk_invalidate(&fdp->disk); - disk_destroy(&fdp->disk); - devstat_remove_entry(&fdp->stats); - ata_free_name(atadev); - ata_free_lun(&afd_lun_map, fdp->lun); - kfree(fdp, M_AFD); - atadev->driver = NULL; -} - -static int -afd_sense(struct afd_softc *fdp) -{ - int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE, - 0, 0, 0, 0, sizeof(struct afd_cappage) >> 8, - sizeof(struct afd_cappage) & 0xff, 0, 0, 0, 0, 0, 0, 0 }; - int count, error = 0; - - /* The IOMEGA Clik! doesn't support reading the cap page, fake it */ - if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12)) { - fdp->cap.transfer_rate = 500; - fdp->cap.heads = 1; - fdp->cap.sectors = 2; - fdp->cap.cylinders = 39441; - fdp->cap.sector_size = 512; - atapi_test_ready(fdp->device); - return 0; - } - - /* get drive capabilities, some drives needs this repeated */ - for (count = 0 ; count < 5 ; count++) { - if (!(error = atapi_queue_cmd(fdp->device, ccb, (caddr_t)&fdp->cap, - sizeof(struct afd_cappage), - ATPR_F_READ, 30, NULL, NULL))) - break; - } - if (error || fdp->cap.page_code != ATAPI_REWRITEABLE_CAP_PAGE) - return 1; - fdp->cap.cylinders = ntohs(fdp->cap.cylinders); - fdp->cap.sector_size = ntohs(fdp->cap.sector_size); - fdp->cap.transfer_rate = ntohs(fdp->cap.transfer_rate); - return 0; -} - -static void -afd_describe(struct afd_softc *fdp) -{ - if (bootverbose) { - ata_prtdev(fdp->device, - "<%.40s/%.8s> rewriteable drive at ata%d as %s\n", - fdp->device->param->model, fdp->device->param->revision, - device_get_unit(fdp->device->channel->dev), - (fdp->device->unit == ATA_MASTER) ? "master" : "slave"); - ata_prtdev(fdp->device, - "%luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n", - (fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) / - ((1024L * 1024L) / fdp->cap.sector_size), - fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors, - fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors, - fdp->cap.sector_size); - ata_prtdev(fdp->device, "%dKB/s,", fdp->cap.transfer_rate / 8); - kprintf(" %s\n", ata_mode2str(fdp->device->mode)); - if (fdp->cap.medium_type) { - ata_prtdev(fdp->device, "Medium: "); - switch (fdp->cap.medium_type) { - case MFD_2DD: - kprintf("720KB DD disk"); break; - - case MFD_HD_12: - kprintf("1.2MB HD disk"); break; - - case MFD_HD_144: - kprintf("1.44MB HD disk"); break; - - case MFD_UHD: - kprintf("120MB UHD disk"); break; - - default: - kprintf("Unknown (0x%x)", fdp->cap.medium_type); - } - if (fdp->cap.wp) kprintf(", writeprotected"); - } - kprintf("\n"); - } - else { - ata_prtdev(fdp->device, "%luMB <%.40s> [%d/%d/%d] at ata%d-%s %s\n", - (fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) / - ((1024L * 1024L) / fdp->cap.sector_size), - fdp->device->param->model, - fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors, - device_get_unit(fdp->device->channel->dev), - (fdp->device->unit == ATA_MASTER) ? "master" : "slave", - ata_mode2str(fdp->device->mode)); - } -} - -static int -afdopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct afd_softc *fdp = dev->si_drv1; - struct disk_info info; - - atapi_test_ready(fdp->device); - - if (count_dev(dev) == 1) - afd_prevent_allow(fdp, 1); - - if (afd_sense(fdp)) - ata_prtdev(fdp->device, "sense media type failed\n"); - - fdp->device->flags &= ~ATA_D_MEDIA_CHANGED; - - bzero(&info, sizeof(info)); - info.d_media_blksize = fdp->cap.sector_size; /* mandatory */ - info.d_media_blocks = fdp->cap.sectors * fdp->cap.heads * - fdp->cap.cylinders; - - info.d_secpertrack = fdp->cap.sectors; /* optional */ - info.d_nheads = fdp->cap.heads; - info.d_ncylinders = fdp->cap.cylinders; - info.d_secpercyl = fdp->cap.sectors * fdp->cap.heads; - - disk_setdiskinfo(&fdp->disk, &info); - return 0; -} - -static int -afdclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct afd_softc *fdp = dev->si_drv1; - - if (count_dev(dev) == 1) - afd_prevent_allow(fdp, 0); - return 0; -} - -static int -afdioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct afd_softc *fdp = dev->si_drv1; - - switch (ap->a_cmd) { - case CDIOCEJECT: - if (count_dev(dev) > 1) - return EBUSY; - return afd_eject(fdp, 0); - - case CDIOCCLOSE: - if (count_dev(dev) > 1) - return 0; - return afd_eject(fdp, 1); - - default: - return ENOIOCTL; - } -} - -static int -afdstrategy(struct dev_strategy_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct bio *bio = ap->a_bio; - struct buf *bp = bio->bio_buf; - struct afd_softc *fdp = dev->si_drv1; - - if (fdp->device->flags & ATA_D_DETACHING) { - bp->b_flags |= B_ERROR; - bp->b_error = ENXIO; - biodone(bio); - return(0); - } - - /* if it's a null transfer, return immediatly. */ - if (bp->b_bcount == 0) { - bp->b_resid = 0; - biodone(bio); - return(0); - } - - crit_enter(); - bioqdisksort(&fdp->bio_queue, bio); - crit_exit(); - ata_start(fdp->device->channel); - return(0); -} - -void -afd_start(struct ata_device *atadev) -{ - struct afd_softc *fdp = atadev->driver; - struct bio *bio = bioq_first(&fdp->bio_queue); - struct buf *bp; - u_int32_t lba; - u_int16_t count; - int8_t ccb[16]; - caddr_t data_ptr; - - if (bio == NULL) - return; - - bioq_remove(&fdp->bio_queue, bio); - bp = bio->bio_buf; - - /* should reject all queued entries if media have changed. */ - if (fdp->device->flags & ATA_D_MEDIA_CHANGED) { - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return; - } - - KKASSERT(bio->bio_offset % fdp->cap.sector_size == 0); - - lba = bio->bio_offset / fdp->cap.sector_size; - count = bp->b_bcount / fdp->cap.sector_size; - data_ptr = bp->b_data; - bp->b_resid = bp->b_bcount; - - bzero(ccb, sizeof(ccb)); - - if (bp->b_cmd == BUF_CMD_READ) - ccb[0] = ATAPI_READ_BIG; - else - ccb[0] = ATAPI_WRITE_BIG; - - ccb[2] = lba>>24; - ccb[3] = lba>>16; - ccb[4] = lba>>8; - ccb[5] = lba; - ccb[7] = count>>8; - ccb[8] = count; - - devstat_start_transaction(&fdp->stats); - - atapi_queue_cmd(fdp->device, ccb, data_ptr, count * fdp->cap.sector_size, - ((bp->b_cmd == BUF_CMD_READ) ? ATPR_F_READ : 0), - 30, afd_done, bio); -} - -static int -afd_done(struct atapi_request *request) -{ - struct bio *bio = request->driver; - struct buf *bp = bio->bio_buf; - struct afd_softc *fdp = request->device->driver; - - if (request->error || (bp->b_flags & B_ERROR)) { - bp->b_error = request->error; - bp->b_flags |= B_ERROR; - } - else - bp->b_resid = bp->b_bcount - request->donecount; - devstat_end_transaction_buf(&fdp->stats, bp); - biodone(bio); - return 0; -} - -static int -afd_eject(struct afd_softc *fdp, int close) -{ - int error; - - if ((error = afd_start_stop(fdp, 0)) == EBUSY) { - if (!close) - return 0; - if ((error = afd_start_stop(fdp, 3))) - return error; - return afd_prevent_allow(fdp, 1); - } - if (error) - return error; - if (close) - return 0; - if ((error = afd_prevent_allow(fdp, 0))) - return error; - fdp->device->flags |= ATA_D_MEDIA_CHANGED; - return afd_start_stop(fdp, 2); -} - -static int -afd_start_stop(struct afd_softc *fdp, int start) -{ - int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(fdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); -} - -static int -afd_prevent_allow(struct afd_softc *fdp, int lock) -{ - int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12)) - return 0; - return atapi_queue_cmd(fdp->device, ccb, NULL, 0, 0, 30, NULL, NULL); -} diff --git a/sys/dev/disk/ata/atapi-fd.h b/sys/dev/disk/ata/atapi-fd.h deleted file mode 100644 index e2151748ad..0000000000 --- a/sys/dev/disk/ata/atapi-fd.h +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-fd.h,v 1.10.2.5 2002/07/31 11:19:26 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-fd.h,v 1.4 2006/09/10 01:26:33 dillon Exp $ - */ - -/* ATAPI Rewriteable drive Capabilities and Mechanical Status Page */ -struct afd_cappage { - u_int16_t data_length; - u_int8_t medium_type; -#define MFD_2DD_UN 0x10 -#define MFD_2DD 0x11 -#define MFD_HD_UN 0x20 -#define MFD_HD_12_98 0x22 -#define MFD_HD_12 0x23 -#define MFD_HD_144 0x24 -#define MFD_UHD 0x31 - -#define MFD_UNKNOWN 0x00 -#define MFD_NO_DISC 0x70 -#define MFD_DOOR_OPEN 0x71 -#define MFD_FMT_ERROR 0x72 - - u_int8_t reserved0 :7; - u_int8_t wp :1; /* write protect */ - u_int8_t unused[4]; - - /* capabilities page */ - u_int8_t page_code :6; -#define ATAPI_REWRITEABLE_CAP_PAGE 0x05 - - u_int8_t reserved1_6 :1; - u_int8_t ps :1; /* page save supported */ - u_int8_t page_length; /* page length */ - u_int16_t transfer_rate; /* in kilobits per second */ - u_int8_t heads; /* number of heads */ - u_int8_t sectors; /* number of sectors pr track */ - u_int16_t sector_size; /* number of bytes per sector */ - u_int16_t cylinders; /* number of cylinders */ - u_int8_t reserved10[10]; - u_int8_t motor_delay; /* motor off delay */ - u_int8_t reserved21[7]; - u_int16_t rpm; /* rotations per minute */ - u_int8_t reserved30[2]; -}; - -struct afd_softc { - struct ata_device *device; /* device softc */ - int lun; /* logical device unit */ - struct bio_queue_head bio_queue; /* queue of i/o requests */ - struct afd_cappage cap; /* capabilities page info */ - struct disk disk; /* virtual drives */ - struct devstat stats; - cdev_t dev; /* device place holder */ -}; - diff --git a/sys/dev/disk/ata/atapi-tape.c b/sys/dev/disk/ata/atapi-tape.c deleted file mode 100644 index ab8ddacac8..0000000000 --- a/sys/dev/disk/ata/atapi-tape.c +++ /dev/null @@ -1,661 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-tape.c,v 1.36.2.12 2002/07/31 11:19:26 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-tape.c,v 1.22 2008/01/06 16:55:49 swildner Exp $ - */ - -#include "opt_ata.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ata-all.h" -#include "atapi-all.h" -#include "atapi-tape.h" - -/* device structures */ -static d_open_t astopen; -static d_close_t astclose; -static d_ioctl_t astioctl; -static d_strategy_t aststrategy; - -static struct dev_ops ast_ops = { - { "ast", 119, D_TAPE | D_TRACKCLOSE }, - .d_open = astopen, - .d_close = astclose, - .d_read = physread, - .d_write = physwrite, - .d_ioctl = astioctl, - .d_strategy = aststrategy -}; - -/* prototypes */ -static int ast_sense(struct ast_softc *); -static void ast_describe(struct ast_softc *); -static int ast_done(struct atapi_request *); -static int ast_mode_sense(struct ast_softc *, int, void *, int); -static int ast_mode_select(struct ast_softc *, void *, int); -static int ast_write_filemark(struct ast_softc *, u_int8_t); -static int ast_read_position(struct ast_softc *, int, struct ast_readposition *); -static int ast_space(struct ast_softc *, u_int8_t, int32_t); -static int ast_locate(struct ast_softc *, int, u_int32_t); -static int ast_prevent_allow(struct ast_softc *stp, int); -static int ast_load_unload(struct ast_softc *, u_int8_t); -static int ast_rewind(struct ast_softc *); -static int ast_erase(struct ast_softc *); - -/* internal vars */ -static u_int32_t ast_lun_map = 0; -static u_int64_t ast_total = 0; -static MALLOC_DEFINE(M_AST, "AST driver", "ATAPI tape driver buffers"); - -int -astattach(struct ata_device *atadev) -{ - struct ast_softc *stp; - struct ast_readposition position; - cdev_t dev; - - stp = kmalloc(sizeof(struct ast_softc), M_AST, M_WAITOK | M_ZERO); - - stp->device = atadev; - stp->lun = ata_get_lun(&ast_lun_map); - ata_set_name(atadev, "ast", stp->lun); - bioq_init(&stp->bio_queue); - - if (ast_sense(stp)) { - kfree(stp, M_AST); - return 0; - } - - if (!strcmp(atadev->param->model, "OnStream DI-30")) { - struct ast_transferpage transfer; - struct ast_identifypage identify; - - stp->flags |= F_ONSTREAM; - bzero(&transfer, sizeof(struct ast_transferpage)); - ast_mode_sense(stp, ATAPI_TAPE_TRANSFER_PAGE, - &transfer, sizeof(transfer)); - bzero(&identify, sizeof(struct ast_identifypage)); - ast_mode_sense(stp, ATAPI_TAPE_IDENTIFY_PAGE, - &identify, sizeof(identify)); - strncpy(identify.ident, "FBSD", 4); - ast_mode_select(stp, &identify, sizeof(identify)); - ast_read_position(stp, 0, &position); - } - - devstat_add_entry(&stp->stats, "ast", stp->lun, DEV_BSIZE, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE, - DEVSTAT_PRIORITY_TAPE); - dev = make_dev(&ast_ops, dkmakeminor(stp->lun, 0, 0), - UID_ROOT, GID_OPERATOR, 0640, "ast%d", stp->lun); - dev->si_drv1 = stp; - dev->si_iosize_max = 256 * DEV_BSIZE; - dev = make_dev(&ast_ops, dkmakeminor(stp->lun, 0, 1), - UID_ROOT, GID_OPERATOR, 0640, "nast%d", stp->lun); - dev->si_drv1 = stp; - dev->si_iosize_max = 256 * DEV_BSIZE; - stp->device->flags |= ATA_D_MEDIA_CHANGED; - ast_describe(stp); - atadev->driver = stp; - return 1; -} - -void -astdetach(struct ata_device *atadev) -{ - struct ast_softc *stp = atadev->driver; - struct buf *bp; - struct bio *bio; - - while ((bio = bioq_first(&stp->bio_queue))) { - bioq_remove(&stp->bio_queue, bio); - bp = bio->bio_buf; - bp->b_flags |= B_ERROR; - bp->b_error = ENXIO; - biodone(bio); - } - devstat_remove_entry(&stp->stats); - dev_ops_remove_minor(&ast_ops,/* dkunitmask(), */dkmakeunit(stp->lun)); - ata_free_name(atadev); - ata_free_lun(&ast_lun_map, stp->lun); - kfree(stp, M_AST); - atadev->driver = NULL; -} - -static int -ast_sense(struct ast_softc *stp) -{ - int count, error = 0; - - /* get drive capabilities, some drives needs this repeated */ - for (count = 0 ; count < 5 ; count++) { - if (!(error = ast_mode_sense(stp, ATAPI_TAPE_CAP_PAGE, - &stp->cap, sizeof(stp->cap)))) { - if (stp->cap.blk32k) - stp->blksize = 32768; - if (stp->cap.blk1024) - stp->blksize = 1024; - if (stp->cap.blk512) - stp->blksize = 512; - if (!stp->blksize) - continue; - stp->cap.max_speed = ntohs(stp->cap.max_speed); - stp->cap.max_defects = ntohs(stp->cap.max_defects); - stp->cap.ctl = ntohs(stp->cap.ctl); - stp->cap.speed = ntohs(stp->cap.speed); - stp->cap.buffer_size = ntohs(stp->cap.buffer_size); - return 0; - } - } - return 1; -} - -static void -ast_describe(struct ast_softc *stp) -{ - if (bootverbose) { - ata_prtdev(stp->device, "<%.40s/%.8s> tape drive at ata%d as %s\n", - stp->device->param->model, stp->device->param->revision, - device_get_unit(stp->device->channel->dev), - (stp->device->unit == ATA_MASTER) ? "master" : "slave"); - ata_prtdev(stp->device, "%dKB/s, ", stp->cap.max_speed); - kprintf("transfer limit %d blk%s, ", - stp->cap.ctl, (stp->cap.ctl > 1) ? "s" : ""); - kprintf("%dKB buffer, ", (stp->cap.buffer_size * DEV_BSIZE) / 1024); - kprintf("%s\n", ata_mode2str(stp->device->mode)); - ata_prtdev(stp->device, "Medium: "); - switch (stp->cap.medium_type) { - case 0x00: - kprintf("none"); break; - case 0x17: - kprintf("Travan 1 (400 Mbyte)"); break; - case 0xb6: - kprintf("Travan 4 (4 Gbyte)"); break; - case 0xda: - kprintf("OnStream ADR (15Gyte)"); break; - default: - kprintf("unknown (0x%x)", stp->cap.medium_type); - } - if (stp->cap.readonly) kprintf(", readonly"); - if (stp->cap.reverse) kprintf(", reverse"); - if (stp->cap.eformat) kprintf(", eformat"); - if (stp->cap.qfa) kprintf(", qfa"); - if (stp->cap.lock) kprintf(", lock"); - if (stp->cap.locked) kprintf(", locked"); - if (stp->cap.prevent) kprintf(", prevent"); - if (stp->cap.eject) kprintf(", eject"); - if (stp->cap.disconnect) kprintf(", disconnect"); - if (stp->cap.ecc) kprintf(", ecc"); - if (stp->cap.compress) kprintf(", compress"); - if (stp->cap.blk512) kprintf(", 512b"); - if (stp->cap.blk1024) kprintf(", 1024b"); - if (stp->cap.blk32k) kprintf(", 32kb"); - kprintf("\n"); - } - else { - ata_prtdev(stp->device, "TAPE <%.40s> at ata%d-%s %s\n", - stp->device->param->model, - device_get_unit(stp->device->channel->dev), - (stp->device->unit == ATA_MASTER) ? "master" : "slave", - ata_mode2str(stp->device->mode)); - } -} - -static int -astopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ast_softc *stp = dev->si_drv1; - - if (!stp) - return ENXIO; - - if (count_dev(dev) > 1) - return EBUSY; - - atapi_test_ready(stp->device); - - if (stp->cap.lock) - ast_prevent_allow(stp, 1); - - if (ast_sense(stp)) - ata_prtdev(stp->device, "sense media type failed\n"); - - stp->device->flags &= ~ATA_D_MEDIA_CHANGED; - stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN); - ast_total = 0; - return 0; -} - -static int -astclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ast_softc *stp = dev->si_drv1; - - /* flush buffers, some drives fail here, they should report ctl = 0 */ - if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN)) - ast_write_filemark(stp, 0); - - /* write filemark if data written to tape */ - if (!(stp->flags & F_ONSTREAM) && - (stp->flags & (F_DATA_WRITTEN | F_FM_WRITTEN)) == F_DATA_WRITTEN) - ast_write_filemark(stp, WF_WRITE); - - /* if minor is even rewind on close */ - if (!(minor(dev) & 0x01)) - ast_rewind(stp); - - if (stp->cap.lock && count_dev(dev) == 1) - ast_prevent_allow(stp, 0); - - stp->flags &= F_CTL_WARN; -#ifdef AST_DEBUG - ata_prtdev(stp->device, "%llu total bytes transferred\n", ast_total); -#endif - return 0; -} - -static int -astioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct ast_softc *stp = dev->si_drv1; - int error = 0; - - switch (ap->a_cmd) { - case MTIOCGET: - { - struct mtget *g = (struct mtget *) ap->a_data; - - bzero(g, sizeof(struct mtget)); - g->mt_type = 7; - g->mt_density = 1; - g->mt_blksiz = stp->blksize; - g->mt_comp = stp->cap.compress; - g->mt_density0 = 0; g->mt_density1 = 0; - g->mt_density2 = 0; g->mt_density3 = 0; - g->mt_blksiz0 = 0; g->mt_blksiz1 = 0; - g->mt_blksiz2 = 0; g->mt_blksiz3 = 0; - g->mt_comp0 = 0; g->mt_comp1 = 0; - g->mt_comp2 = 0; g->mt_comp3 = 0; - break; - } - case MTIOCTOP: - { - int i; - struct mtop *mt = (struct mtop *)ap->a_data; - - switch ((int16_t) (mt->mt_op)) { - - case MTWEOF: - for (i=0; i < mt->mt_count && !error; i++) - error = ast_write_filemark(stp, WF_WRITE); - break; - - case MTFSF: - if (mt->mt_count) - error = ast_space(stp, SP_FM, mt->mt_count); - break; - - case MTBSF: - if (mt->mt_count) - error = ast_space(stp, SP_FM, -(mt->mt_count)); - break; - - case MTREW: - error = ast_rewind(stp); - break; - - case MTOFFL: - error = ast_load_unload(stp, SS_EJECT); - break; - - case MTNOP: - error = ast_write_filemark(stp, 0); - break; - - case MTERASE: - error = ast_erase(stp); - break; - - case MTEOD: - error = ast_space(stp, SP_EOD, 0); - break; - - case MTRETENS: - error = ast_load_unload(stp, SS_RETENSION | SS_LOAD); - break; - - case MTFSR: - case MTBSR: - case MTCACHE: - case MTNOCACHE: - case MTSETBSIZ: - case MTSETDNSTY: - case MTCOMP: - default: - error = EINVAL; - } - break; - } - case MTIOCRDSPOS: - { - struct ast_readposition position; - - if ((error = ast_read_position(stp, 0, &position))) - break; - *(u_int32_t *)ap->a_data = position.tape; - break; - } - case MTIOCRDHPOS: - { - struct ast_readposition position; - - if ((error = ast_read_position(stp, 1, &position))) - break; - *(u_int32_t *)ap->a_data = position.tape; - break; - } - case MTIOCSLOCATE: - error = ast_locate(stp, 0, *(u_int32_t *)ap->a_data); - break; - case MTIOCHLOCATE: - error = ast_locate(stp, 1, *(u_int32_t *)ap->a_data); - break; - default: - error = ENOTTY; - } - return error; -} - -static int -aststrategy(struct dev_strategy_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct bio *bio = ap->a_bio; - struct buf *bp = bio->bio_buf; - struct ast_softc *stp = dev->si_drv1; - - if (stp->device->flags & ATA_D_DETACHING) { - bp->b_flags |= B_ERROR; - bp->b_error = ENXIO; - biodone(bio); - return(0); - } - - /* if it's a null transfer, return immediatly. */ - if (bp->b_bcount == 0) { - bp->b_resid = 0; - biodone(bio); - return(0); - } - if (bp->b_cmd != BUF_CMD_READ && (stp->flags & F_WRITEPROTECT)) { - bp->b_flags |= B_ERROR; - bp->b_error = EPERM; - biodone(bio); - return(0); - } - - /* check for != blocksize requests */ - if (bp->b_bcount % stp->blksize) { - ata_prtdev(stp->device, "transfers must be multiple of %d\n", - stp->blksize); - bp->b_flags |= B_ERROR; - bp->b_error = EIO; - biodone(bio); - return(0); - } - - /* warn about transfers bigger than the device suggests */ - if (bp->b_bcount > stp->blksize * stp->cap.ctl) { - if ((stp->flags & F_CTL_WARN) == 0) { - ata_prtdev(stp->device, "WARNING: CTL exceeded %d > %d\n", - bp->b_bcount, stp->blksize * stp->cap.ctl); - stp->flags |= F_CTL_WARN; - } - } - - crit_enter(); - bioq_insert_tail(&stp->bio_queue, bio); - crit_exit(); - ata_start(stp->device->channel); - return(0); -} - -void -ast_start(struct ata_device *atadev) -{ - struct ast_softc *stp = atadev->driver; - struct bio *bio = bioq_first(&stp->bio_queue); - struct buf *bp; - u_int32_t blkcount; - int8_t ccb[16]; - - if (bio == NULL) - return; - bzero(ccb, sizeof(ccb)); - - bp = bio->bio_buf; - if (bp->b_cmd == BUF_CMD_READ) - ccb[0] = ATAPI_READ; - else - ccb[0] = ATAPI_WRITE; - - bioq_remove(&stp->bio_queue, bio); - blkcount = bp->b_bcount / stp->blksize; - - ccb[1] = 1; - ccb[2] = blkcount>>16; - ccb[3] = blkcount>>8; - ccb[4] = blkcount; - - devstat_start_transaction(&stp->stats); - - atapi_queue_cmd(stp->device, ccb, bp->b_data, blkcount * stp->blksize, - ((bp->b_cmd == BUF_CMD_READ) ? ATPR_F_READ : 0), - 120, ast_done, bio); -} - -static int -ast_done(struct atapi_request *request) -{ - struct bio *bio = request->driver; - struct buf *bp = bio->bio_buf; - struct ast_softc *stp = request->device->driver; - - if (request->error) { - bp->b_error = request->error; - bp->b_flags |= B_ERROR; - } else { - if (bp->b_cmd != BUF_CMD_READ) - stp->flags |= F_DATA_WRITTEN; - bp->b_resid = bp->b_bcount - request->donecount; - ast_total += (bp->b_bcount - bp->b_resid); - } - devstat_end_transaction_buf(&stp->stats, bp); - biodone(bio); - return 0; -} - -static int -ast_mode_sense(struct ast_softc *stp, int page, void *pagebuf, int pagesize) -{ - int8_t ccb[16] = { ATAPI_MODE_SENSE, 0x08, page, pagesize>>8, pagesize, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - error = atapi_queue_cmd(stp->device, ccb, pagebuf, pagesize, ATPR_F_READ, - 10, NULL, NULL); -#ifdef AST_DEBUG - atapi_dump("ast: mode sense ", pagebuf, pagesize); -#endif - return error; -} - -static int -ast_mode_select(struct ast_softc *stp, void *pagebuf, int pagesize) -{ - int8_t ccb[16] = { ATAPI_MODE_SELECT, 0x10, 0, pagesize>>8, pagesize, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -#ifdef AST_DEBUG - ata_prtdev(stp->device, "modeselect pagesize=%d\n", pagesize); - atapi_dump("mode select ", pagebuf, pagesize); -#endif - return atapi_queue_cmd(stp->device, ccb, pagebuf, pagesize, 0, - 10, NULL, NULL); -} - -static int -ast_write_filemark(struct ast_softc *stp, u_int8_t function) -{ - int8_t ccb[16] = { ATAPI_WEOF, 0x01, 0, 0, function, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - if (stp->flags & F_ONSTREAM) - ccb[4] = 0x00; /* only flush buffers supported */ - else { - if (function) { - if (stp->flags & F_FM_WRITTEN) - stp->flags &= ~F_DATA_WRITTEN; - else - stp->flags |= F_FM_WRITTEN; - } - } - error = atapi_queue_cmd(stp->device, ccb, NULL, 0, 0, 10, NULL, NULL); - if (error) - return error; - return atapi_wait_dsc(stp->device, 10*60); -} - -static int -ast_read_position(struct ast_softc *stp, int hard, - struct ast_readposition *position) -{ - int8_t ccb[16] = { ATAPI_READ_POSITION, (hard ? 0x01 : 0), 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - error = atapi_queue_cmd(stp->device, ccb, (caddr_t)position, - sizeof(struct ast_readposition), ATPR_F_READ, 10, - NULL, NULL); - position->tape = ntohl(position->tape); - position->host = ntohl(position->host); - return error; -} - -static int -ast_space(struct ast_softc *stp, u_int8_t function, int32_t count) -{ - int8_t ccb[16] = { ATAPI_SPACE, function, count>>16, count>>8, count, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(stp->device, ccb, NULL, 0, 0, 60*60, NULL, NULL); -} - -static int -ast_locate(struct ast_softc *stp, int hard, u_int32_t pos) -{ - int8_t ccb[16] = { ATAPI_LOCATE, 0x01 | (hard ? 0x4 : 0), 0, - pos>>24, pos>>16, pos>>8, pos, - 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - error = atapi_queue_cmd(stp->device, ccb, NULL, 0, 0, 10, NULL, NULL); - if (error) - return error; - return atapi_wait_dsc(stp->device, 60*60); -} - -static int -ast_prevent_allow(struct ast_softc *stp, int lock) -{ - int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - return atapi_queue_cmd(stp->device, ccb, NULL, 0, 0,30, NULL, NULL); -} - -static int -ast_load_unload(struct ast_softc *stp, u_int8_t function) -{ - int8_t ccb[16] = { ATAPI_START_STOP, 0x01, 0, 0, function, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - if ((function & SS_EJECT) && !stp->cap.eject) - return 0; - error = atapi_queue_cmd(stp->device, ccb, NULL, 0, 0, 10, NULL, NULL); - if (error) - return error; - tsleep((caddr_t)&error, 0, "astlu", 1 * hz); - if (function == SS_EJECT) - return 0; - return atapi_wait_dsc(stp->device, 60*60); -} - -static int -ast_rewind(struct ast_softc *stp) -{ - int8_t ccb[16] = { ATAPI_REZERO, 0x01, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - error = atapi_queue_cmd(stp->device, ccb, NULL, 0, 0, 10, NULL, NULL); - if (error) - return error; - return atapi_wait_dsc(stp->device, 60*60); -} - -static int -ast_erase(struct ast_softc *stp) -{ - int8_t ccb[16] = { ATAPI_ERASE, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }; - int error; - - if ((error = ast_rewind(stp))) - return error; - - return atapi_queue_cmd(stp->device, ccb, NULL, 0, 0, 60*60, NULL, NULL); -} diff --git a/sys/dev/disk/ata/atapi-tape.h b/sys/dev/disk/ata/atapi-tape.h deleted file mode 100644 index 8324343e22..0000000000 --- a/sys/dev/disk/ata/atapi-tape.h +++ /dev/null @@ -1,162 +0,0 @@ -/*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/dev/ata/atapi-tape.h,v 1.11.2.5 2002/03/18 08:37:34 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-tape.h,v 1.4 2006/02/17 19:17:54 dillon Exp $ - */ - -/* ATAPI tape drive Capabilities and Mechanical Status Page */ -struct ast_cappage { - /* mode page data header */ - u_int8_t data_length; /* total length of data */ - u_int8_t medium_type; /* medium type (if any) */ - u_int8_t reserved :4; - u_int8_t mode :3; /* buffering mode */ - u_int8_t write_protect :1; /* media is writeprotected */ - u_int8_t blk_desc_len; /* block Descriptor Length */ - - /* capabilities page */ - u_int8_t page_code :6; -#define ATAPI_TAPE_CAP_PAGE 0x2a - - u_int8_t reserved0_6 :1; - u_int8_t ps :1; /* parameters saveable */ - u_int8_t page_length; /* page Length == 0x12 */ - u_int8_t reserved2; - u_int8_t reserved3; - u_int8_t readonly :1; /* read Only Mode */ - u_int8_t reserved4_1234 :4; - u_int8_t reverse :1; /* supports reverse direction */ - u_int8_t reserved4_67 :2; - u_int8_t reserved5_012 :3; - u_int8_t eformat :1; /* supports ERASE formatting */ - u_int8_t reserved5_4 :1; - u_int8_t qfa :1; /* supports QFA formats */ - u_int8_t reserved5_67 :2; - u_int8_t lock :1; /* supports locking media */ - u_int8_t locked :1; /* the media is locked */ - u_int8_t prevent :1; /* defaults to prevent state */ - u_int8_t eject :1; /* supports eject */ - u_int8_t disconnect :1; /* can break request > ctl */ - u_int8_t reserved6_5 :1; - u_int8_t ecc :1; /* supports error correction */ - u_int8_t compress :1; /* supports data compression */ - u_int8_t reserved7_0 :1; - u_int8_t blk512 :1; /* supports 512b block size */ - u_int8_t blk1024 :1; /* supports 1024b block size */ - u_int8_t reserved7_3456 :4; - u_int8_t blk32k :1; /* supports 32kb block size */ - u_int16_t max_speed; /* supported speed in KBps */ - u_int16_t max_defects; /* max stored defect entries */ - u_int16_t ctl; /* continuous transfer limit */ - u_int16_t speed; /* current Speed, in KBps */ - u_int16_t buffer_size; /* buffer Size, in 512 bytes */ - u_int8_t reserved18; - u_int8_t reserved19; -}; - -/* ATAPI OnStream ADR data transfer mode page (ADR unique) */ -struct ast_transferpage { - /* mode page data header */ - u_int8_t data_length; /* total length of data */ - u_int8_t medium_type; /* medium type (if any) */ - u_int8_t dsp; /* device specific parameter */ - u_int8_t blk_desc_len; /* block Descriptor Length */ - - /* data transfer page */ - u_int8_t page_code :6; -#define ATAPI_TAPE_TRANSFER_PAGE 0x30 - - u_int8_t reserved0_6 :1; - u_int8_t ps :1; /* parameters saveable */ - u_int8_t page_length; /* page Length == 0x02 */ - u_int8_t reserved2; - u_int8_t read32k :1; /* 32k blk size (data only) */ - u_int8_t read32k5 :1; /* 32.5k blk size (data&AUX) */ - u_int8_t reserved3_23 :2; - u_int8_t write32k :1; /* 32k blk size (data only) */ - u_int8_t write32k5 :1; /* 32.5k blk size (data&AUX) */ - u_int8_t reserved3_6 :1; - u_int8_t streaming :1; /* streaming mode enable */ -}; - -/* ATAPI OnStream ADR vendor identification mode page (ADR unique) */ -struct ast_identifypage { - /* mode page data header */ - u_int8_t data_length; /* total length of data */ - u_int8_t medium_type; /* medium type (if any) */ - u_int8_t dsp; /* device specific parameter */ - u_int8_t blk_desc_len; /* block Descriptor Length */ - - /* data transfer page */ - u_int8_t page_code :6; -#define ATAPI_TAPE_IDENTIFY_PAGE 0x36 - - u_int8_t reserved0_6 :1; - u_int8_t ps :1; /* parameters saveable */ - u_int8_t page_length; /* page Length == 0x06 */ - u_int8_t ident[4]; /* host id string */ - u_int8_t reserved6; - u_int8_t reserved7; -}; - -/* ATAPI read position structure */ -struct ast_readposition { - u_int8_t reserved0_05 :6; - u_int8_t eop :1; /* end of partition */ - u_int8_t bop :1; /* beginning of partition */ - u_int8_t reserved1; - u_int8_t reserved2; - u_int8_t reserved3; - u_int32_t host; /* frame address in buffer */ - u_int32_t tape; /* frame address on tape */ - u_int8_t reserved12; - u_int8_t reserved13; - u_int8_t reserved14; - u_int8_t blks_in_buf; /* blocks in buffer */ - u_int8_t reserved16; - u_int8_t reserved17; - u_int8_t reserved18; - u_int8_t reserved19; -}; - -struct ast_softc { - struct ata_device *device; /* device softc */ - int lun; /* logical device unit */ - int flags; /* device state flags */ -#define F_CTL_WARN 0x0001 /* warned about CTL wrong? */ -#define F_WRITEPROTECT 0x0002 /* media is writeprotected */ -#define F_DATA_WRITTEN 0x0004 /* data has been written */ -#define F_FM_WRITTEN 0x0008 /* filemark has been written */ -#define F_ONSTREAM 0x0100 /* OnStream ADR device */ - - int blksize; /* block size (512 | 1024) */ - struct bio_queue_head bio_queue; /* queue of i/o requests */ - struct atapi_params *param; /* drive parameters table */ - struct ast_cappage cap; /* capabilities page info */ - struct devstat stats; /* devstat entry */ -}; -- 2.41.0